Skip to content

docs(agents): describe the flow authoring form the repo actually uses - #1572

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-1436-agents-md-flow-authoring-form
Sep 5, 2026
Merged

docs(agents): describe the flow authoring form the repo actually uses#1572
os-zhuang merged 1 commit into
mainfrom
claude/issue-1436-agents-md-flow-authoring-form

Conversation

@os-musk

@os-musk os-musk commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Fixes #1436

AGENTS.md item 3 of §🔒 Schema Validation Requirements told authors to build flows with FlowSchema.parse() from @objectstack/spec/automation, adding that defineFlow() is that call. Neither appears anywhere in src/. This replaces the prescription with the form the repo actually uses, and says where validation really happens.

⚠️ The card's line number :147 is stale — the line is :171, shifted by PR #1527. Confirmed independently on my base.

What I measured

Base: origin/main @ 18444c8. Gate chain re-run at head 4525acc.

The card's three possibilities, distinguished against the installed tarball rather than the docs — which the card asked for specifically, since this lane keeps inheriting claims about the platform from in-repo prose. @objectstack/spec 17.2.0 exports both, as functions:

FlowSchema present: true   function   (has .parse: function)
defineFlow present: true   function

and the implementation in dist/automation/index.js:

function defineFlow(config) {
  return FlowSchema.parse(config);
}

⇒ The API is real and the parenthetical was accurate. "Invented prose, delete it" was the wrong fix. This is the card's possibility 1: aspirational.

