Skip to content

Docs code samples the current @objectstack/spec refuses: the remaining view fragments in build/interface/views.mdx and the send_email flow action in build/automation/flows.mdx #307

Description

@objectstack-fleet

Found while #301 was staged on 2026-10-06. #301 rewrites the two declaration samples in views.mdx to the defineView form and parse-checks them against @objectstack/spec 17.6.0 from npm. The same check, run on the samples #301 did not touch, finds more that do not work. Priority: P2. A reader who copies these gets a schema error.

Findings

  1. build/interface/views.mdx, the remaining fragments.
    • The Kanban, Calendar, Gantt and other fragments omit the top-level columns that every list view requires.
    • "Common list options" sets fontWeight: 600, but the spec wants a string.
    • Wrapped as list views with data, spec 17.6.0 refuses each one.
    • Source: objectstack origin/main packages/spec/src/ui/view.zod.ts (ViewSchema; kanban.columns is required at about :1809).
  2. build/automation/flows.mdx:54,250. These use action: 'send_email', which is not in FlowNodeAction. This was inferred by reading the code and has not been run.

Done looks like

Order

After #301 lands. Consider whether a docs-sample parse gate is worth adding; propose it in the PR rather than building it unasked.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop, repo:objectos seat
    Session: session_01FeA1nwBz1ohH65dvffUGKr
    Account: hotlong (the seat's linked user, as GET /user answers it; always the card's assignee)
    Branch: claude/pm-dispatch-objectos-ju9td1, the session's one designated push branch. #301 has landed (PR #310, 5d2f837). This card is staged on a local branch cut from origin/main @ 5d2f837 and pushed after #311 and #305.
    Worktree: objectos-issue-307
    Domain: n/a (single-lane repo)
    Seat: repo:objectos (objectstack-ai/objectstack#9831)
    File surface:

    A proposed docs-sample parse gate goes in the PR body as a proposal; it is not built unasked.
    Stop on breach and explain in the report.
    Container & model: M, mode:subagent, model: default.
    Clause-②: no
    Thread-read: none
    Serial constraints cleared: no. Pushes are serial on the one branch: #311 → #305 → this card → #308 → #312.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 307,
     "status": "staged",
     "branch": "staged/issue-307",
     "worktree": "/home/user/objectos-issue-307",
     "base": "5d2f837 (origin/main at cut, #310, as the claim states). origin/main is now cf449fa (#313, #314); git merge-tree --write-tree origin/main HEAD is clean (tree 0087435), and no path is shared.",
     "final_commit": "4d12d0a48e2f397ca90c77177ab13761563841fa",
     "commits": ["4d12d0a docs: make the views and flows code samples parse with @objectstack/spec 17.7.0"],
     "pr": null,
     "pr_body_draft": "/tmp/claude-0/-home-user/2224823d-3484-535e-94a5-c071ba6af395/scratchpad/issue-307/pr-body.md (first line: Fixes #307)",
     "session": "session_01FeA1nwBz1ohH65dvffUGKr — parent PM seat's id (subagent)",
     "premise_still_valid": true,
     "summary": "Every code sample on both pages now parses with @objectstack/spec 17.7.0, the npm latest published 2026-10-06T12:22Z and versioned at objectstack 4e4e8814. views.mdx: Kanban, Calendar, Gantt, Tree and Chart get their required top-level columns; fontWeight becomes '600'; each fragment says it omits the container and data; the List view types table now states the required keys the spec declares. flows.mdx: finding 2 held only in part. send_email is not a FlowNodeAction value, but FlowNodeAction does not gate node type at parse (ADR-0018). What defineFlow refused was the whole old sample shape (trigger, steps, inputs, manual and scheduled types), so every flow sample is rewritten to FlowSchema's nodes and edges. Email goes through a notify node with channels: ['email'] (NotifyConfigSchema), and requires is ['automation', 'triggers'], because defineStack refuses ['automation'] alone. The prose that described the old shape was rewritten against public objectstack sources.",
     "files_changed": [
      "content/docs/build/interface/views.mdx (+32 −12)",
      "content/docs/build/automation/flows.mdx (+250 −110)"
     ],
     "parse_table": {
      "method": "As in #301: extract the published fenced blocks and evaluate them with only TS syntax removed (import, export, as const). Wraps: a defineView, defineFlow or defineStack block as written; a single-view fragment three ways (ListViewSchema or FormViewSchema; defineView with the fragment as list or form; and with the omitted data supplied as a listViews entry); fragments of flow keys wrapped with the nodes their comment names. Every builtin node of every flow is also parsed against its executor contract (getBuiltinNodeConfigContracts), which is stricter than defineFlow's presence-only check. A curl to the trigger route is checked against AutomationApiContracts.triggerFlow and TriggerFlowRequestSchema. CEL strings get the slot-shape check only: the spec ships no CEL parser. Scripts: scratchpad issue-307/spec-check/scripts/{extract,views-check,flows-check,controls}.mjs.",
      "views_before_5d2f837": "9 pass, 18 fail. Blocks 1-3 (#301 containers and registration) PASS. Block 4, common options @114: FAIL x3, conditionalFormatting.0.style.fontWeight: expected string, received number. Blocks 5-9 (kanban @146, calendar @165, gantt @179, tree @194, chart @215): FAIL x3 each, columns: invalid_union (required). Blocks 10-11, forms: PASS x3.",
      "views_after_4d12d0a": "27 pass, 0 fail. Every block PASS; each fragment is PASS x3 (@121, 154, 175, 191, 208, 231, 260, 277).",
      "flows_before_5d2f837": "13 pass, 6 fail, 2 n/a. Block 1, defineStack @22: PASS alone, but no page flow parsed, so requires was never judged. Block 2, welcome @40: FAIL, label, nodes and edges missing, unrecognized trigger and steps. Block 3, nightly @86: FAIL, type 'scheduled' invalid, unrecognized schedule and steps. Block 4, renewal @121: FAIL, label missing on the flow, nodes.0 and nodes.2. Block 5, timeRelative fragments @163: PASS x6. Block 6, approve @187: FAIL, type 'manual' invalid, unrecognized inputs and steps. Block 7, curl @208: N/A, the action door. Block 8, condition @230: FAIL, no id or label, unrecognized when, then and else. Block 9, error handling @247: FAIL, no id or label, unrecognized action, inputs, retry and onError. Block 10, CEL @268: slot shape only x3. Block 11, os test --scenario @286: N/A.",
      "flows_after_4d12d0a": "27 pass, 0 fail, 1 n/a. Block 1 @27: PASS alone, and PASS with all 5 page flows. Blocks 2, 3, 4, 6 and 8 (@51, 123, 176, 252, 320): defineFlow PASS and executor contracts PASS. Block 5 @226: PASS x6. Block 7, curl @286: PASS x4 (the route equals triggerFlow, the flow is on the page, the body parses, and the params are declared isInput). Block 9 @365: PASS, wrapped with charge_card, mark_paid and flag_for_review, plus contracts. Block 10 @395: slot shape x3. Block 11, os test @418: N/A.",
      "refusal_controls": "28 of 28 hold, EXIT 0. The kanban without top-level columns is FAIL. fontWeight 600 is FAIL and '600' is PASS. A chart without values is FAIL. kanban without its own columns is FAIL. A calendar without startDateField is FAIL; with startDateField only it is PASS. The misspelling colums is FAIL (the parse is strict). requires ['automation'] with a record_change flow is FAIL; with 'triggers' added it is PASS. The old trigger/steps shape is FAIL. A node of type send_email is PASS (ADR-0018), but FlowNodeAction.parse('send_email') is FAIL, and a node with action: 'send_email' is FAIL. notify with neither title nor template is FAIL. notify with subject/body is PASS under defineFlow and FAIL under the executor contract. strategy 'retry' with no maxRetries is FAIL. onError 'rollback' is FAIL. Per-node retry and onError are FAIL. A fault edge spelled as a label is PASS (an ordinary edge). type manual and type scheduled are FAIL. offsetDays together with withinDays is FAIL. The old body {inputs} parses with inputs dropped (TriggerFlowRequestSchema is not strict). update_record with filters is FAIL.",
      "page_text_ablation": "Run on scratch copies only. Deleting the kanban's top-level columns line (anchor count 1 to 0) turns views-check red: EXIT 1, block 5 FAIL x3. Setting requires back to ['automation'] (mutant marker 1, anchor 0) turns flows-check red: EXIT 1, defineStack refuses the 4 flows with triggers."
     },
     "ruling_a": "views.mdx keeps its 7 siblings (de, es, fr, ja, ko, zh-Hans, zh-Hant). The change is code shape only: required columns added, fontWeight retyped, the table's required-key lists corrected. No view type, key or capability is removed. The siblings were already stale at base (zh-Hans source_sha 7fe2a7f… against base English 4616870…, after #301's change), and freshness counts are unchanged at zh-Hans 47 and others 24. flows.mdx does remove or reverse capability assertions, so ruling A applies, but there are no siblings left to delete: PR #310 (5d2f837) deleted all 7 under ruling A (git log --diff-filter=D gives 5d2f837). The assertions removed or reversed: the send_email action; before-flows mutating the record (ObjectStack: a before hook does that); the rollback error mode; the manual type; os test --scenario; the {!org.FIELD} interpolation; and 'failed runs land in the job retry queue'.",
     "gates": [
      "type-check: pnpm turbo run type-check --continue --force (lock). VERDICT command-exit 0, '✓ Types generated successfully', 1 successful, 0 cached.",
      "build: NEXT_PRIVATE_STANDALONE=true pnpm turbo run build --force (lock). VERDICT command-exit 0, 1 successful, 0 cached. The log's 'Failed to load dynamic font … self-signed certificate' lines are OG-image font fetches that this container's egress blocks; they are non-fatal.",
      "test: pnpm turbo run test --force (lock). VERDICT command-exit 0, '✓ 10 self-test(s) passed'.",
      "check-locale-surface: EXIT 0, '✓ every advertised URL has a source file and every source file is advertised; …'.",
      "check-positioning: EXIT 0, '✓ positioning: 4 copies equal their constants; the brand is right in 659 pages and 2 llms bodies; no stale sentence in 79 English sources …'.",
      "check-search-locales: EXIT 0, '✓ search locales: all 8 locales answer 200, find \"permissions\", find every own page by its title within the first 3 pages, and find nothing for a nonce'.",
      "gen-zh-hant --check: EXIT 0, '✓ zh-Hant: 60 generated file(s) match the zh-Hans sources byte for byte.'",
      "ownership with the workflow argv (git diff --name-status --no-renames origin/main...HEAD), --actor hotlong, TRANSLATION_BOT_LOGIN set: EXIT 0, '✓ 2 file(s) changed, no translation artifacts touched.' Control with the bot as actor: EXIT 1.",
      "check-translations: EXIT 0, '✓ translations gate passed'. Stale is reported only: zh-Hans 47, others 24, unchanged from base.",
      "check-translation-output --self-test: EXIT 0. --files: EXIT 0, '✓ translation output gate passed (256 pre-existing finding(s) reported)'.",
      "check-node-floor, --self-test and run: EXIT 0. check-half-states --self-test: EXIT 0, '1551 cases pass'.",
      "Control bytes in the 2 changed files: 0."
     ],
     "screenshots": "/tmp/claude-0/-home-user/2224823d-3484-535e-94a5-c071ba6af395/scratchpad/issue-307/shots/after/: after-{views,flows}-{1440,390}.png are full-page; clips/ holds the tables and the long code blocks; after-report.json holds the measurements. next start served the build on :3307, and Chromium loaded both pages at both widths: HTTP 200, the right h1, 11 code blocks each. scrollWidth equals the viewport (1440/1440 and 390/390). Every code box sits inside the viewport (17-373 px at 390), and long lines scroll inside their box (overflow-x: auto). I looked at the views table, the flow types table, and the kanban, common-options, ticket-email, nightly-cleanup and error-handling blocks: none overflows the layout. The server I started (pids 9696, 9753, 9775) is stopped, and :3307 no longer answers.",
     "tests": "Parse checks before and after, on 5d2f837 and 4d12d0a: views 9/18 to 27/0, flows 13/6/2 to 27/0/1. 28 of 28 refusal controls hold. Two page-text ablations turn the checker red (EXIT 1). Every gate above ran at 4d12d0a with a clean worktree afterwards (git status empty).",
     "deviations": [
      "Spec 17.7.0, the latest, not #301's 17.6.0. #301's two container samples re-parse PASS on 17.7.0.",
      "flows.mdx is a full-sample rewrite, not only the send_email action. Measured, every flow sample except the timeRelative fragments was refused for its shape, and the Done criterion asks for every sample to parse. Prose rewritten where it described the old shape: the flow types table, the trigger timing table, step types to node types, error handling, the CEL samples and the testing command.",
      "Bounded same-class fixes in place on the two pages: the views table's required keys (under-required kanban.columns and chart.values; over-required gallery, calendar titleField, map and tree); requires gains 'triggers'; the curl moves to the canonical trigger route with params; os test --scenario becomes a test-file argument, because --scenario is not a flag; the CEL has() sample becomes isBlank; duration(\"30d\") is dropped.",
      "The welcome-email sample's object changes from sys_user to support_ticket: nothing public says a record-change flow fires on sys_user.",
      "Two short pointers to ObjectStack's public docs are added: Hooks vs flows, and The acting organization for time-triggered flows.",
      "Commit trailer is the model-free pair (Co-Authored-By: Claude, Claude-Session), per the agent contract and the sibling staged branches. The harness reminder asked for a model-named Co-Authored-By. The unpushed commit was amended once to fix this.",
      "NOT MEASURED: the live resolution of the docs.objectstack.ai links (egress CONNECT 403). The anchors are derived from public source headings that ObjectStack's own pages link to.",
      "NOT MEASURED: email delivery on a running ObjectOS runtime. The claim rests on the published spec and objectos's own Email and Notifications pages.",
      "Lock waits on a shared box: the build waited 533 s and held the lock 74 s; the test waited 226 s."
     ],
     "mcp_calls": "0",
     "api_writes": "1 — this os-dev-report comment (POST /repos/objectstack-ai/objectos/issues/307/comments, through the scripts/pm/fleet-write relay). Nothing pushed, no PR, no labels.",
     "open_questions": [],
     "out_of_scope_findings": [
      "class: c · reach: named producer — public objectos docs pages, measured on @objectstack/spec 17.7.0: build/automation/workflows.mdx:104 defineFlow refused (label missing on the flow, nodes.0 and nodes.3); build/automation/approvals.mdx:216 defineFlow refused (nodes.0.label and nodes.4.label missing); build/interface/actions.mdx:119 defineView refused (unrecognized key actions), and its lines 63 and 127-133 show the old {type:'action', action, inputs, record} step; reference/cel.mdx shows the 'Flow guard' {when: P…} step. Same family as #301 and #307: name these pages in one family close-out card rather than filing them one by one. The parse gate proposed in the PR body would hold the family closed · dedupe words: docs sample parse defineFlow label workflows approvals actions defineView",
      "carrier: none · noted, not filed — views.mdx keeps three spellings that are legacy but still accepted: exportOptions as a bare array (lifts to {formats}), filterableFields ('legacy shorthand — prefer userFilters'), and visibleOn in the Visibility bullet and See also (deprecated in favour of visibleWhen, normalized at parse). They parse, so they are not this defect class.",
      "carrier: none · noted, not filed — objectstack packages/spec/src/api/automation-api.zod.ts:207: TriggerFlowRequestSchema is not strict, so a trigger body that says inputs where it means params parses and drops it. It is a wire request body, not stored metadata, so it is not class c."
     ]
    }

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR #315 on head 69f7f1ed25d0914d7c7e98a6b9c0a0f0898d9489 · 2026-10-06T16:27Z. I am landing it now: no governed path is touched, and every check is green.

    Path surface (get_files): 2 English pages, +282/−122: content/docs/build/interface/views.mdx and content/docs/build/automation/flows.mdx. No locale file, app code or script.

    Checks on 69f7f1e: build, Ownership & freshness and Node floor succeeded; Deploy docs was skipped. mergeable_state is clean on base cf449fa.

    Push: fast-forward with no force. ff/issue-307 starts at the remote branch head 41a1994, merges origin/main @ cf449fa (the diff against main is then empty), and cherry-picks 4d12d0a. git diff origin/main 69f7f1e is byte-identical to git diff 5d2f837 4d12d0a.

    Review:

    Follow-up filed: #316 covers the same family on workflows, approvals, actions and cel, plus the docs-sample parse gate that #307's PR body proposes. It is staged now.

    After merge: watch the deploy verdict and smoke, then post the landed note here. #308 is next on the branch.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed and live · 2026-10-06T16:37Z


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions