@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
@@ -1,35 +1,72 @@
1
1
  import { flagString, parseArgs } from "../lib/args.js";
2
- import { recoverBuilderFlowSession, startBuilderFlowSession, syncBuilderFlowSession } from "../builder-flow-runtime.js";
2
+ import { cancelBuilderFlowSession, archiveBuilderFlowSession, pauseBuilderFlowSession, recoverBuilderFlowSession, releaseBuilderFlowAssignment, resumeBuilderFlowSession, } from "../builder-flow-runtime.js";
3
+ const USAGE = "Usage: flow-agents builder-run <recover|pause|resume|cancel|release-assignment|archive> --session-dir <path> [--reason <text> | --authorization-file <path>]";
3
4
  export async function main(argv) {
4
5
  const parsed = parseArgs(argv);
5
6
  const action = parsed.positionals[0];
6
7
  const sessionDir = flagString(parsed.flags, "session-dir");
8
+ const authorizationFile = flagString(parsed.flags, "authorization-file");
9
+ const reason = flagString(parsed.flags, "reason");
7
10
  const validRecoveryArguments = parsed.positionals.length === 1
8
11
  && Object.keys(parsed.flags).length === 1
9
12
  && typeof parsed.flags["session-dir"] === "string";
10
13
  if (action === "recover" && !validRecoveryArguments) {
11
- console.error("Usage: flow-agents builder-run <start|sync|recover> --session-dir <path>");
14
+ console.error(USAGE);
12
15
  return 64;
13
16
  }
14
17
  if (!sessionDir) {
15
18
  console.error("builder-run requires --session-dir .kontourai/flow-agents/<slug>");
16
19
  return 64;
17
20
  }
18
- if (action !== "start" && action !== "sync" && action !== "recover") {
19
- console.error("Usage: flow-agents builder-run <start|sync|recover> --session-dir <path>");
21
+ if (!action || !["recover", "pause", "resume", "cancel", "release-assignment", "archive"].includes(action)) {
22
+ console.error(USAGE);
20
23
  return 64;
21
24
  }
22
- const result = action === "start"
23
- ? await startBuilderFlowSession({ sessionDir })
24
- : action === "sync"
25
- ? await syncBuilderFlowSession({ sessionDir })
26
- : await recoverBuilderFlowSession({ sessionDir });
25
+ const agentLifecycle = action === "pause" || action === "resume" || action === "release-assignment";
26
+ const authorizedLifecycle = action === "cancel" || action === "archive";
27
+ const lifecycle = agentLifecycle || authorizedLifecycle;
28
+ const allowedLifecycleFlag = (name) => name === "session-dir" || (agentLifecycle ? name === "reason" : name === "authorization-file");
29
+ if (lifecycle && (parsed.positionals.length !== 1 || Object.keys(parsed.flags).some((name) => !allowedLifecycleFlag(name)))) {
30
+ console.error(USAGE);
31
+ return 64;
32
+ }
33
+ if (agentLifecycle && !reason) {
34
+ console.error(`builder-run ${action} requires --reason <text>`);
35
+ return 64;
36
+ }
37
+ if (authorizedLifecycle && !authorizationFile) {
38
+ console.error(`builder-run ${action} requires a signed --authorization-file <path>`);
39
+ return 64;
40
+ }
41
+ if (!lifecycle && (authorizationFile || reason)) {
42
+ console.error(USAGE);
43
+ return 64;
44
+ }
45
+ const result = action === "recover"
46
+ ? await recoverBuilderFlowSession({ sessionDir })
47
+ : action === "pause"
48
+ ? await pauseBuilderFlowSession({ sessionDir, reason: reason })
49
+ : action === "resume"
50
+ ? await resumeBuilderFlowSession({ sessionDir, reason: reason })
51
+ : action === "cancel"
52
+ ? await cancelBuilderFlowSession({ sessionDir, authorizationFile: authorizationFile })
53
+ : action === "release-assignment"
54
+ ? await releaseBuilderFlowAssignment({ sessionDir, reason: reason })
55
+ : await archiveBuilderFlowSession({ sessionDir, authorizationFile: authorizationFile });
27
56
  console.log(JSON.stringify({
28
57
  run_id: result.run.runId,
29
58
  definition_id: result.run.definitionId,
30
59
  current_step: result.run.state.current_step,
31
60
  status: result.run.state.status,
32
61
  attached: result.attached,
62
+ ...(action === "cancel" ? {
63
+ assignment_released: "assignmentReleased" in result ? result.assignmentReleased : false,
64
+ idempotent: "idempotent" in result ? result.idempotent : false,
65
+ } : action === "release-assignment" ? {
66
+ assignment_released: "assignmentReleased" in result ? result.assignmentReleased : false,
67
+ } : action === "archive" ? {
68
+ archive_dir: "archiveDir" in result ? result.archiveDir : null,
69
+ } : {}),
33
70
  next_action: result.projection.next_action,
34
71
  }));
35
72
  return 0;
@@ -255,6 +255,9 @@ function classifyWorkflow(slug, workflowPath) {
255
255
  if (status === "verified" && nextStatus === "done") {
256
256
  return { ...base, classification: "cleanup_candidate", reasons: ["verified workflow has next_action.status done"] };
257
257
  }
258
+ if (status === "canceled" && phase === "done") {
259
+ return { ...base, classification: "terminal_done", reasons: ["canceled workflow retains its artifacts without requiring delivery promotion"] };
260
+ }
258
261
  if (["delivered", "accepted", "archived"].includes(status) && phase === "done") {
259
262
  if (status !== "archived" && !hasPromotionClaim(workflowPath)) {
260
263
  return { ...base, classification: "cleanup_candidate", reasons: [`${status} workflow reached phase done without a promotion claim; ${PROMOTE_REMEDY}`] };
@@ -6,6 +6,7 @@ export declare const phases: string[];
6
6
  export declare const checkKinds: Set<string>;
7
7
  export declare const checkStatuses: Set<string>;
8
8
  export declare const verdicts: Set<string>;
9
+ export declare const WORKFLOW_WRITER_CONTRACT_VERSION = "1.0";
9
10
  export declare function writeJson(file: string, payload: AnyObj): void;
10
11
  export declare function loadJson(file: string, fallback?: AnyObj): AnyObj;
11
12
  export declare function appendJsonl(file: string, payload: AnyObj): void;
@@ -173,10 +174,13 @@ export declare function reduceCaptureLogByCommand(commandLog: AnyObj[] | undefin
173
174
  * @param timestamp ISO-8601 timestamp for createdAt / updatedAt / observedAt
174
175
  * @param checks Normalized check objects (from record-evidence --check-json / --surface-trust-json)
175
176
  * @param criteria Acceptance criteria objects (from acceptance.json .criteria array)
176
- * @param critiques Critique objects (from critique.json .critiques array)
177
+ * @param critiques Critique objects reconstructed from trust.bundle claims
177
178
  * @param commandLog Optional parsed command-log.jsonl entries (capture-authoritative fold)
178
179
  */
179
- export declare function buildTrustBundle(slug: string, timestamp: string, checks: AnyObj[], criteria: AnyObj[], critiques: AnyObj[], commandLog?: AnyObj[], flowAgentsDir?: string, actorKey?: string): Promise<AnyObj | null>;
180
+ export declare function buildTrustBundle(slug: string, timestamp: string, checks: AnyObj[], criteria: AnyObj[], critiques: AnyObj[], commandLog?: AnyObj[], flowAgentsDir?: string, actorKey?: string, exactFlowContext?: {
181
+ flowId: string;
182
+ stepId: string;
183
+ }): Promise<AnyObj | null>;
180
184
  /**
181
185
  * Fail-open wrapper: builds (via Surface), validates, and writes a trust.bundle.
182
186
  * Accepts raw check/criterion/critique inputs directly (ADR 0010 Phase 4a).
@@ -190,13 +194,34 @@ export declare function buildTrustBundle(slug: string, timestamp: string, checks
190
194
  * @param criteria Acceptance criteria objects (same as buildTrustBundle)
191
195
  * @param critiques Critique objects (same as buildTrustBundle)
192
196
  */
193
- export declare function writeTrustBundle(dir: string, slug: string, timestamp: string, checks: AnyObj[], criteria: AnyObj[], critiques: AnyObj[], actorKey?: string): Promise<{
197
+ export declare function writeTrustBundle(dir: string, slug: string, timestamp: string, checks: AnyObj[], criteria: AnyObj[], critiques: AnyObj[], actorKey?: string, exactFlowContext?: {
198
+ flowId: string;
199
+ stepId: string;
200
+ }): Promise<{
194
201
  written: boolean;
195
202
  errors: string[];
196
203
  }>;
197
204
  export declare function sidecarBase(slug: string): AnyObj;
205
+ export declare function currentWorkflowSessionDir(root: string): string | null;
198
206
  export declare function validateEvidenceRef(ref: AnyObj, label: string): AnyObj;
199
207
  export declare function normalizeEvidenceRefs(raw: unknown, label: string): AnyObj[];
208
+ /** Validate test-evidence command shape without executing it. */
209
+ type TestExecutionProof = {
210
+ kind: "local-process-exit";
211
+ runner: string;
212
+ static_test_units: number;
213
+ };
214
+ /**
215
+ * Produce evidence from the locally executed command and statically reviewable
216
+ * test units. Runner stdout is deliberately excluded: any executable can print
217
+ * a Vitest/Jest-looking success summary, but it cannot turn a non-test script
218
+ * into a supported test workflow or supply this locally-created proof.
219
+ */
220
+ export declare function testExecutionProof(command: string, projectRoot: string, seenScripts?: Set<string>, packageScriptBody?: boolean): TestExecutionProof | null;
221
+ /** Validate test-evidence command shape without executing it. */
222
+ export declare function isMeaningfulTestCommand(command: string, projectRoot: string, seenScripts?: Set<string>, packageScriptBody?: boolean): boolean;
223
+ export declare function observedExecutedTestCount(output: string): number;
224
+ export declare function inferExecutedTestCount(command: string, projectRoot: string, output: string, seenScripts?: Set<string>): number;
200
225
  export declare function normalizeCheck(raw: AnyObj, allowGateClaimPrefix?: boolean, existingCheckStampById?: ReadonlyMap<string, boolean>): AnyObj;
201
226
  /**
202
227
  * Derive kit identity from a parsed trust.bundle by structurally reading the
@@ -622,3 +647,5 @@ export declare function buildGateInquiryRecords(bundle: BundleFile, blockSignal:
622
647
  export declare const LIVENESS_TERMINAL: Set<string>;
623
648
  export { buildClaimExplanation } from "./sidecar-claim-explain.js";
624
649
  export type { ClaimEvidenceItem, ClaimExplanation } from "./sidecar-claim-explain.js";
650
+ export declare function mainFromPublicWorkflow(argv: string[]): Promise<number>;
651
+ export declare function main(argv?: string[], authority?: symbol): Promise<number>;