What the repo does instead. All 22 src/flows/*.flow.ts files take a type-only import and annotate a plain object literal — checked against a real file, not the type signature, per the card:

// src/flows/campaign-completion.flow.ts
import type * as Automation from '@objectstack/spec/automation';
type Flow = Automation.Flow;
export const CampaignCompletionFlow: Flow = { name: 'campaign_completion',};
import type * as Automation …   → 22 of 22 flow files
defineFlow | FlowSchema in src/ → 0
Automation.Flow in src/         → 22   ← the card's own control

Why this is the honest direction, and not "the repo is behind". The card's alternative branch was: if the wrapper is the preferred authoring form, correct the repo instead of the instruction. I found no preference signal, and two signals against it:

  1. The spec publishes Flow as the schema's input type (z.input of FlowSchema) — exported precisely so a literal can be annotated with it. There is no deprecation on the literal form.
  2. defineFlow() returns FlowParsed (z.infer, the output type), so the two are not interchangeable drop-ins — const X: Flow = defineFlow({…}) mixes the two sides of the schema.

Also decisive: AGENTS.md already described the literal form correctly one section earlier, in the File Suffix Protocol (:153, "typed as Automation.Flow"). The two sections disagreed with each other; :153 matched the code.

That nothing goes unvalidated is confirmed by ablation, not assumed. The card's own defect is asserting a validation path that does not exist, so the replacement wording had to be checked. With one flow's type mutated to a bogus value on disk:

line 19 now:   type: 'os_probe_bogus_type',
MUTATION CONFIRMED ON THE CODE LINE
MUTATED validate exit: 1
  ✗ defineStack validation failed (1 issue):
  ✗ flows.17.type: Invalid value 'os_probe_bogus_type'. Expected one of:
    autolaunched, record_change, schedule, screen, api.

and on the restored tree pnpm validate exits 0. Restore proven byte-identical (git diff HEAD empty; blob daa4237 both sides).

⚠️ My first attempt at this probe was a no-op and is reported as such: grep -c counts lines, and the first occurrence of type: 'schedule' in that file is inside the JSDoc comment at :11, so perl mutated prose and validate passed. Re-anchored on the code line (:19, trailing comma). The green from attempt 1 was void, not evidence.

⇒ Validation is real; it happens at objectstack validate and again when the platform parses at AutomationEngine.registerFlow on boot — not in the metadata file.

Gates

pnpm verify at 4525accexit 0, all eight in the chain:

✓ Validation passed (2203ms)          validate
(clean)                               typecheck
✓ i18n lint gate: 0 i18n/missing-*    lint + lint:i18n-gate
✓ source hygiene clean                hygiene
✓ source token ratchet clean          hygiene:tokens
   authored total ~135,444 (ceiling ~140,000)
✓ Build complete (1498ms)             build
Test Files  160 passed (160)          test
     Tests  3391 passed | 1 skipped (3392)

Scope

AGENTS.md item 3 only, plus the changeset this PR adds. No src/ change.

⛔ I did not sweep the other six items of that list, and ⛔ I added no guard, gate, lint rule or test — per AGENTS.md Scope rule 3, a validation-class gap is a platform problem that goes upstream, not a local guard.

The section-wide problem is real and measured, and is filed as its own card, back-linked. One correction to the dispatch brief's sweep, reported because it was load-bearing: Schema.parse( is not confined to AGENTS.mdscripts/analytics-reconcile/run.ts:91 calls DatasetSchema.parse(ds). The section's own seven symbols are still called nowhere, so the finding holds; the stated measurement was just wider than the truth.

Landing path

AGENTS.md is a governed surface (2026-08-18 cross-repo ruling): draft PR, human merge. Opened draft and it stays draft — not marked ready, not enqueued, no auto-merge, no reviewers requested (the seat does that). Predecessor #1229 landed via PR #1527, so this card was free to run. #1443 remains fenced behind this one and is not addressed here.

Refs #1429

🤖 Generated with Claude Code

Generated by Claude Code


Generated by Claude Code

Item 3 of AGENTS.md §Schema Validation Requirements prescribed
`FlowSchema.parse()` / `defineFlow()`. Both exist in @objectstack/spec
17.2.0 (verified against the installed tarball), but neither appears
anywhere in src/: all 22 src/flows/*.flow.ts files take a type-only
import and annotate a plain object literal as `Automation.Flow`.

Replace the prescription with the house form, and say where validation
actually happens — `pnpm validate` (confirmed by ablation: a bogus flow
`type` fails it with `flows.N.type: Invalid value ...`) and the
platform's own parse at `AutomationEngine.registerFlow` on boot.

Item 3 only; the sibling items' related defect is filed separately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YDbLQQiy7ew8sdwiCQEZwC
@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
hotcrm Ignored Ignored Sep 3, 2026 4:30pm UTC

Request Review

os-musk commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

⚠️ For hotlong and os-zhuang — this is a governed PR awaiting your merge, and it reached you by ASSIGNEE rather than by a review request. The difference is a tooling failure, not a signal about the PR.

repo:hotcrm seat, session_01YDbLQQiy7ew8sdwiCQEZwC, 16:37Z.

Reviewed and ACCEPTed — the review record is on the card: #1436 (comment 5528920265). Verified against the diff and head 4525acc, ⛔ not against the agent's report.

  • 8/8 check runs completed: success on 4525acc. ⚠️ One honest caveat: this PR carries 8 checks where a recent src/ PR carried 9 — the absent one is Quality Checks, consistent with a path filter on a docs-only diff. ⛔ Not a red, but "did not run" is not "passed", so it is stated rather than smoothed over.
  • Surface: AGENTS.md +1/−1 (item 3 of §🔒 Schema Validation Requirements) plus the changeset this PR adds. No src/ change.
  • Governed (AGENTS.md, 2026-08-18 cross-repo ruling) ⇒ draft, human merge. ⛔ Not queued, ⛔ no auto-merge, ⛔ no approving review from any agent seat — the agent-approval ban outranks approver-set membership, so the merge itself is the review record.

Why you are assignees instead of requested reviewers

The protocol says push a governed PR at both authorised approvers rather than wait to be found. The update_pull_request review-request call failed twice with API rate limit already exceeded for user ID 323835826 — the seat and its dev agents share one GitHub identity and one budget, and it has been intermittently exhausted all shift. ⛔ I did not retry in a loop. Assigning you both is this lane's sanctioned fallback notification, and I am naming it so the channel is not mistaken for the content.

The review request is recorded as OWED and will be re-attempted when the budget recovers; it is listed in the round report and on the seat post (#1353). ⚠️ If you merge before then, the owed request simply becomes moot — ⛔ please do not wait for it.

What to look at, honestly

The substance is measured and I would merge it if I were permitted to. Two things a human might legitimately want changed, neither of which I treated as rework:

  1. Item 3 is now ~5 sentences on one line while its six siblings remain one-liners. The content is right and front-loads the instruction, and the section-wide follow-up (AGENTS.md §🔒 Schema Validation Requirements: all seven items prescribe an XSchema.parse() call the repo makes nowhere — item 1 names the wrong method, and the section's premise sentence is false as written #1573) will likely restructure the list — but if you prefer a trim, it is a one-line edit and a fair ask.
  2. The seven-item section is systematically wrong, not just item 3 — .parse( is called nowhere in src/, and item 1 names the wrong method on the right symbol (ObjectSchema.create(), 18 files). ⛔ Deliberately not swept here: a seven-item rewrite of a governed agent-instruction surface is its own change and may want a ruling rather than an edit. Filed as AGENTS.md §🔒 Schema Validation Requirements: all seven items prescribe an XSchema.parse() call the repo makes nowhere — item 1 names the wrong method, and the section's premise sentence is false as written #1573.

⚠️ Also on the record in the review: two measurements in my own dispatch order were wrong and this PR's author caught both — my XSchema.parse( sweep manufactured a false "only in AGENTS.md" because I piped git grep through head -8 (and AGENTS.md has exactly 8 matching lines, so it hid six other files), and my ObjectSchema.create() count of 19 was a substring match where the true call-site count is 18. Neither changes the conclusion, and the corrected numbers are the ones in #1573.

#1443 is the next link on the AGENTS.md chain and is fenced until this PR merges or closes.


Generated by Claude Code

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

Labels

documentation Improvements or additions to documentation

Projects

None yet

4 participants