Skip to content

feat(cli): lint ADR-0044 approval revise-loop footguns at compile time - #2279

Merged
os-zhuang merged 1 commit into
mainfrom
feat/lint-approval-revise-loop
Jun 24, 2026
Merged

feat(cli): lint ADR-0044 approval revise-loop footguns at compile time#2279
os-zhuang merged 1 commit into
mainfrom
feat/lint-approval-revise-loop

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

What & why

First slice of #2274 (AI Build-mode awareness of the ADR-0044 revise loop). objectstack compile's flow anti-pattern linter (lint-flow-patterns.ts) — whose stated job is to "guide the author, very often an AI generating templates, toward the robust pattern" — now catches the two send-back-for-revision shapes an approval flow most commonly gets wrong:

  • Dead-end revise — an approval node has a revise out-edge but no path loops back to it. This is a valid DAG, so registerFlowaccepts it — yet the submitter reworks the record with nowhere to resubmit. The linter is the only place that catches this footgun.
  • Un-declared revise loop — the loop returns to the approval but the closing edge isn't type: 'back', so registerFlowrejects it as an un-declared cycle. The lint fires at compile time with the specific fix ("mark the resubmit edge type: 'back'"), so the author/agent corrects it before registration.
  • maxRevisions: 0 + a revise edge — self-contradictory (send-back disabled → the branch always auto-rejects); flagged too.

Advisory warnings only — never fails the build (consistent with the existing #1874 rules). This mirrors, server-side, the client-side cycle surfacing shipped in objectui (#1958).

Scope

This is the deterministic guardrail piece of #2274 (compile-time structured feedback). The remaining #2274 work — agent prompt/few-shot, flow-builder.zod.tsback edge style, and an eval, plus the optional auto-repair — stays tracked on #2274.

Files

  • packages/cli/src/utils/lint-flow-patterns.tsscanApprovalReviseLoops() + 3 rule ids (flow-approval-revise-dead-end, -unmarked-backedge, -disabled).
  • packages/cli/src/utils/lint-flow-patterns.test.ts — 5 new cases.

Verification

  • @objectstack/cli tests: 28 passing (5 new — declared loop accepted; unmarked loop flagged; dead-end flagged; maxRevisions:0 flagged; normal approval not flagged).
  • tsc -p tsconfig.build.json clean for the changed files; eslint clean.

Refs #2274, #1770 (ADR-0044). Pairs with objectui #1954 / #1955 / #1958.

🤖 Generated with Claude Code

`objectstack compile` (lint-flow-patterns) now warns on two send-back-for-
revision shapes an AI authoring an approval flow gets wrong:
- Dead-end revise: an approval with a `revise` out-edge but no path looping
back to it — a valid DAG that `registerFlow` ACCEPTS, yet the submitter
reworks the record with nowhere to resubmit. The linter is the only place
that catches this.
- Un-declared revise loop: the loop returns to the approval but the closing
edge isn't `type: 'back'`, so `registerFlow` rejects it as an un-declared
cycle — the lint fires at compile time with the specific fix.
Also flags `maxRevisions: 0` alongside a `revise` edge (send-back disabled).
Advisory only; never fails the build. Mirrors the client-side rule shipped in
objectui (#1958).
Refs #2274, #1770 (ADR-0044).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@os-zhuang
os-zhuang merged commit 84784fc into mainJun 24, 2026
1 of 2 checks passed
@os-zhuang
os-zhuang deleted the feat/lint-approval-revise-loop branch June 24, 2026 09:46
@vercel

vercelBot commented Jun 24, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specBuildingBuildingPreview, CommentJun 24, 2026 9:46am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling size/m labels Jun 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/cli.

15 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/cloud-artifact-api.mdx(via packages/cli)
  • content/docs/concepts/implementation-status.mdx(via @objectstack/cli)
  • content/docs/concepts/packages.mdx(via @objectstack/cli)
  • content/docs/getting-started/cli.mdx(via @objectstack/cli)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/cli)
  • content/docs/guides/authentication.mdx(via @objectstack/cli)
  • content/docs/guides/client-sdk.mdx(via @objectstack/cli)
  • content/docs/guides/hook-bodies.mdx(via packages/cli)
  • content/docs/guides/packages.mdx(via @objectstack/cli)
  • content/docs/guides/project-scoping.mdx(via @objectstack/cli)
  • content/docs/guides/runtime-services/data-service.mdx(via packages/cli)
  • content/docs/guides/runtime-services/index.mdx(via packages/cli)
  • content/docs/guides/skills.mdx(via packages/cli)
  • content/docs/protocol/objectos/plugin-spec.mdx(via @objectstack/cli)
  • content/docs/protocol/objectos/realtime-protocol.mdx(via @objectstack/cli)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

os-zhuang added a commit that referenced this pull request Jun 24, 2026
… on main) (#2283)
`packages/cli/src/utils/lint-flow-patterns.test.ts:190` had an untyped `edges`
parameter (TS7006 under the build's noImplicitAny), introduced by #2279. The
TypeScript Type Check job builds the whole workspace, so this fails CI for
*every* open PR. Add the edge-array type (and an explicit approvalConfig type).
Test-only; no behavior change.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang added a commit that referenced this pull request Jun 24, 2026
…vision shape (#2294)
The objectstack-automation skill documented approve/reject approvals (ADR-0019)
but not the ADR-0044 revise loop, so AI-authored approval flows omit it (and a
revise loop hand-built without the back-edge gets rejected by registerFlow).
Add a "Send-back for revision" section to the Approvals area: the `revise`
out-edge → a signal `wait` node, the resubmit edge typed `type: 'back'` (the only
thing that legalizes the cycle — graph-minus-back-edges must be a DAG, authors
opt in edge by edge), and the `maxRevisions` budget. Calls out the two shapes the
compile-time flow lint flags (dead-end revise; unmarked back-edge) and points at
the canonical showcase_budget_approval.
Completes the agent-teaching slice of #2274 (ADR-0044), alongside the compile-time
lint (#2279), the flow-builder `back` edge style (#2291), and the engine's
already-specific cycle-rejection hint.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang added a commit that referenced this pull request Jun 24, 2026
)
Adds skills/objectstack-automation/evals/approvals/test-revise-loop.md, the first
concrete eval under the skills' (previously placeholder) evals/ format — Scenario
/ Expected Output / Common Mistakes / Validation Criteria. It pins the expected
send-back-for-revision shape (revise branch + signal wait + type:'back' resubmit +
maxRevisions), the three footguns the compile-time lint flags, and registerFlow-
based pass criteria.
This is the authorable (a) half of #2274's eval slice. The executable eval RUNNER
(b) remains a separate platform project — the skills' evals/ harness is still
"not yet implemented" per each dir's README.
Refs #2274, #1770 (ADR-0044). Builds on the lint (#2279) and skill (#2294).
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang added a commit that referenced this pull request Jul 5, 2026
fix(plugin-form): dedupe master-detail create toast + localize Cancel (#2278) (#2279)
objectui@ec9c8eec8e1ce7310e78511f4beee09ba1d98862
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang