@kontourai/flow-agents 3.5.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/.github/workflows/ci.yml +4 -0
  2. package/CHANGELOG.md +15 -0
  3. package/build/src/builder-flow-run-adapter.d.ts +32 -3
  4. package/build/src/builder-flow-run-adapter.js +113 -20
  5. package/build/src/builder-flow-runtime.d.ts +26 -3
  6. package/build/src/builder-flow-runtime.js +502 -49
  7. package/build/src/builder-lifecycle-authority.d.ts +35 -0
  8. package/build/src/builder-lifecycle-authority.js +219 -0
  9. package/build/src/cli/assignment-provider.d.ts +14 -7
  10. package/build/src/cli/assignment-provider.js +128 -65
  11. package/build/src/cli/builder-run.js +46 -9
  12. package/build/src/cli/workflow-artifact-cleanup-audit.js +3 -0
  13. package/build/src/cli/workflow-sidecar.d.ts +30 -3
  14. package/build/src/cli/workflow-sidecar.js +825 -99
  15. package/build/src/cli/workflow.d.ts +2 -0
  16. package/build/src/cli/workflow.js +769 -0
  17. package/build/src/cli.js +2 -0
  18. package/build/src/flow-kit/validate.d.ts +17 -0
  19. package/build/src/flow-kit/validate.js +340 -2
  20. package/build/src/index.d.ts +4 -0
  21. package/build/src/index.js +7 -5
  22. package/build/src/lib/observed-command.d.ts +7 -0
  23. package/build/src/lib/observed-command.js +100 -0
  24. package/build/src/lib/package-version.d.ts +2 -0
  25. package/build/src/lib/package-version.js +13 -0
  26. package/build/src/lib/pinned-cli-command.d.ts +6 -0
  27. package/build/src/lib/pinned-cli-command.js +21 -0
  28. package/build/src/tools/generate-context-map.js +5 -3
  29. package/context/contracts/artifact-contract.md +1 -1
  30. package/context/scripts/hooks/config-protection.js +8 -1
  31. package/context/scripts/hooks/lib/config-protection-remedies.js +3 -0
  32. package/context/scripts/hooks/lib/kit-catalog.js +1 -1
  33. package/context/scripts/hooks/stop-goal-fit.js +79 -10
  34. package/docs/context-map.md +24 -20
  35. package/docs/developer-architecture.md +1 -1
  36. package/docs/public-workflow-cli.md +132 -0
  37. package/docs/skills-map.md +51 -27
  38. package/docs/spec/builder-flow-runtime.md +78 -40
  39. package/docs/workflow-usage-guide.md +110 -38
  40. package/evals/ci/run-baseline.sh +2 -0
  41. package/evals/fixtures/hook-influence/cases.json +2 -2
  42. package/evals/integration/test_builder_entry_enforcement.sh +57 -45
  43. package/evals/integration/test_builder_step_producers.sh +297 -6
  44. package/evals/integration/test_bundle_install.sh +258 -55
  45. package/evals/integration/test_critique_supersession_roundtrip.sh +21 -8
  46. package/evals/integration/test_current_json_per_actor.sh +12 -0
  47. package/evals/integration/test_dual_emit_flow_step.sh +62 -43
  48. package/evals/integration/test_flowdef_session_activation.sh +145 -25
  49. package/evals/integration/test_flowdef_session_history_preservation.sh +23 -21
  50. package/evals/integration/test_gate_lockdown.sh +3 -5
  51. package/evals/integration/test_goal_fit_hook.sh +60 -2
  52. package/evals/integration/test_liveness_verdict.sh +14 -17
  53. package/evals/integration/test_phase_map_and_gate_claim.sh +63 -38
  54. package/evals/integration/test_public_workflow_cli.sh +573 -0
  55. package/evals/integration/test_pull_work_liveness_preflight.sh +22 -66
  56. package/evals/integration/test_sidecar_field_preservation.sh +36 -11
  57. package/evals/integration/test_workflow_sidecar_writer.sh +277 -44
  58. package/evals/integration/test_workflow_steering_hook.sh +15 -38
  59. package/evals/run.sh +2 -0
  60. package/evals/static/test_builder_skill_coherence.sh +247 -0
  61. package/evals/static/test_library_exports.sh +5 -2
  62. package/evals/static/test_workflow_skills.sh +13 -325
  63. package/kits/builder/flows/build.flow.json +22 -0
  64. package/kits/builder/flows/shape.flow.json +9 -9
  65. package/kits/builder/kit.json +70 -16
  66. package/kits/builder/skills/builder-shape/SKILL.md +75 -75
  67. package/kits/builder/skills/continue-work/SKILL.md +45 -106
  68. package/kits/builder/skills/deliver/SKILL.md +96 -442
  69. package/kits/builder/skills/design-probe/SKILL.md +40 -139
  70. package/kits/builder/skills/evidence-gate/SKILL.md +59 -201
  71. package/kits/builder/skills/execute-plan/SKILL.md +54 -125
  72. package/kits/builder/skills/fix-bug/SKILL.md +42 -132
  73. package/kits/builder/skills/gate-review/SKILL.md +60 -211
  74. package/kits/builder/skills/idea-to-backlog/SKILL.md +63 -244
  75. package/kits/builder/skills/learning-review/SKILL.md +63 -170
  76. package/kits/builder/skills/pickup-probe/SKILL.md +54 -111
  77. package/kits/builder/skills/plan-work/SKILL.md +51 -185
  78. package/kits/builder/skills/pull-work/SKILL.md +136 -485
  79. package/kits/builder/skills/release-readiness/SKILL.md +66 -107
  80. package/kits/builder/skills/review-work/SKILL.md +89 -176
  81. package/kits/builder/skills/tdd-workflow/SKILL.md +53 -147
  82. package/kits/builder/skills/verify-work/SKILL.md +101 -113
  83. package/package.json +2 -2
  84. package/schemas/builder-lifecycle-authorization.schema.json +57 -0
  85. package/schemas/lifecycle-authority-keys.schema.json +25 -0
  86. package/schemas/workflow-state.schema.json +1 -1
  87. package/scripts/hooks/config-protection.js +8 -1
  88. package/scripts/hooks/lib/config-protection-remedies.js +3 -0
  89. package/scripts/hooks/lib/kit-catalog.js +1 -1
  90. package/scripts/hooks/stop-goal-fit.js +79 -10
  91. package/src/builder-flow-run-adapter.ts +156 -23
  92. package/src/builder-flow-runtime.ts +535 -53
  93. package/src/builder-lifecycle-authority.ts +218 -0
  94. package/src/cli/assignment-provider-lock.test.mjs +83 -0
  95. package/src/cli/assignment-provider.ts +91 -22
  96. package/src/cli/builder-flow-run-adapter.test.mjs +4 -2
  97. package/src/cli/builder-flow-runtime.test.mjs +597 -8
  98. package/src/cli/builder-run.ts +54 -9
  99. package/src/cli/kit-metadata-security.test.mjs +232 -6
  100. package/src/cli/public-api.test.mjs +15 -0
  101. package/src/cli/workflow-artifact-cleanup-audit.ts +3 -0
  102. package/src/cli/workflow-sidecar-execution-proof.test.mjs +90 -0
  103. package/src/cli/workflow-sidecar.ts +748 -99
  104. package/src/cli/workflow.ts +708 -0
  105. package/src/cli.ts +2 -0
  106. package/src/flow-kit/validate.ts +320 -2
  107. package/src/index.ts +20 -5
  108. package/src/lib/observed-command.ts +96 -0
  109. package/src/lib/package-version.ts +15 -0
  110. package/src/lib/pinned-cli-command.ts +23 -0
  111. package/src/tools/generate-context-map.ts +5 -3
@@ -4,6 +4,11 @@ title: Workflow Usage Guide
4
4
 
5
5
  # Workflow Usage Guide
6
6
 
7
+ > Consumer repositories and Builder skills use the supported public workflow
8
+ > surface and isolated exact-package launcher documented in
9
+ > [Public Workflow CLI](public-workflow-cli.md). Lower-level writer commands are
10
+ > package internals, not a supported agent or consumer interface.
11
+
7
12
  This guide shows how to use the Builder Kit workflow skills in normal chats.
8
13
 
9
14
  > **Which doc do I want?** This page is the *driver's manual* — what to say at each stage and what should happen. If you want the conceptual map first — layers, sidecars, hooks, evidence, and why the system is shaped this way — read the [Agent System Guidebook](agent-system-guidebook.md). For a one-line summary of every skill and gate, use the [Skills Map](skills-map.md). Flow Agents coordinates the local runtime, installs Flow Kits, and records artifacts; Flow owns gate semantics, including typed `expects` entries with `kind: "trust.bundle"`, trusted producer config, and gate overrides.
@@ -21,7 +26,7 @@ Workflow artifacts follow a closeout lifecycle. Local runtime artifacts live und
21
26
  For local artifact queue hygiene, run the read-only cleanup audit:
22
27
 
23
28
  ```bash
24
- npm run workflow-artifact-cleanup-audit -- --artifact-root .flow-agents
29
+ npm run workflow-artifact-cleanup-audit -- --artifact-root .kontourai/flow-agents
25
30
  ```
26
31
 
27
32
  The audit is linked to the lifecycle policy in `docs/workflow-artifact-lifecycle.md`. It classifies active WIP, cleanup candidates, terminal done records, active learning follow-ups, and invalid sidecars without deleting or archiving anything.
@@ -38,20 +43,21 @@ Use Builder Kit shape. I have several ideas:
38
43
  - billing alert improvements
39
44
  - AI dashboard summary
40
45
 
41
- Separate these into distinct ideas, use Probe/alignment questions if the outcome or bundle is unclear, find the thinnest meaningful slice for each, push back if I bundle unrelated work, and stop at the backlog gate unless I explicitly ask you to sync GitHub issues.
46
+ Separate these into distinct ideas, use Probe/alignment questions if the outcome or bundle is unclear, find the thinnest meaningful slice for each, push back if I bundle unrelated work, and stop at the backlog gate unless I explicitly ask you to sync configured provider work items (for example, GitHub issues).
42
47
  ```
43
48
 
44
49
  Expected behavior:
45
50
 
46
51
  - delegate shaping to `kits/builder/skills/idea-to-backlog/SKILL.md`
47
52
  - link the artifact to the Builder Kit Flow Definition at `kits/builder/flows/shape.flow.json`
53
+ - start the public `builder.shape` Flow with a safe explicit slug, then inspect its public status before the step producer records evidence
48
54
  - inventory each distinct idea separately
49
55
  - classify each idea
50
56
  - identify the thinnest meaningful slice
51
57
  - shape executable work items with a readable story/outcome, scope, non-goals, stable `R*` requirement ids, stable `AC*` acceptance ids, verification expectation, milestone/delivery outcome, dependencies, and source artifact
52
58
  - require bundle justification before grouping ideas
53
59
  - map dependencies as blocking, blocked-by, or related-only
54
- - stop at the backlog gate unless you explicitly ask to continue or explicitly request GitHub issue sync
60
+ - stop at the backlog gate unless you explicitly ask to continue or explicitly request configured provider work-item sync; GitHub issue sync is an optional adapter example
55
61
 
56
62
  Expected artifact:
57
63
 
@@ -89,7 +95,7 @@ If the relationship is only thematic, split the work. If there is a real depende
89
95
 
90
96
  ## 3. Pull Ready Work From The Backlog
91
97
 
92
- Use `pull-work` when provider-backed work items already exist and you want to choose what to work on next. GitHub issues are the first concrete adapter example, not the core workflow vocabulary.
98
+ Use `pull-work` when provider-backed work items already exist and you want to choose what to work on next. The public `builder.build` interface accepts exactly two Work Item reference forms: `provider:id` and `owner/repo#numeric-id`. The latter is a GitHub-compatible adapter form; do not invent arbitrary reference formats. GitHub issues remain an optional adapter example, not the core workflow vocabulary.
93
99
 
94
100
  Example prompt:
95
101
 
@@ -112,11 +118,11 @@ Expected artifact:
112
118
  .kontourai/flow-agents/<slug>/<slug>--pull-work.md
113
119
  ```
114
120
 
115
- When a repository has backlog provider settings, `pull-work` should use those settings without requiring the user to name the board. In Flow Agents, `npm run effective-backlog-settings -- --repo-path . --json` resolves `kontourai/flow-agents` to GitHub Project `kontourai/1`, so a prompt like `use pull-work` is enough for the configured provider path.
121
+ When a repository has backlog provider settings, `pull-work` should use those settings without requiring the user to name the board. In this repository, the optional GitHub adapter resolves `kontourai/flow-agents` to GitHub Project `kontourai/1`, so a prompt like `use pull-work` is enough for that configured provider path.
116
122
 
117
123
  ### Assignment ownership: the third provider leg
118
124
 
119
- Beside the `WorkItemProvider` (what work exists) and `BoardProvider` (how it is grouped/ranked) settings above, `pull-work` also reads `AssignmentProvider` settings to decide who currently owns a candidate work item before offering it. This is durable, human-visible ownership a GitHub issue assignee, an `agent:claimed` label, and a versioned machine-readable claim comment (or, for tracker-less repos and evals, an equivalent local JSON record) joined against the ephemeral liveness presence layer so a crashed session's stale claim never blocks a second session from picking up the same work.
125
+ Beside the `WorkItemProvider` (what work exists) and `BoardProvider` (how it is grouped/ranked) settings above, `pull-work` also reads `AssignmentProvider` settings to decide who currently owns a candidate work item before offering it. This is durable, human-visible ownership represented by the configured provider. For example, the optional GitHub adapter can use an issue assignee, an `agent:claimed` label, and a versioned machine-readable claim comment; tracker-less repos and evals can use an equivalent local JSON record. Join it against the ephemeral liveness presence layer so a crashed session's stale claim never blocks a second session from picking up the same work.
120
126
 
121
127
  Settings live at `context/settings/assignment-provider-settings.json` (validated by `schemas/assignment-provider-settings.schema.json`), mirroring the same `defaults`/`projects[]` shape as the backlog provider settings above; resolve them with `npm run effective-assignment-provider-settings -- --repo-path . --json`. See `context/contracts/assignment-provider-contract.md` for the full `claim`/`release`/`supersede`/`status`/`list` vocabulary, the assignment ⋈ liveness join table, and the human-assignee ask-first policy.
122
128
 
@@ -124,7 +130,7 @@ Direct `pull-work` remains a normal workflow primitive. The Builder Kit build pa
124
130
 
125
131
  Builder Kit build is the product-level entry point for implementation pickup. In that mode, `pull-work` may guide the next step automatically as `pull-work -> design-probe / pickup-probe`; direct `pull-work` still stops with a `plan-work` handoff unless you ask to continue.
126
132
 
127
- If the board is empty or every issue is vague/stale, route back to Builder Kit shape / `idea-to-backlog`. Do not invent implementation work from an empty queue.
133
+ If the board is empty or every work item is vague/stale, route back to Builder Kit shape / `idea-to-backlog`. Do not invent implementation work from an empty queue.
128
134
 
129
135
  Before selecting new work, `pull-work` must separate your WIP from global conflict context:
130
136
 
@@ -215,17 +221,17 @@ Use execute-plan for .kontourai/flow-agents/<slug>/<slug>--plan.md. Prefer isola
215
221
 
216
222
  Use `review-work` after implementation and before verification. Review is critique: it asks whether the code should change before you trust it.
217
223
 
218
- Review checks quality, security triggers, architecture fit, project standards, risky assumptions, and maintainability. It writes `critique.json`. A clean review does not prove the feature works; it only says the implementation has no open reviewer findings that block the next gate.
224
+ Review checks quality, security triggers, architecture fit, project standards, risky assumptions, and maintainability. In the active `verify` step, `review-work` owns `clean-critique` through public `workflow critique` in `trust.bundle`. A clean review does not prove the feature works; it only says the implementation has no open reviewer findings that block the next gate.
219
225
 
220
226
  Example prompt:
221
227
 
222
228
  ```text
223
- Use review-work for .kontourai/flow-agents/<slug>/<slug>--deliver.md. Run code review, security review if triggered, and standards/architecture critique. Record findings in critique.json. Do not fix code.
229
+ Use review-work for the current Builder session. Run code review, security review if triggered, and standards/architecture critique. Record findings through public workflow critique. Do not fix code.
224
230
  ```
225
231
 
226
232
  Then use `verify-work` for implementation verification. Verification is evidence: it asks what proves the accepted behavior works.
227
233
 
228
- Verification runs build/type/lint/test/security/browser/runtime checks as relevant, maps results to acceptance criteria and Goal Fit, and writes `evidence.json`.
234
+ Verification runs build/type/lint/test/security/browser/runtime checks as relevant, maps results to acceptance criteria and Goal Fit, and records command-backed evidence in `trust.bundle`. In the active `verify` step, `verify-work` owns `acceptance-criteria`, `tests-evidence`, and applicable `policy-compliance`.
229
235
 
230
236
  Example prompt:
231
237
 
@@ -272,7 +278,61 @@ Goal Fit is the local stop condition before a final answer. The working artifact
272
278
 
273
279
  The `stop-goal-fit` hook also checks the latest workflow artifact and warns when the session is about to stop with missing `Definition Of Done`, incomplete Goal Fit, invalid sidecars, or open final acceptance work. Set `FLOW_AGENTS_GOAL_FIT_STRICT=true` to block incomplete local delivery. Set `FLOW_AGENTS_REQUIRE_SIDECARS=true` when structured workflow state should be mandatory. Set `FLOW_AGENTS_REQUIRE_CRITIQUE=true` when critique records should also be mandatory.
274
280
 
275
- Use `npm run workflow:sidecar --` to create routine sidecars instead of hand-writing JSON:
281
+ For an active Builder run, inspect and record evidence through the public CLI:
282
+
283
+ ```bash
284
+ flow-agents workflow status --session-dir .kontourai/flow-agents/<slug> --json
285
+ flow-agents workflow evidence \
286
+ --session-dir .kontourai/flow-agents/<slug> \
287
+ --expectation <declared-expectation> \
288
+ --status <pass|fail|not_verified> \
289
+ --command "npm test" \
290
+ --summary "The recorded command supports the declared expectation." \
291
+ --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/<slug>/<slug>--plan-work.md","summary":"Reviewable artifact for the declared expectation."}'
292
+
293
+ # For tests-evidence, repeat --criterion-json for every accepted criterion.
294
+ # Repeat --command and its matching top-level command ref when criteria use
295
+ # different checks.
296
+ flow-agents workflow evidence \
297
+ --session-dir .kontourai/flow-agents/<slug> \
298
+ --expectation tests-evidence \
299
+ --status pass \
300
+ --command "npm test" \
301
+ --summary "Each accepted criterion has command-backed verification evidence." \
302
+ --evidence-ref-json '{"kind":"command","excerpt":"npm test","summary":"Exact substantive project test command recorded for this verification result."}' \
303
+ --criterion-json '{"id":"<criterion-id>","status":"pass","evidence_refs":[{"kind":"command","excerpt":"npm test","summary":"Exact substantive project test command run for this criterion."}]}' \
304
+ --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/<slug>/<slug>--plan-work.md","summary":"Criterion mapping and expected verification evidence."}'
305
+
306
+ flow-agents workflow critique \
307
+ --session-dir .kontourai/flow-agents/<slug> \
308
+ --verdict <pass|fail|not_verified> \
309
+ --summary "Report-only critique findings and gaps are recorded." \
310
+ --artifact-ref ".kontourai/flow-agents/<slug>/<slug>--deliver.md" \
311
+ --artifact-ref "<reviewed-changed-file>" \
312
+ --lane-json '{"id":"code-review","status":"pass","summary":"Code quality, correctness, architecture, and standards were reviewed.","evidence_refs":[{"kind":"artifact","file":".kontourai/flow-agents/<slug>/<slug>--deliver.md","summary":"Reviewed delivery artifact and changed-scope context."}]}'
313
+ ```
314
+
315
+ Only the step skill declared for that Flow expectation should publish it.
316
+ Run authenticated critique before `tests-evidence`; the delegated reviewer
317
+ invokes the public critique command under a runtime identity distinct from the
318
+ active implementation actor. The command does not accept a caller-selected
319
+ reviewer identity.
320
+ Every critique must include at least one substantive lane. A passing critique
321
+ must also cite the delivery report and reviewed changed files. Stored file
322
+ hashes and the workspace snapshot prevent later implementation changes from
323
+ inheriting a stale clean review.
324
+ Entrypoints, profiles, shared primitives, and extensions do not claim step-gate
325
+ completion. `review-work` owns only `clean-critique`; `verify-work` owns
326
+ `acceptance-criteria`, `tests-evidence`, and applicable `policy-compliance`.
327
+
328
+ ### Package Maintainer Internals
329
+
330
+ The following writer details explain existing package implementation and
331
+ maintenance tests. They are not Builder skill or consumer commands. Skills use
332
+ the public CLI shown above and treat an unavailable public operation as a
333
+ blocker or `NOT_VERIFIED` gap.
334
+
335
+ The package's internal writer can create and validate projected artifacts:
276
336
 
277
337
  ```bash
278
338
  npm run workflow:sidecar -- ensure-session \
@@ -288,15 +348,19 @@ npm run workflow:sidecar -- init-plan .kontourai/flow-agents/<slug>/<slug>--deli
288
348
 
289
349
  #### Deterministic slug from a work-item ref
290
350
 
291
- For issue-backed sessions, pass `--work-item <owner/repo#id>` instead of `--task-slug`. The
292
- derived slug has the format `<owner>-<repo>-<id>` for example:
351
+ For work-item-backed sessions, use one of the two supported reference forms:
352
+ `provider:id` or `owner/repo#numeric-id`. The latter is the GitHub-compatible
353
+ adapter form; do not use other formats. `--task-slug` is reserved for an
354
+ existing local Work Item retry. The internal writer derives a deterministic slug
355
+ from either supported form; the GitHub-compatible example has the format
356
+ `<owner>-<repo>-<id>`:
293
357
 
294
358
  ```bash
295
359
  npm run workflow:sidecar -- ensure-session \
296
360
  --work-item "kontourai/flow-agents#161" \
297
361
  --source-request "Implement #161" \
298
362
  --summary "Deterministic slug demo."
299
- # Creates .flow-agents/kontourai-flow-agents-161/
363
+ # Creates .kontourai/flow-agents/kontourai-flow-agents-161/
300
364
  ```
301
365
 
302
366
  The slug is deterministic and idempotent: any agent or worktree that runs `ensure-session
@@ -309,9 +373,10 @@ detectable via `liveness status --subject kontourai-flow-agents-161` (see
309
373
  Rules:
310
374
  - `--task-slug` always wins when both flags are supplied (back-compat).
311
375
  - Omitting both flags still dies with `--task-slug is required`.
312
- - The `id` part after `#` must be a plain integer (GitHub issue number). Non-integer ids are
313
- rejected.
314
- - Issue-backed sessions should prefer `--work-item` over hand-supplied `--task-slug` so that
376
+ - In `owner/repo#numeric-id`, the id after `#` must be a plain integer. In
377
+ `provider:id`, the provider and id must use the provider-neutral reference
378
+ grammar; nonconforming or arbitrary formats are rejected.
379
+ - Work-item-backed sessions should prefer `--work-item` over hand-supplied `--task-slug` so that
315
380
  liveness subjectId alignment is automatic.
316
381
 
317
382
  #### Branch convention
@@ -417,24 +482,28 @@ version's rule set) — but it is not a partial/best-effort pass either.
417
482
  when a `state.json` has no `branch` field, naming the gap without breaking legacy
418
483
  sessions/fixtures.
419
484
 
420
- Reviewer Markdown artifacts can be imported into `critique.json`:
421
-
422
- ```bash
423
- npm run workflow:sidecar -- import-critique .kontourai/flow-agents/<slug> .kontourai/flow-agents/<slug>/<slug>--review.md
424
- ```
485
+ Reviewer Markdown can be retained as a linked reference, but the public
486
+ `workflow critique` operation is the only Builder review-recording interface.
425
487
 
426
- Core workflow skills should use these writer commands when available. If a writer command or validation is unavailable or blocked, the artifact should record the exact sidecar gap as `NOT_VERIFIED` rather than silently falling back to an unstructured pass.
488
+ Package integration tests use these writer commands to exercise projection
489
+ internals. Core workflow skills must use `flow-agents workflow`; if its required
490
+ operation is unavailable or blocked, record the exact gap as `NOT_VERIFIED`
491
+ rather than silently falling back to an internal command or unstructured pass.
427
492
 
428
493
  Manual sidecar writing is an exceptional recovery path only. If `npm run workflow:sidecar --` cannot acquire `.workflow-sidecar.lockdir` with `EPERM` or `EACCES`, first fix the artifact directory permissions or ownership, or rerun the workflow in an approved writable workspace. If the writer is still blocked by local permissions or sandboxing, manually write only schema-valid sidecars, record the exact writer failure as `NOT_VERIFIED`, and run `npm run workflow:validate-artifacts -- --require-sidecars <artifact-dir>` before treating recovery as complete.
429
494
 
430
- For substantial Flow Agents repo changes, maintainers can use the combined local evidence command after checks and critique are ready:
495
+ The combined internal writer fixture below is documented only for maintainers
496
+ of its integration tests. It is not a Builder workflow operation:
431
497
 
432
498
  ```bash
433
499
  npm run workflow:sidecar -- dogfood-pass \
434
500
  --check-json '{"id":"focused-check","kind":"test","status":"pass","summary":"Focused check passed."}' \
435
501
  --require-critique \
436
502
  --critique-id "dogfood-review" \
437
- --critique-summary "Critique passed."
503
+ --critique-verdict pass \
504
+ --critique-summary "Critique passed." \
505
+ --artifact-ref ".kontourai/flow-agents/<slug>/<slug>--deliver.md" \
506
+ --lane-json '{"id":"code-review","status":"pass","summary":"Focused review completed.","evidence_refs":[{"kind":"artifact","file":".kontourai/flow-agents/<slug>/<slug>--deliver.md","summary":"Reviewed dogfood delivery artifact."}]}'
438
507
  ```
439
508
 
440
509
  `dogfood-pass` is fail-closed: it refuses a clean pass without evidence and refuses required critique gaps before writing partial evidence. When the same clean pass is also merge-ready, add `--release-decision merge` and one or more `--release-doc-ref` values to write `release.json` in the same validated pass. Release decisions require passing critique.
@@ -512,7 +581,7 @@ Completion gate:
512
581
  - `state.status` may be `delivered`, `accepted`, or `archived` with `phase: done` only when evidence is passing and either a promoted doc exists or the no-docs decision is explicit.
513
582
  - `NOT_VERIFIED` evidence cannot be promoted as a clean delivery doc. Promote it as a blocked or partial record only if the doc names the gap and next owner.
514
583
  - For adapter or provider work, the promoted doc should distinguish local/dry-run capability from live external mutation.
515
- - Final delivery must reconcile sidecars before stopping: `acceptance.json`, `evidence.json`, and `release.json` are authoritative gate inputs. Temporary verifier-local mismatch notes are superseded only when the final orchestrator evidence or release validation names the reconciled sidecars. If Markdown and sidecars still disagree, hold the terminal delivery.
584
+ - Final delivery must reconcile `trust.bundle` before stopping. Temporary verifier-local notes are superseded only when the final public evidence or release validation names the reconciled trust slices. If linked reports and the bundle disagree, hold the terminal delivery.
516
585
  - Final acceptance should also close the active local state: after merge or accepted no-provider-change work, do not leave `state.status: verified` unless release, docs promotion, or learning still has an unresolved blocker.
517
586
 
518
587
  The validator and stop hook enforce this shape for terminal workflows. If a delivery is terminal and neither the Markdown artifact nor `state.json.artifact_paths` points at durable docs, validation should fail unless the artifact records an explicit no-docs decision.
@@ -584,24 +653,27 @@ Use learning-review. Capture facts, decisions, gaps, follow-ups, and durable kno
584
653
  ## Resumable sessions
585
654
 
586
655
  Builder build sessions also project their canonical Flow run into the resume block.
587
- Start a newly selected session with `flow-agents builder-run start --session-dir
588
- .kontourai/flow-agents/<slug>`. Thereafter, follow `next_action.skills` or
589
- `next_action.operations`, record the current gate evidence, and use the exact
590
- `next_action.command` if automatic synchronization was interrupted. See
656
+ Start a newly selected session with `flow-agents workflow start --flow builder.build
657
+ --work-item <provider-ref> --assignment-provider <configured-kind>` and add
658
+ `--effective-state-json <provider-status.json>` for a non-local provider, where `<provider-ref>` is exactly `provider:id` or
659
+ `owner/repo#numeric-id`; the latter is the GitHub-compatible adapter form. The
660
+ adapter supplies the stable, human-readable Work Item reference. Thereafter, follow `next_action.skills` or `next_action.operations` and record the
661
+ current gate through the public `workflow evidence` command. After interruption, inspect
662
+ the read-only `workflow status` projection without attaching evidence or advancing the run. See
591
663
  [`docs/spec/builder-flow-runtime.md`](spec/builder-flow-runtime.md) for the ownership,
592
664
  trust-binding, route-back, and artifact-root contract.
593
665
 
594
- If the same Builder slice is interrupted and its sidecar/current pointers may be
595
- stale, restore the projection from the existing canonical Flow run with:
666
+ If the same Builder slice is interrupted, inspect its canonical status. Resume
667
+ only when the public status reports a paused run:
596
668
 
597
669
  ```bash
598
- flow-agents builder-run recover --session-dir .kontourai/flow-agents/<slug>
670
+ flow-agents workflow status --session-dir .kontourai/flow-agents/<slug> --json
671
+ flow-agents workflow resume --session-dir .kontourai/flow-agents/<slug> --reason "Continue the bound work item"
599
672
  ```
600
673
 
601
- The session slug is the run identity; recovery accepts no caller-selected run or
602
- step. It validates the sole Work Item binding and updates only the sidecar/current
603
- projection, leaving the entire Flow run byte-identical. Recovery never attaches or
604
- evaluates `trust.bundle`; use `builder-run sync` for that separate operation.
674
+ The session slug is the run identity. Do not select a different run, force a
675
+ step, or use an internal synchronization command to bypass the canonical next
676
+ action.
605
677
 
606
678
  When a session resumes (after context compaction, an agent restart, or a cross-session
607
679
  handoff), the workflow-steering hook emits a `RESUME:` block on `SessionStart` that
@@ -614,7 +686,7 @@ The `RESUME:` block supplements the existing `STATE:` line and contains:
614
686
  - **Plan** — path to the plan artifact (`<slug>--plan-work.md` from `state.json artifact_paths` or conventional fallback).
615
687
  - **Next step** — the first `handoff.json next_steps` entry.
616
688
  - **Blockers** — any recorded blockers from `handoff.json`, or "none".
617
- - **Trust** — `Trust: N verified / M disputed / T total` from reading `trust.bundle`. Each disputed or unknown claim is listed with its id and a copy-pasteable remedy command: `npm run workflow:sidecar -- claim <id> <dir>`.
689
+ - **Trust** — `Trust: N verified / M disputed / T total` from reading `trust.bundle`. Each disputed or unknown claim names the owning expectation so its step producer can attach resolving evidence through `flow-agents workflow evidence`.
618
690
  - **Liveness advisory** (when applicable) — `[LIVENESS WARNING: another agent appears live on this work: actor <X>, last seen <T>]` when the shared liveness stream (`.kontourai/flow-agents/liveness/events.jsonl`, ADR 0012) contains a fresh claim or heartbeat from a different actor for the same slug. This is advisory only — the hook exits 0 regardless. The block also always includes an `ACTOR: <actor> (<source>)` line — the same runtime-agnostic actor identity this session resolves for itself (see "Actor identity and liveness writes" below), so a resuming agent can see at a glance which identity its own liveness claims/heartbeats will be filed under.
619
691
  - **Route hint** — `To continue: resume this work. Or run pull-work to assess WIP and start new/parallel work.` — always routes the resume-vs-parallel decision through `pull-work` rather than auto-taking it.
620
692
 
@@ -41,6 +41,7 @@ CHECKS=(
41
41
  "Flow Kit repository integration|bash evals/integration/test_flow_kit_repository.sh"
42
42
  "Runtime adapter activation integration|bash evals/integration/test_runtime_adapter_activation.sh"
43
43
  "Bundle install integration|bash evals/integration/test_bundle_install.sh"
44
+ "Public workflow CLI integration|bash evals/integration/test_public_workflow_cli.sh"
44
45
  "Bundle lifecycle integration|bash evals/integration/test_bundle_lifecycle.sh"
45
46
  "Activate npx context integration|bash evals/integration/test_activate_npx_context.sh"
46
47
  "Kit conformance levels integration|bash evals/integration/test_kit_conformance_levels.sh"
@@ -133,6 +134,7 @@ LANE_RUNTIME_AND_KIT=(
133
134
  "Flow Kit repository integration"
134
135
  "Runtime adapter activation integration"
135
136
  "Bundle install integration"
137
+ "Public workflow CLI integration"
136
138
  "Bundle lifecycle integration"
137
139
  "Activate npx context integration"
138
140
  "Kit conformance levels integration"
@@ -131,7 +131,7 @@
131
131
  ],
132
132
  "agent_must_do": [
133
133
  "delegate to review-work for report-only critique before verify-work",
134
- "not count critique.json as verification evidence or evidence.json as critique",
134
+ "not count report-only critique as verification evidence",
135
135
  "route open critique findings back through execute-plan, then re-review and re-verify"
136
136
  ],
137
137
  "evidence": {
@@ -156,7 +156,7 @@
156
156
  "guidance_must_include": [
157
157
  "KIT WORKFLOW ROUTE",
158
158
  "activate `deliver`",
159
- "--flow-id builder.build",
159
+ "public `flow-agents workflow` interface",
160
160
  "plan-work -> execute-plan -> review-work -> verify-work",
161
161
  "release-readiness and learning-review"
162
162
  ],
@@ -13,6 +13,12 @@ trap 'rm -rf "$TMP"' EXIT
13
13
  pass() { printf ' PASS %s\n' "$1"; }
14
14
  fail() { printf ' FAIL %s\n' "$1"; errors=$((errors + 1)); }
15
15
 
16
+ seed_pull_work_report() {
17
+ local artifact_root="$1" slug="$2" work_item_ref="$3"
18
+ mkdir -p "$artifact_root/$slug"
19
+ printf '# Pull Work\n\nSelected Work Item: %s\n' "$work_item_ref" > "$artifact_root/$slug/$slug--pull-work.md"
20
+ }
21
+
16
22
  WRITER="workflow-sidecar"
17
23
 
18
24
  echo "=== Builder workflow entry enforcement ==="
@@ -185,14 +191,20 @@ else
185
191
  fi
186
192
 
187
193
  LOCAL_ROOT="$TMP/local/.kontourai/flow-agents"
188
- if flow_agents_node "$WRITER" ensure-session \
194
+ seed_pull_work_report "$LOCAL_ROOT" "local-request" "local:local-request"
195
+ cat >"$LOCAL_ROOT/local-request/work-item.json" <<'JSON'
196
+ {"id":"local-request","title":"Local request","source_provider":{"kind":"local","path":"work-item.json"}}
197
+ JSON
198
+ cat >"$LOCAL_ROOT/local-request/state.json" <<'JSON'
199
+ {"schema_version":"1.0","task_slug":"local-request","status":"planned","phase":"pickup","work_item_refs":["local:local-request"],"next_action":{"status":"continue","summary":"Start Builder."}}
200
+ JSON
201
+ if FLOW_AGENTS_ACTOR=builder-entry-local node "$ROOT/build/src/cli.js" workflow start \
189
202
  --artifact-root "$LOCAL_ROOT" \
203
+ --flow builder.build \
204
+ --work-item local:local-request \
190
205
  --task-slug local-request \
191
- --actor builder-entry-local \
192
206
  --title "Local request" \
193
- --summary "Providerless work still needs an anchor." \
194
- --flow-id builder.build \
195
- --timestamp "2026-07-10T00:00:00Z" >"$TMP/local.out" 2>&1; then
207
+ --summary "Providerless work still needs an anchor." >"$TMP/local.out" 2>&1; then
196
208
  if node - "$LOCAL_ROOT" <<'NODE'
197
209
  const fs = require('node:fs');
198
210
  const path = require('node:path');
@@ -209,7 +221,7 @@ if (workItem.source_provider?.kind !== 'local' || workItem.source_provider?.path
209
221
  if (flowState.current_step !== 'design-probe' || flowState.subject !== 'local:local-request') process.exit(1);
210
222
  if (state.flow_run?.current_step !== 'design-probe') process.exit(1);
211
223
  if (JSON.stringify(state.next_action?.skills) !== JSON.stringify(['pickup-probe'])) process.exit(1);
212
- if (!state.next_action?.command?.includes('builder-run sync')) process.exit(1);
224
+ if (!state.next_action?.command?.includes("'workflow' 'status'")) process.exit(1);
213
225
  if ('enforcement' in state.next_action) process.exit(1);
214
226
  const bundle = JSON.parse(fs.readFileSync(path.join(root, 'local-request', 'trust.bundle'), 'utf8'));
215
227
  const selected = (bundle.claims || []).find((claim) => claim.claimType === 'builder.pull-work.selected');
@@ -228,14 +240,13 @@ fi
228
240
 
229
241
  LOCAL_SESSION="$LOCAL_ROOT/local-request"
230
242
  FLOW_DIGEST_BEFORE="$(find "$TMP/local/.kontourai/flow/runs/local-request" -type f -print0 | sort -z | xargs -0 shasum -a 256)"
231
- if flow_agents_node "$WRITER" ensure-session \
243
+ if FLOW_AGENTS_ACTOR=builder-entry-local node "$ROOT/build/src/cli.js" workflow start \
232
244
  --artifact-root "$LOCAL_ROOT" \
245
+ --flow builder.build \
246
+ --work-item local:local-request \
233
247
  --task-slug local-request \
234
- --actor builder-entry-local \
235
248
  --title "Local request" \
236
- --summary "Providerless work still needs an anchor." \
237
- --flow-id builder.build \
238
- --timestamp "2026-07-10T00:00:00Z" >"$TMP/builder-ensure-again.out" 2>&1 \
249
+ --summary "Providerless work still needs an anchor." >"$TMP/builder-ensure-again.out" 2>&1 \
239
250
  && [[ "$FLOW_DIGEST_BEFORE" == "$(find "$TMP/local/.kontourai/flow/runs/local-request" -type f -print0 | sort -z | xargs -0 shasum -a 256)" ]] \
240
251
  && node - "$TMP/local" "$LOCAL_SESSION" <<'NODE'
241
252
  const fs = require('node:fs');
@@ -247,7 +258,7 @@ const sidecar = JSON.parse(fs.readFileSync(path.join(session, 'state.json'), 'ut
247
258
  if (flowState.current_step !== 'design-probe' || flowState.subject !== 'local:local-request') process.exit(1);
248
259
  if (sidecar.flow_run?.current_step !== 'design-probe') process.exit(1);
249
260
  if (JSON.stringify(sidecar.next_action?.skills) !== JSON.stringify(['pickup-probe'])) process.exit(1);
250
- if (!sidecar.next_action?.command?.includes('builder-run sync')) process.exit(1);
261
+ if (!sidecar.next_action?.command?.includes("'workflow' 'status'")) process.exit(1);
251
262
  NODE
252
263
  then
253
264
  pass "repeated ensure-session loads the canonical Flow run without resetting its history"
@@ -258,6 +269,7 @@ fi
258
269
  BROKEN_PROJECT="$TMP/broken-start"
259
270
  BROKEN_ROOT="$BROKEN_PROJECT/.kontourai/flow-agents"
260
271
  mkdir -p "$BROKEN_PROJECT/.kontourai"
272
+ seed_pull_work_report "$BROKEN_ROOT" "broken-start" "local:broken-start"
261
273
  printf 'not a run-store directory\n' > "$BROKEN_PROJECT/.kontourai/flow"
262
274
  if flow_agents_node "$WRITER" ensure-session \
263
275
  --artifact-root "$BROKEN_ROOT" \
@@ -265,32 +277,29 @@ if flow_agents_node "$WRITER" ensure-session \
265
277
  --actor builder-entry-broken \
266
278
  --title "Broken start" \
267
279
  --summary "Flow startup must fail visibly." \
268
- --flow-id builder.build >"$TMP/broken-start.out" 2>&1; then
269
- fail "invalid canonical Flow startup should fail ensure-session"
270
- elif [[ -f "$BROKEN_ROOT/broken-start/state.json" ]] \
280
+ --flow-id builder.build >"$TMP/broken-start.out" 2>&1 \
281
+ && [[ -f "$BROKEN_ROOT/broken-start/state.json" ]] \
271
282
  && [[ ! -e "$BROKEN_PROJECT/.kontourai/flow/runs/broken-start" ]] \
272
- && grep -q 'canonical Builder Flow entry failed' "$TMP/broken-start.out" \
273
- && grep -q 'Re-run the same ensure-session command' "$TMP/broken-start.out" \
274
283
  && node - "$BROKEN_ROOT/broken-start/state.json" <<'NODE'
275
284
  const fs = require('node:fs');
276
285
  const state = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
277
286
  if (state.flow_run) process.exit(1);
278
- if (!state.next_action?.command?.includes('builder-run start')) process.exit(1);
287
+ if (!state.next_action?.command?.includes("'workflow' 'start'")) process.exit(1);
279
288
  NODE
280
289
  then
281
- pass "failed canonical startup is visible and leaves only retryable sidecar guidance"
290
+ pass "private writer leaves public retry guidance without touching an invalid Flow store"
282
291
  else
283
- fail "failed canonical startup forged state or lost recovery guidance: $(cat "$TMP/broken-start.out")"
292
+ fail "private writer touched canonical Flow or lost public retry guidance: $(cat "$TMP/broken-start.out")"
284
293
  fi
285
294
 
286
295
  rm -f "$BROKEN_PROJECT/.kontourai/flow"
287
- if flow_agents_node "$WRITER" ensure-session \
296
+ if FLOW_AGENTS_ACTOR=builder-entry-broken node "$ROOT/build/src/cli.js" workflow start \
288
297
  --artifact-root "$BROKEN_ROOT" \
298
+ --flow builder.build \
299
+ --work-item local:broken-start \
289
300
  --task-slug broken-start \
290
- --actor builder-entry-broken \
291
301
  --title "Broken start" \
292
- --summary "Flow startup must recover from persisted acquisition provenance." \
293
- --flow-id builder.build >"$TMP/broken-start-retry.out" 2>&1 \
302
+ --summary "Flow startup must recover from persisted acquisition provenance." >"$TMP/broken-start-retry.out" 2>&1 \
294
303
  && node - "$BROKEN_PROJECT" <<'NODE'
295
304
  const fs = require('node:fs');
296
305
  const path = require('node:path');
@@ -301,7 +310,7 @@ if (flowState.current_step !== 'design-probe') process.exit(1);
301
310
  if (!(bundle.claims || []).some((claim) => claim.claimType === 'builder.pull-work.selected' && claim.status === 'verified')) process.exit(1);
302
311
  NODE
303
312
  then
304
- pass "interrupted Flow startup retries from exact persisted acquisition provenance"
313
+ pass "public startup consumes exact persisted acquisition provenance and advances canonical Flow"
305
314
  else
306
315
  fail "interrupted acquisition could not recover: $(cat "$TMP/broken-start-retry.out")"
307
316
  fi
@@ -337,15 +346,14 @@ const fs = require('node:fs');
337
346
  const path = require('node:path');
338
347
  const project = process.argv[2];
339
348
  const session = path.join(project, '.kontourai', 'flow-agents', 'skipped-ownership');
340
- const flowState = JSON.parse(fs.readFileSync(path.join(project, '.kontourai', 'flow', 'runs', 'skipped-ownership', 'state.json'), 'utf8'));
341
349
  const sidecar = JSON.parse(fs.readFileSync(path.join(session, 'state.json'), 'utf8'));
342
- if (flowState.current_step !== 'pull-work' || sidecar.flow_run?.current_step !== 'pull-work') process.exit(1);
343
- if (JSON.stringify(sidecar.next_action?.skills) !== JSON.stringify(['pull-work'])) process.exit(1);
350
+ if (sidecar.flow_run) process.exit(1);
351
+ if (fs.existsSync(path.join(project, '.kontourai', 'flow', 'runs', 'skipped-ownership'))) process.exit(1);
344
352
  if (fs.existsSync(path.join(session, 'trust.bundle'))) process.exit(1);
345
353
  if (fs.existsSync(path.join(project, '.kontourai', 'flow-agents', 'assignment', 'skipped-ownership.json'))) process.exit(1);
346
354
  NODE
347
355
  then
348
- pass "skipped ownership remains at pull-work without selected-work evidence"
356
+ pass "private skipped-ownership seed creates no assignment, evidence, or canonical Flow"
349
357
  else
350
358
  fail "unproven ownership advanced the canonical run: $(cat "$TMP/skipped.out")"
351
359
  fi
@@ -364,15 +372,14 @@ const fs = require('node:fs');
364
372
  const path = require('node:path');
365
373
  const project = process.argv[2];
366
374
  const session = path.join(project, '.kontourai', 'flow-agents', 'arbitrary-session-name');
367
- const flowState = JSON.parse(fs.readFileSync(path.join(project, '.kontourai', 'flow', 'runs', 'arbitrary-session-name', 'state.json'), 'utf8'));
368
375
  const sidecar = JSON.parse(fs.readFileSync(path.join(session, 'state.json'), 'utf8'));
369
- if (flowState.subject !== 'kontourai/flow-agents#541' || flowState.current_step !== 'pull-work') process.exit(1);
370
- if (sidecar.flow_run?.current_step !== 'pull-work') process.exit(1);
376
+ if (JSON.stringify(sidecar.work_item_refs) !== JSON.stringify(['kontourai/flow-agents#541'])) process.exit(1);
377
+ if (sidecar.flow_run || fs.existsSync(path.join(project, '.kontourai', 'flow', 'runs', 'arbitrary-session-name'))) process.exit(1);
371
378
  if (fs.existsSync(path.join(session, 'trust.bundle'))) process.exit(1);
372
379
  if (!fs.existsSync(path.join(project, '.kontourai', 'flow-agents', 'assignment', 'arbitrary-session-name.json'))) process.exit(1);
373
380
  NODE
374
381
  then
375
- pass "assignment subject must canonically match the exact Work Item before pull-work can pass"
382
+ pass "private mismatched-subject seed records scope but cannot create or advance canonical Flow"
376
383
  else
377
384
  fail "mismatched assignment subject was treated as exact Work Item evidence: $(cat "$TMP/mismatched-subject.out")"
378
385
  fi
@@ -462,8 +469,7 @@ const fs = require('node:fs');
462
469
  const path = require('node:path');
463
470
  const project = process.argv[2];
464
471
  const session = path.join(project, '.kontourai', 'flow-agents', 'preexisting-selection');
465
- const flowState = JSON.parse(fs.readFileSync(path.join(project, '.kontourai', 'flow', 'runs', 'preexisting-selection', 'state.json'), 'utf8'));
466
- if (flowState.current_step !== 'pull-work') process.exit(1);
472
+ if (fs.existsSync(path.join(project, '.kontourai', 'flow', 'runs', 'preexisting-selection'))) process.exit(1);
467
473
  if (fs.existsSync(path.join(session, 'trust.bundle'))) process.exit(1);
468
474
  NODE
469
475
  then
@@ -482,12 +488,13 @@ else
482
488
  stop_status=$?
483
489
  if [[ "$stop_status" -eq 2 ]] \
484
490
  && grep -q 'required skills: pickup-probe' "$TMP/stop.err" \
485
- && grep -q 'builder-run sync' "$TMP/stop.err" \
491
+ && grep -q 'next command: sh -c' "$TMP/stop.err" \
486
492
  && grep -q 'release skipped for active Flow run' "$TMP/stop.err" \
487
493
  && node - "$LOCAL_SESSION/state.json" <<'NODE'
488
494
  const fs = require('node:fs');
489
495
  const state = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
490
496
  if (state.flow_run?.status !== 'active' || state.flow_run?.current_step !== 'design-probe') process.exit(1);
497
+ if (!state.next_action?.command?.includes("'workflow' 'status'")) process.exit(1);
491
498
  NODE
492
499
  then
493
500
  pass "active Flow run blocks Stop, preserves liveness, and exposes executable guidance"
@@ -496,31 +503,35 @@ NODE
496
503
  fi
497
504
  fi
498
505
 
499
- if flow_agents_node "$WRITER" record-gate-claim "$LOCAL_SESSION" \
506
+ printf '# Plan Work\n\nRoute-back fixture plan evidence.\n' > "$LOCAL_SESSION/local-request--plan-work.md"
507
+ printf '# Delivery\n\nRoute-back fixture execution evidence.\n' > "$LOCAL_SESSION/local-request--deliver.md"
508
+
509
+ if FLOW_AGENTS_ACTOR=builder-entry-local node "$ROOT/build/src/cli.js" workflow evidence --session-dir "$LOCAL_SESSION" \
500
510
  --expectation pickup-probe-readiness \
501
511
  --status pass \
502
512
  --summary "Pickup Probe confirmed scope and planning readiness." \
503
- --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/local-request/work-item.json","summary":"Probe fixture evidence."}' >/dev/null 2>&1 \
504
- && flow_agents_node "$WRITER" record-gate-claim "$LOCAL_SESSION" \
513
+ --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/local-request/local-request--pull-work.md","summary":"Declared pull-work fixture evidence."}' >/dev/null 2>&1 \
514
+ && FLOW_AGENTS_ACTOR=builder-entry-local node "$ROOT/build/src/cli.js" workflow evidence --session-dir "$LOCAL_SESSION" \
505
515
  --expectation probe-decisions-or-accepted-gaps \
506
516
  --status pass \
507
517
  --summary "Probe decisions and accepted gaps are recorded." \
508
- --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/local-request/work-item.json","summary":"Probe decision fixture evidence."}' >/dev/null 2>&1 \
509
- && flow_agents_node "$WRITER" record-gate-claim "$LOCAL_SESSION" \
518
+ --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/local-request/local-request--pull-work.md","summary":"Declared pull-work decision fixture evidence."}' >/dev/null 2>&1 \
519
+ && FLOW_AGENTS_ACTOR=builder-entry-local node "$ROOT/build/src/cli.js" workflow evidence --session-dir "$LOCAL_SESSION" \
510
520
  --expectation implementation-plan \
511
521
  --status pass \
512
522
  --summary "Implementation plan records files, sequence, and evidence." \
513
- --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/local-request/work-item.json","summary":"Plan fixture evidence."}' >/dev/null 2>&1 \
514
- && flow_agents_node "$WRITER" record-gate-claim "$LOCAL_SESSION" \
523
+ --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/local-request/local-request--plan-work.md","summary":"Declared plan fixture evidence."}' >/dev/null 2>&1 \
524
+ && FLOW_AGENTS_ACTOR=builder-entry-local node "$ROOT/build/src/cli.js" workflow evidence --session-dir "$LOCAL_SESSION" \
515
525
  --expectation implementation-scope \
516
526
  --status pass \
517
527
  --summary "Implementation scope and changed files are recorded." \
518
- --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/local-request/work-item.json","summary":"Execution fixture evidence."}' >/dev/null 2>&1 \
519
- && flow_agents_node "$WRITER" record-gate-claim "$LOCAL_SESSION" \
528
+ --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/local-request/local-request--deliver.md","summary":"Declared execution fixture evidence."}' >/dev/null 2>&1 \
529
+ && FLOW_AGENTS_ACTOR=builder-entry-local node "$ROOT/build/src/cli.js" workflow evidence --session-dir "$LOCAL_SESSION" \
520
530
  --expectation tests-evidence \
521
531
  --status fail \
522
532
  --route-reason implementation_defect \
523
533
  --summary "Verification found an implementation defect." \
534
+ --command false \
524
535
  --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/local-request/work-item.json","summary":"Failed verification fixture evidence."}' >"$TMP/route-back.out" 2>&1 \
525
536
  && node - "$TMP/local" "$LOCAL_SESSION" <<'NODE'
526
537
  const fs = require('node:fs');
@@ -541,6 +552,7 @@ else
541
552
  fi
542
553
 
543
554
  PROVIDER_ROOT="$TMP/provider/.kontourai/flow-agents"
555
+ seed_pull_work_report "$PROVIDER_ROOT" "kontourai-flow-agents-438" "kontourai/flow-agents#438"
544
556
  if flow_agents_node "$WRITER" ensure-session \
545
557
  --artifact-root "$PROVIDER_ROOT" \
546
558
  --work-item "kontourai/flow-agents#438" \