@cassiomc1/forgeloop 1.5.0 → 1.6.1

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 (133) hide show
  1. package/CONTRACT_COVERAGE.md +1 -0
  2. package/DOCS_INDEX.md +20 -10
  3. package/EXECUTION_STATE.md +20 -0
  4. package/LOOP_ENGINEERING.md +103 -1
  5. package/LOOP_SYSTEM_DESIGN.md +32 -0
  6. package/PROTOCOL_INTEGRATION.md +90 -0
  7. package/QUALITY_SCORECARD.md +2 -0
  8. package/README.md +47 -9
  9. package/THIRD_PARTY_NOTICES.md +15 -0
  10. package/THREAT_MODEL.md +41 -1
  11. package/docs/ARTIFACT_REFERENCE.md +159 -0
  12. package/docs/CLI_REFERENCE.md +294 -3
  13. package/docs/DIAGNOSTIC_MODEL.md +181 -0
  14. package/docs/DOCUMENTATION_GUIDE.md +22 -13
  15. package/docs/EXECUTION_TRACE.md +76 -0
  16. package/docs/MCP.md +34 -1
  17. package/docs/RECIPES.md +67 -0
  18. package/docs/RELEASE_CHECKLIST_1_6_1.md +121 -0
  19. package/docs/TROUBLESHOOTING.md +133 -2
  20. package/docs/assets/diagrams/forgeloop-engineering-flow.html +13797 -0
  21. package/docs/assets/diagrams/forgeloop-engineering-flow.receipt.json +37 -0
  22. package/docs/assets/diagrams/forgeloop-engineering-flow.svg +5002 -0
  23. package/docs/diagrams/README.md +55 -0
  24. package/docs/diagrams/forgeloop-engineering-flow.workflow.json +122 -0
  25. package/docs/diagrams/manifest.json +42 -0
  26. package/docs/diagrams/reviews/forgeloop-engineering-flow.review.json +20 -0
  27. package/package.json +13 -8
  28. package/schemas/action.schema.json +100 -0
  29. package/schemas/approval.schema.json +51 -0
  30. package/schemas/capability-policy.schema.json +41 -0
  31. package/schemas/diagnostic-case.schema.json +85 -0
  32. package/schemas/execution-receipt.schema.json +16 -0
  33. package/schemas/execution.schema.json +15 -0
  34. package/schemas/hypothesis-disposition.schema.json +16 -0
  35. package/schemas/intervention.schema.json +27 -0
  36. package/schemas/policy-lock.schema.json +1 -0
  37. package/schemas/policy-snapshot.schema.json +2 -0
  38. package/schemas/trajectory-evaluation.schema.json +64 -0
  39. package/schemas/trajectory-scenario.schema.json +42 -0
  40. package/src/cli.js +94 -0
  41. package/src/commands/action-authorize.js +41 -0
  42. package/src/commands/action-propose.js +10 -0
  43. package/src/commands/action-reconcile.js +10 -0
  44. package/src/commands/action-record.js +47 -0
  45. package/src/commands/action-show.js +10 -0
  46. package/src/commands/action-verify.js +10 -0
  47. package/src/commands/advance.js +7 -2
  48. package/src/commands/approval-request.js +64 -0
  49. package/src/commands/approval-resolve.js +10 -0
  50. package/src/commands/baseline.js +3 -3
  51. package/src/commands/eval.js +6 -0
  52. package/src/commands/history.js +18 -0
  53. package/src/commands/init.js +2 -2
  54. package/src/commands/inspect.js +49 -0
  55. package/src/commands/metrics.js +7 -0
  56. package/src/commands/next.js +8 -2
  57. package/src/commands/policy-discover.js +2 -2
  58. package/src/commands/record-diagnosis.js +37 -1
  59. package/src/commands/record-hypothesis-disposition.js +45 -0
  60. package/src/commands/record-intervention.js +35 -0
  61. package/src/commands/reflect.js +38 -0
  62. package/src/commands/report.js +9 -1
  63. package/src/commands/run-action.js +18 -0
  64. package/src/commands/run-check.js +1 -0
  65. package/src/commands/trace.js +34 -0
  66. package/src/commands/validate-protocol.js +21 -13
  67. package/src/core/action-authorization.js +106 -0
  68. package/src/core/action-constants.js +86 -0
  69. package/src/core/action-execution.js +106 -0
  70. package/src/core/action-ledger-projection.js +302 -0
  71. package/src/core/action-model.js +581 -0
  72. package/src/core/action-readiness.js +141 -0
  73. package/src/core/action-reconciliation-policy.js +49 -0
  74. package/src/core/action-reconciliation.js +66 -0
  75. package/src/core/action-verification.js +111 -0
  76. package/src/core/actions.js +462 -0
  77. package/src/core/approvals.js +405 -0
  78. package/src/core/artifact-registry.js +48 -0
  79. package/src/core/audit.js +25 -0
  80. package/src/core/bundles.js +15 -0
  81. package/src/core/capability-policy.js +226 -0
  82. package/src/core/cli-command-definitions.js +210 -1
  83. package/src/core/command-executors.js +171 -15
  84. package/src/core/command-runtime.js +12 -1
  85. package/src/core/completion-artifacts.js +71 -14
  86. package/src/core/completion-recovery-rebind.js +194 -0
  87. package/src/core/completion.js +70 -0
  88. package/src/core/continuity-reconciliation.js +24 -5
  89. package/src/core/diagnostic-model.js +396 -0
  90. package/src/core/diagnostic-projection.js +51 -0
  91. package/src/core/diagnostic-record.js +360 -0
  92. package/src/core/error-codes.js +363 -0
  93. package/src/core/events.js +41 -1
  94. package/src/core/execution-prerequisites.js +4 -1
  95. package/src/core/execution.js +29 -188
  96. package/src/core/failure-signature.js +70 -0
  97. package/src/core/failure-surface.js +57 -0
  98. package/src/core/history.js +110 -0
  99. package/src/core/hypothesis-projection.js +85 -0
  100. package/src/core/information-gain-projection.js +283 -0
  101. package/src/core/information-gain.js +138 -0
  102. package/src/core/inspect.js +105 -7
  103. package/src/core/integration-invocation-policy.js +55 -0
  104. package/src/core/integration-resources.js +51 -0
  105. package/src/core/next-action-model.js +35 -1
  106. package/src/core/next-action.js +459 -3
  107. package/src/core/phase.js +40 -21
  108. package/src/core/policy-engine.js +113 -6
  109. package/src/core/preflight-consistency.js +31 -5
  110. package/src/core/preflight.js +19 -2
  111. package/src/core/prepared-execution.js +256 -0
  112. package/src/core/progress.js +41 -4
  113. package/src/core/protocol-info.js +56 -0
  114. package/src/core/protocol.js +14 -0
  115. package/src/core/receipt.js +1 -0
  116. package/src/core/reconcile-closure.js +15 -12
  117. package/src/core/reflection.js +305 -0
  118. package/src/core/resumability.js +57 -3
  119. package/src/core/runtime-context.js +19 -1
  120. package/src/core/schema-validation.js +8 -0
  121. package/src/core/strategy-analysis.js +97 -0
  122. package/src/core/task-paths.js +28 -0
  123. package/src/core/task-snapshot.js +53 -0
  124. package/src/core/templates.js +8 -0
  125. package/src/core/trace.js +548 -0
  126. package/src/core/trajectory-evaluation.js +71 -0
  127. package/src/core/trajectory-metrics.js +80 -0
  128. package/src/core/transaction.js +8 -0
  129. package/src/core/verification-execution.js +257 -0
  130. package/src/core/work-state.js +10 -5
  131. package/src/integration.js +8 -0
  132. package/docs/assets/forgeloop-flow.svg +0 -1
  133. package/docs/forgeloop-flow.mmd +0 -51
package/THREAT_MODEL.md CHANGED
@@ -8,6 +8,45 @@ not an agent runtime. It does not execute commands found in those files, call
8
8
  an LLM, or publish on behalf of a target. The controls below describe the
9
9
  remaining trust boundaries and their executable evidence.
10
10
 
11
+ ## Durable action boundary
12
+
13
+ Durable actions make external side effects explicit, but they do not make an
14
+ arbitrary remote system transactional. Side-effecting actions require an
15
+ immutable idempotency key; `COMMIT_UNKNOWN` forbids automatic retry and can be
16
+ resolved only by explicit reconciliation. Capability policy is project-local
17
+ configuration and never creates `HOST_ATTESTED` authority. Current capability
18
+ policy is the source of truth for guidance only after its identity is bound to
19
+ the active policy epoch: historical approvals are consulted
20
+ only when the current policy returns `REQUIRE_APPROVAL`. Approvals bind to the
21
+ action fingerprint, contract fingerprint, task revision, and capability; drift
22
+ makes them stale. Host-bound authorization is exposed as structured guidance
23
+ with no standalone CLI command that could lose the trusted context. `run-action`
24
+ accepts exact argv with `shell: false`, and host-reported actions remain distinct
25
+ from ForgeLoop-executed actions.
26
+
27
+ Residual limitation: ForgeLoop cannot atomically commit local protocol state
28
+ and an arbitrary external system in one transaction. Idempotency, durable
29
+ intent, evidence, and reconciliation reduce duplicate-effect risk but do not
30
+ provide a universal exactly-once guarantee.
31
+
32
+ ### Hardened durable-action threats (T-DURABLE-01 … T-DURABLE-13)
33
+
34
+ | ID | Threat | Mitigation | Test evidence |
35
+ | --- | --- | --- | --- |
36
+ | T-DURABLE-01 | Caller walks `PROPOSED -> AUTHORIZED -> STARTED -> COMMITTED -> VERIFIED` through the generic record surface | Generic transitions refuse `AUTHORIZED`/`VERIFIED`; dedicated core services own those transitions and require complete policy-bound or canonical-evidence details | `tests/action-security.test.js`, `tests/action-authorization.test.js`, `tests/action-cli.test.js` |
37
+ | T-DURABLE-02 | Actor marks an externally committed action `NOT_COMMITTED` to enable a duplicate retry | Settling `COMMITTED`/`NOT_COMMITTED` requires trusted out-of-band host attestation plus bounded evidence; actor observations may only record `UNKNOWN` | `tests/action-reconciliation.test.js`, `tests/integration-authority-context.test.js` |
38
+ | T-DURABLE-03 | Actor weakens `capabilities.json` immediately before an action launch | Current capability policy must match the persisted policy lock and task policy snapshot before authorization; drift fails closed before `ACTION_STARTED` (`E_ACTION_POLICY_DRIFT`) | `tests/action-authorization.test.js`, `tests/policy-lock.test.js` |
39
+ | T-DURABLE-04 | Model places `authorityContext` inside tool arguments or command input | Authority context is a separate host-provided parameter excluded from command input schemas; MCP tool registries strip it from args and accept it only from an embedding-controlled provider | `tests/integration-authority-context.test.js`, `integrations/mcp/tests/authority-context.test.js` |
40
+ | T-DURABLE-05 | Command validation failures are misclassified as external ambiguity | Deterministic pre-launch preparation runs before authorization; `ACTION_STARTED` is recorded only after argv normalization, resolution, installation authority, policy identity, and approval validation succeed, so pre-launch failure leaves the action `PROPOSED` with no ambiguity | `tests/run-action.test.js`, `tests/durable-action-hardening.test.js` |
41
+ | T-DURABLE-06 | Exit code 0 is mistaken for verified external state | `COMMITTED` and `VERIFIED` remain separate states; verification requires an independent passed ForgeLoop execution artifact and rejects the action's own commit execution as evidence | `tests/action-verification.test.js`, `tests/action-readiness.test.js` |
42
+ | T-DURABLE-07 | Partial ledger forgery: artifact edits or incomplete transition-like events | Deterministic ledger replay validates revision continuity, fingerprint constancy, legal chronology, modern authorization/verification evidence, reconciliation ordering, and artifact/projection equivalence during audit and completion | `tests/action-ledger-replay.test.js`, `tests/action-security.test.js` |
43
+ | T-DURABLE-08 | Reconciliation mirror replay confusion: one settlement is represented by two events and replay double-applies it | `ACTION_RECONCILED(outcome=COMMITTED)` owns the transition; a following `ACTION_COMMIT_RECORDED(reconciled=true)` is validated as a same-revision non-transition mirror and never increments state/revision; mismatched or orphaned mirrors invalidate the ledger | `tests/action-ledger-replay.test.js`, `tests/durable-action-chains.test.js` |
44
+ | T-DURABLE-09 | Cross-requirement verification substitution: a passed check for requirement A verifies action requirement B | Verification evidence must be an independent passed execution whose immutable `requirement` exactly equals the action's requirement; new required actions cannot omit their requirement | `tests/action-verification.test.js`, `tests/durable-action-chains.test.js`, `tests/action-readiness.test.js` |
45
+ | T-DURABLE-10 | Authority dropped between host and reconciliation core: trusted host supplies authority but an adapter discards it | Top-level `authorityContext` propagates through every command executor (including `action-reconcile` and `action-authorize`) to the core service; actor-controlled input remains stripped and cannot mint trust | `tests/integration-authority-context.test.js`, `integrations/mcp/tests/authority-context.test.js` |
46
+ | T-DURABLE-11 | Post-authorization approval mutation: the approval artifact changes after its fingerprint was bound into `ACTION_AUTHORIZED` | Readiness and audit recompute the canonical approval fingerprint via `validateBoundApprovalFingerprint()` for `REQUIRE_APPROVAL` authorizations; any mismatch yields UNTRUSTED / invalid audit | `tests/approval-fingerprint-integrity.test.js` |
47
+ | T-DURABLE-12 | Stale approval precedence: a pending approval created under an older policy blocks, resurrects, or obscures the current decision | `next` selects the required `PROPOSED` action and evaluates current capability policy first; only `REQUIRE_APPROVAL` validates the approval binding tuple before resolving it. `ALLOW`, `DENY`, and `REQUIRE_AUTHORITY` ignore historical approval state, while `approval-request` refuses unnecessary or weaker approvals | `tests/next-action-policy-guidance.test.js`, `tests/approval-request-policy.test.js` |
48
+ | T-DURABLE-13 | Guidance or approval creation trusts a modified `capabilities.json` before checking the active task policy epoch | `next`, `approval-request`, and `action-authorize` all validate the canonical `loadPolicyIdentity()` result before capability decisions can produce authorization-related behavior; drift fails closed with `E_ACTION_POLICY_DRIFT` and no approval artifact is persisted | `tests/next-action-policy-guidance.test.js`, `tests/approval-request-policy.test.js`, `tests/action-authorization.test.js` |
49
+
11
50
  | Threat | Impact | Trust boundary | Mitigation | Residual limitation | Test evidence |
12
51
  | --- | --- | --- | --- | --- | --- |
13
52
  | Path traversal | Writes or reads outside the selected target | Target path and every managed relative path | `ensureWithin`, safe-path checks, realpath containment, Windows-drive rejection | A separately privileged process can change the filesystem after validation | `tests/core.test.js`, `tests/portability.test.js`, `tests/fixtures/protocol/invalid/path-traversal.json` |
@@ -42,6 +81,7 @@ remaining trust boundaries and their executable evidence.
42
81
  | Unsupported profile fact | Turns an agent decision into a durable user fact | `PROJECT_PROFILE.md` and `.forgeloop/sources.json` | Source IDs, source-kind validation, unknown-reference rejection, and explicit misclassification failures | Arbitrary Markdown semantics still require a human or host-specific parser | `tests/profile-provenance.test.js`, `src/core/profile.js` |
43
82
  | Weak verification | Treats a vague or inferred claim as observed evidence | Receipt checks and coverage | Versioned check schema, contradictory-status rejection, observed-evidence requirements, and coverage matrix | Evidence remains local and declarative; it is not a remote attestation service | `tests/evidence-coverage.test.js`, `tests/completion.test.js` |
44
83
  | Unattested observed command | An actor supplies `--command "..."` or forged command metadata and makes an unrun process appear to be observed evidence | Check provenance, execution artifact, and process boundary | `run-check` captures exact argv, cwd, resolution, timestamps, exit status, and task/check binding; it classifies before launch, uses `shell: false`, and rejects install-capable resolution without trusted authority. `record-check --command` is metadata only; command `OBSERVED` checks require `FORGELOOP_EXECUTED` plus a valid `executionRef`; completion, audit, protocol validation, and bundles revalidate it | The local execution artifact is not cryptographic remote attestation, and a separately privileged process can alter the target after execution | `tests/run-check.test.js`, `tests/completion-cli.test.js`, `tests/verification-capability.test.js`, `tests/validate-protocol-cli.test.js` |
84
+ | Contradictory execution isolation metadata | A custom execution adapter reports guarantees the host does not enforce, for example `NATIVE_PROJECT` claiming `isolated=true`, an isolated mode claiming `liveProjectWritable=true`, or `SYSTEM_ISOLATED` claiming inherited network access | Verification execution adapter boundary and execution evidence | Adapter results are normalized and validated before evidence persistence: canonical mode/guarantee invariants are intrinsically enforced, isolated execution must use a cwd separate from the protocol project root, and violations fail closed with `E_VERIFICATION_EXECUTION_INVALID` or `E_VERIFICATION_ISOLATION_UNAVAILABLE` | The isolation report is still host-supplied; ForgeLoop validates coherence and policy satisfaction, not the underlying OS enforcement | `tests/verification-execution-isolation.test.js` |
45
85
  | Malicious receipt | Turns local claims into false publication or completion claims | Execution receipt JSON | Semantic evidence checks for completion, checks, review, push, commit, and deployment; explicit publication booleans | Evidence text is declarative and must still be reviewed for provenance | `tests/receipt-semantics.test.js`, `tests/observability.test.js` |
46
86
  | Malicious task brief | Grants a child task more authority than intended | Delegation brief JSON and host harness | Relative path boundaries, guide/verification/authority checks, secret-free validation, set validation, parent integration ownership | The host harness remains responsible for OS permissions and execution policy | `tests/delegation.test.js`, `tests/delegation-set.test.js` |
47
87
  | Artifact content exposure | Sensitive material enters portable artifacts or diagnostics | State, receipt, delegation, evidence, and repository text | Nested key/value detection, shaped marker patterns, scanner coverage, no content echo in errors | Content scanners cannot prove that an unknown encoding is harmless | `tests/security-limits.test.js`, `tests/test_scan_secrets.py`, `scripts/scan_secrets.py` |
@@ -62,7 +102,7 @@ remaining trust boundaries and their executable evidence.
62
102
  | Environment-injected trust root | The active actor creates an authority file outside the project target and sets `FORGELOOP_AUTHORITY_FILE` or `FORGELOOP_AUTHORITY_DIR` when invoking ForgeLoop | Actor-controlled process environment versus host-attested runtime authority | Standalone CLI uses `trustMode: NONE`; environment-selected sources are metadata/candidates only and fail with `E_AUTHORITY_UNTRUSTED_SOURCE`; trusted authority requires an internal `HOST_ATTESTED` context not exposed as a self-assertable CLI option | If the host integration allows the actor to mutate or replace the attested source/context, the host trust boundary is compromised | Environment-injection rejection, standalone audit/complete rejection, host-attested positive path |
63
103
  | Stale receipt recovery dead-end | Work state changes after preparing a receipt, leaving a mismatch that cannot be refreshed because the old receipt is rejected during re-preparation | Preparation lifecycle and recovery action resolution | Recoverable stale receipt binding in `prepareCompletion`, executable `PREPARE_COMPLETION` return from `next`, atomic refresh of stateFingerprint and changedPaths | Manual file corruption outside CLI commands requires manual diagnostic recovery | `tests/stale-receipt-recovery.test.js`, `tests/next-executability.test.js` |
64
104
  | Recursive npm script dispatch | A recognized npm lifecycle script invokes another npm script, which later invokes an installation-capable resolver (e.g. `test` -> `npm run visual` -> `npx package`) | Recognized npm dispatcher semantics before ForgeLoop process launch | Recursive npm-script resolution with cycle detection, maximum depth (16), lifecycle hook inspection, restart special semantics, and fail-closed behavior when the resolver cannot prove the chain is non-installing | Opaque executables may spawn arbitrary descendants. Full descendant-process attestation requires host-level process controls and is outside this release | `tests/run-check.test.js`, `tests/verification-capability.test.js` |
65
- | npm invocation rewriting and workspace dispatch | npm configuration flags appear before the subcommand, or npm workspace selectors cause script execution to occur against a package.json different from the ForgeLoop target root | Raw npm argv versus effective npm command and execution context | Canonical npm invocation parsing, effective subcommand extraction, workspace flag detection across the full npm argv, and fail-closed workspace script handling when the selected package.json cannot be proven from the current target | ForgeLoop 0.1.15 intentionally does not implement full npm workspace resolution. Users should execute run-check from the selected workspace target directory | `tests/run-check.test.js`, `tests/verification-capability.test.js` |
105
+ | npm invocation rewriting and workspace dispatch | npm configuration flags appear before the subcommand, or npm workspace selectors cause script execution to occur against a package.json different from the ForgeLoop target root | Raw npm argv versus effective npm command and execution context | Canonical npm invocation parsing, effective subcommand extraction, workspace flag detection across the full npm argv, and fail-closed workspace script handling when the selected package.json cannot be proven from the current target | ForgeLoop intentionally does not implement full npm workspace resolution. Users should execute run-check from the selected workspace target directory | `tests/run-check.test.js`, `tests/verification-capability.test.js` |
66
106
  | Unclassified npm Install-Capable Command | The npm security classifier recognizes only a small denylist of package-mutating commands. Another official npm command or alias with install/update/bootstrap semantics falls through as a local package command | Effective npm command semantics versus ForgeLoop's command classifier | Semantic npm command classification with explicit install-capable families, explicit script-dispatch families, a deliberately small non-installing allowlist, and fail-closed behavior for unknown or ambiguous npm commands | Future npm commands are blocked until ForgeLoop explicitly classifies them | `tests/verification-capability.test.js`, `tests/run-check.test.js` |
67
107
  | Policy weakening bypass | An actor weakens complexity or security thresholds mid-task to bypass verification failures | Task policy snapshot (`policy-snapshot.json`) and semantic policy diff | `policy-diff` classifies rule relaxations as `WEAKEN`, preflight snapshots enforce baseline digests, and `complete` blocks on `E_POLICY_WEAKENING` | A project operator with local filesystem access can authoritatively update project rules | `tests/policy-autonomy.test.js`, `tests/policy-hardening.test.js` |
68
108
  | Inert check evasion | An actor relies on an inert or non-matching checker to create false verification pass | Policy engine checker inspection | Scanned file counters and adapter target checks; unproven or inert project rules trigger `E_CHECK_INERT` | Discovered rules gracefully downgrade to advisory without stopping execution | `tests/policy-autonomy.test.js`, `tests/policy-hardening.test.js` |
@@ -31,6 +31,10 @@ All artifact schemas are defined in `schemas/*.schema.json`. Persisted artifact
31
31
  | `policy/policy.lock` | `policy-lock` | Protocol Generated | Atomic Digest Compilation | Policy Integrity Lock |
32
32
  | `task-state/<task-key>/policy-snapshot.json` | `policy-snapshot` | Protocol Generated | Mutable Before Execution | Task Policy Attestation |
33
33
  | `task-state/<task-key>/recovery.json` | `task-recovery` | Protocol Generated | Recovery State Transitions | Task Recovery State |
34
+ | `task-state/<task-key>/actions/action-<id>.json` | `action` | Protocol Managed | State Machine Transitions | External Action Provenance |
35
+ | `task-state/<task-key>/approvals/approval-<id>.json` | `approval` | Protocol Managed | Append Decision Once | Action Approval Attestation |
36
+ | `policy/capabilities.json` | `capability-policy` | Operator Or Agent | Mutable Configuration | Capability Policy Specification |
37
+ | `task-state/<task-key>/evaluations/eval-<id>.json` | `trajectory-evaluation` | Protocol Compiled | Immutable Once Written | Trajectory Evaluation |
34
38
 
35
39
  <!-- END FORGELOOP GENERATED: artifact-registry -->
36
40
 
@@ -371,6 +375,16 @@ The cryptographically compiled verification receipt required for task completion
371
375
  - `selectedGuides` *(array<string>, required)*
372
376
  - `changedPaths` *(array<string>, required)*
373
377
  - `checks` *(array<object>, required)*
378
+ - `actions` *(object, optional)*
379
+ - `count` *(integer, required, minimum: 0)*
380
+ - `required` *(integer, required, minimum: 0)*
381
+ - `verified` *(integer, required, minimum: 0)*
382
+ - `trustedSatisfied` *(integer, optional, minimum: 0)*
383
+ - `unresolvedRequired` *(integer, optional, minimum: 0)*
384
+ - `failed` *(integer, required, minimum: 0)*
385
+ - `ambiguous` *(integer, required, minimum: 0)*
386
+ - `pending` *(integer, required, minimum: 0)*
387
+ - `actionRefs` *(array<string>, required)*
374
388
  - `evidence` *(array<object>, optional)*
375
389
  - `schemaVersion` *(number, optional, const: 1)*
376
390
  - `kind` *(string, required, enum: `OBSERVED`, `INFERRED`, `NOT_VERIFIED`, `BLOCKED`)*
@@ -409,8 +423,17 @@ Attested command execution provenance artifact generated by `forgeloop run-check
409
423
  - `requirement` *(string, required, minLength: 1)*
410
424
  - `verificationCycle` *(integer, required, minimum: 1)*
411
425
  - `kind` *(string, required, const: `COMMAND_EXECUTION`)*
426
+ - `executionKind` *(string, optional, enum: `VERIFICATION`, `DURABLE_ACTION`)*
412
427
  - `argv` *(array<string>, required, minItems: 1)*
428
+ - `protocolProjectRoot` *(string, optional, minLength: 1)*
413
429
  - `cwd` *(string, required, minLength: 1)*
430
+ - `executionIsolation` *(string, optional, enum: `NATIVE_PROJECT`, `PROJECT_ISOLATED`, `SYSTEM_ISOLATED`)*
431
+ - `isolation` *(object, optional)*
432
+ - `mode` *(string, required, enum: `NATIVE_PROJECT`, `PROJECT_ISOLATED`, `SYSTEM_ISOLATED`)*
433
+ - `isolated` *(boolean, required)*
434
+ - `liveProjectWritable` *(boolean, required)*
435
+ - `networkPolicy` *(string, required, minLength: 1)*
436
+ - `environmentPolicy` *(string, required, minLength: 1)*
414
437
  - `resolution` *(object, required)*
415
438
  - `resolutionMode` *(string, required, minLength: 1)*
416
439
  - `mayInstall` *(boolean, required)*
@@ -436,6 +459,16 @@ Attested command execution provenance artifact generated by `forgeloop run-check
436
459
 
437
460
  <!-- END FORGELOOP GENERATED: schema:execution -->
438
461
 
462
+ Isolation metadata must be intrinsically truthful. `liveProjectWritable` is an
463
+ enforced host guarantee reported by the trusted execution adapter, not a claim
464
+ implied by a different working directory; a disposable copy alone is
465
+ insufficient. Canonical combinations are `NATIVE_PROJECT` (`isolated=false`,
466
+ `liveProjectWritable=true`), `PROJECT_ISOLATED` (`isolated=true`,
467
+ `liveProjectWritable=false`), and `SYSTEM_ISOLATED` (`isolated=true`,
468
+ `liveProjectWritable=false`, `networkPolicy=DENIED`). Contradictory metadata is
469
+ rejected with `E_VERIFICATION_EXECUTION_INVALID` before the execution artifact
470
+ is persisted, even when the required isolation policy would be `NONE`.
471
+
439
472
  ---
440
473
 
441
474
  ### 2.13 `task-state/<taskKey>/task.json`
@@ -571,6 +604,7 @@ silently ignored.
571
604
  - `digest` *(string, required, minLength: 1)*
572
605
  - `rulesDigest` *(string, required)*
573
606
  - `baselineDigest` *(string, required)*
607
+ - `capabilityPolicyDigest` *(string, optional, pattern: `^sha256:[a-f0-9]{64}$`)*
574
608
  - `capturedAt` *(string, optional)*
575
609
 
576
610
  <!-- END FORGELOOP GENERATED: schema:policy-lock -->
@@ -599,6 +633,8 @@ comparison explicitly `UNKNOWN` rather than assuming an empty baseline.
599
633
  - `rules` *(array<string,object>, required)*
600
634
  - `baseline` *(object, optional)*
601
635
  - `baselineDigest` *(string, optional)*
636
+ - `capabilityPolicyDigest` *(string, optional, pattern: `^sha256:[a-f0-9]{64}$`)*
637
+ - `capabilityPolicyFingerprint` *(string, optional, pattern: `^[a-f0-9]{64}$`)*
602
638
  - `capturedAt` *(string, optional)*
603
639
 
604
640
  <!-- END FORGELOOP GENERATED: schema:policy-snapshot -->
@@ -644,3 +680,126 @@ host-owned `grantRef`; the standalone CLI does not self-issue that authority.
644
680
  - `grantRef` *(string, optional, minLength: 1)*
645
681
 
646
682
  <!-- END FORGELOOP GENERATED: schema:task-recovery -->
683
+
684
+ ---
685
+
686
+ ### 2.20 `task-state/<taskKey>/actions/action-<id>.json`
687
+
688
+ <!-- forgeloop-doc: schema=action artifact=.forgeloop/task-state/<task-key>/actions/action-<id>.json -->
689
+
690
+ Durable external action artifact recording intent, capability policy binding,
691
+ authority, execution provenance, ambiguity, and reconciliation state for a
692
+ side-effecting operation. The `actionFingerprint` covers immutable identity
693
+ fields only; mutable state lives in `state` and `revision`.
694
+
695
+ #### Canonical Fields
696
+
697
+ <!-- BEGIN FORGELOOP GENERATED: schema:action -->
698
+
699
+ - `schemaVersion` *(number, required, const: 1)*
700
+ - `taskId` *(string, required, minLength: 1, maxLength: 256)*
701
+ - `actionId` *(string, required, pattern: `^action-[A-Za-z0-9_-]+$`)*
702
+ - `actionFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
703
+ - `effectClass` *(string, required, enum: `READ_ONLY`, `REVERSIBLE_WRITE`, `IRREVERSIBLE_WRITE`, `EXTERNAL_PUBLICATION`, `DESTRUCTIVE`)*
704
+ - `capability` *(string, required, enum: `filesystem.read`, `filesystem.write`, `process.execute`, `dependency.install`, `network.read`, `network.write`, `repository.commit`, `repository.push`, `repository.pull_request`, `external.publish`, `external.delete`, `deployment.execute`)*
705
+ - `operation` *(string, required, minLength: 1, maxLength: 512)*
706
+ - `target` *(string, required, minLength: 1, maxLength: 512)*
707
+ - `idempotencyKey` *(string or null, required)*
708
+ - `requiredForCompletion` *(boolean, required)*
709
+ - `requirement` *(string or null, required)*
710
+ - `provenance` *(string, required, enum: `FORGELOOP_EXECUTED`, `HOST_ATTESTED`, `CALLER_REPORTED`, `HOST_REPORTED`, `EXTERNAL_OBSERVED`)*
711
+ - `state` *(string, required, enum: `PROPOSED`, `AUTHORIZED`, `STARTED`, `COMMITTED`, `VERIFIED`, `FAILED`, `COMMIT_UNKNOWN`, `CANCELLED`)*
712
+ - `revision` *(integer, required, minimum: 0)*
713
+ - `createdAt` *(string, required, minLength: 1)*
714
+ - `updatedAt` *(string, required, minLength: 1)*
715
+ - `lastEvidenceRef` *(string or null, optional)*
716
+ - `lastReconciliationAt` *(string or null, optional)*
717
+ - `commitResultCode` *(object or null, optional)*
718
+
719
+ <!-- END FORGELOOP GENERATED: schema:action -->
720
+
721
+ ---
722
+
723
+ ### 2.21 `task-state/<taskKey>/approvals/approval-<id>.json`
724
+
725
+ <!-- forgeloop-doc: schema=approval artifact=.forgeloop/task-state/<task-key>/approvals/approval-<id>.json -->
726
+
727
+ Crash-safe durable approval request cryptographically bound to the exact action
728
+ fingerprint, contract fingerprint, task revision, and capability. Any drift
729
+ makes the approval stale. Resolution is one-time; approvals persist across
730
+ process and harness boundaries.
731
+
732
+ #### Canonical Fields
733
+
734
+ <!-- BEGIN FORGELOOP GENERATED: schema:approval -->
735
+
736
+ - `schemaVersion` *(number, required, const: 1)*
737
+ - `taskId` *(string, required, minLength: 1, maxLength: 256)*
738
+ - `approvalId` *(string, required, pattern: `^approval-[A-Za-z0-9_-]+$`)*
739
+ - `actionId` *(string, required, pattern: `^action-[A-Za-z0-9_-]+$`)*
740
+ - `actionFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
741
+ - `contractFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
742
+ - `taskRevision` *(integer, required, minimum: 0)*
743
+ - `capability` *(string, required, enum: `filesystem.read`, `filesystem.write`, `process.execute`, `dependency.install`, `network.read`, `network.write`, `repository.commit`, `repository.push`, `repository.pull_request`, `external.publish`, `external.delete`, `deployment.execute`)*
744
+ - `status` *(string, required, enum: `PENDING`, `APPROVED`, `REJECTED`)*
745
+ - `requestedAt` *(string, required, minLength: 1)*
746
+ - `reason` *(string or null, optional)*
747
+ - `decision` *(string, optional, enum: `APPROVED`, `REJECTED`)*
748
+ - `resolvedAt` *(string or null, optional)*
749
+ - `authorityKind` *(string, optional, enum: `CALLER_ACKNOWLEDGED`, `HOST_ATTESTED`)*
750
+ - `hostGrantRef` *(string or null, optional)*
751
+
752
+ <!-- END FORGELOOP GENERATED: schema:approval -->
753
+
754
+ ---
755
+
756
+ ### 2.22 `policy/capabilities.json`
757
+
758
+ <!-- forgeloop-doc: schema=capability-policy artifact=.forgeloop/policy/capabilities.json -->
759
+
760
+ Project-local machine-readable capability policy mapping canonical capability
761
+ values to ALLOW, DENY, REQUIRE_AUTHORITY, or REQUIRE_APPROVAL decisions. This
762
+ artifact is policy specification only; it can never mint host authority.
763
+
764
+ #### Canonical Fields
765
+
766
+ <!-- BEGIN FORGELOOP GENERATED: schema:capability-policy -->
767
+
768
+ - `schemaVersion` *(number, required, const: 1)*
769
+ - `defaultDecision` *(string, required, enum: `ALLOW`, `DENY`)*
770
+ - `rules` *(array<object>, required)*
771
+ - `capability` *(string, required, enum: `filesystem.read`, `filesystem.write`, `process.execute`, `dependency.install`, `network.read`, `network.write`, `repository.commit`, `repository.push`, `repository.pull_request`, `external.publish`, `external.delete`, `deployment.execute`)*
772
+ - `decision` *(string, required, enum: `ALLOW`, `DENY`, `REQUIRE_AUTHORITY`, `REQUIRE_APPROVAL`)*
773
+
774
+ <!-- END FORGELOOP GENERATED: schema:capability-policy -->
775
+
776
+ ---
777
+
778
+ ### 2.23 `task-state/<taskKey>/evaluations/eval-<id>.json`
779
+
780
+ <!-- forgeloop-doc: schema=trajectory-evaluation artifact=.forgeloop/task-state/<task-key>/evaluations/eval-<id>.json -->
781
+
782
+ Immutable trajectory evaluation result compiled from the canonical trace against
783
+ a project-local reference scenario. Evaluations are projections over canonical
784
+ evidence and never override lifecycle validation.
785
+
786
+ #### Canonical Fields
787
+
788
+ <!-- BEGIN FORGELOOP GENERATED: schema:trajectory-evaluation -->
789
+
790
+ - `schemaVersion` *(number, required, const: 1)*
791
+ - `evaluationId` *(string, required, pattern: `^eval-[A-Za-z0-9_-]+$`)*
792
+ - `scenarioId` *(string, required, minLength: 1, maxLength: 128)*
793
+ - `scenarioFingerprint` *(string, optional, pattern: `^[a-f0-9]{64}$`)*
794
+ - `taskId` *(string, required, minLength: 1, maxLength: 256)*
795
+ - `result` *(string, required, enum: `PASS`, `FAIL`)*
796
+ - `completionValid` *(boolean, required)*
797
+ - `safetyValid` *(boolean, required)*
798
+ - `missingMilestones` *(array<string>, optional)*
799
+ - `limits` *(object, optional)*
800
+ - `efficiency` *(object or null, optional)*
801
+ - `computedAt` *(string, optional, minLength: 1)*
802
+ - `source` *(string, optional, enum: `PROJECT_LOCAL_REFERENCE`)*
803
+ - `evaluationFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
804
+
805
+ <!-- END FORGELOOP GENERATED: schema:trajectory-evaluation -->
@@ -39,11 +39,12 @@ ForgeLoop uses a definition-driven command-line parser:
39
39
 
40
40
  | Category | Commands |
41
41
  | --- | --- |
42
- | **Inspection & Diagnostics** | [`protocol-info`](#protocol-info), [`doctor`](#doctor), [`progress`](#progress), [`profile-interview`](#profile-interview), [`inspect`](#inspect), [`status`](#status), [`validate-state`](#validate-state), [`validate-protocol`](#validate-protocol) |
42
+ | **Inspection & Diagnostics** | [`protocol-info`](#protocol-info), [`doctor`](#doctor), [`metrics`](#metrics), [`eval`](#eval), [`history`](#history), [`trace`](#trace), [`reflect`](#reflect), [`progress`](#progress), [`profile-interview`](#profile-interview), [`inspect`](#inspect), [`status`](#status), [`validate-state`](#validate-state), [`validate-protocol`](#validate-protocol) |
43
43
  | **Setup & Maintenance** | [`init`](#init), [`update`](#update), [`task-migrate`](#task-migrate), [`migrate-protocol`](#migrate-protocol), [`task-unlock`](#task-unlock), [`task-recover`](#task-recover), [`task-repair-legacy-recovery`](#task-repair-legacy-recovery), [`task-resume`](#task-resume) |
44
- | **Lifecycle & State** | [`activate`](#activate), [`route`](#route), [`preflight`](#preflight), [`advance`](#advance), [`next`](#next), [`record-diagnosis`](#record-diagnosis), [`record-decision-criterion`](#record-decision-criterion), [`complete`](#complete), [`clear-state`](#clear-state), [`reconcile-closure`](#reconcile-closure), [`task-create`](#task-create), [`task-list`](#task-list), [`task-show`](#task-show), [`task-lock-status`](#task-lock-status), [`task-scope`](#task-scope) |
44
+ | **Lifecycle & State** | [`activate`](#activate), [`route`](#route), [`preflight`](#preflight), [`advance`](#advance), [`next`](#next), [`record-diagnosis`](#record-diagnosis), [`record-intervention`](#record-intervention), [`record-hypothesis-disposition`](#record-hypothesis-disposition), [`record-decision-criterion`](#record-decision-criterion), [`complete`](#complete), [`clear-state`](#clear-state), [`reconcile-closure`](#reconcile-closure), [`task-create`](#task-create), [`task-list`](#task-list), [`task-show`](#task-show), [`task-lock-status`](#task-lock-status), [`task-scope`](#task-scope) |
45
45
  | **Cross-Harness Continuity** | [`continuity`](#continuity), [`record-continuity`](#record-continuity), [`reconcile-continuity`](#reconcile-continuity), [`clear-continuity`](#clear-continuity) |
46
46
  | **Verification & Completion** | [`prepare-completion`](#prepare-completion), [`run-check`](#run-check), [`record-check`](#record-check), [`record-terminal-result`](#record-terminal-result), [`audit`](#audit), [`report`](#report), [`validate-receipt`](#validate-receipt) |
47
+ | **Durable Actions & Approvals** | [`run-action`](#run-action), [`action-propose`](#action-propose), [`action-record`](#action-record), [`action-show`](#action-show), [`action-reconcile`](#action-reconcile), [`action-verify`](#action-verify), [`action-authorize`](#action-authorize), [`approval-request`](#approval-request), [`approval-resolve`](#approval-resolve) |
47
48
  | **Policy & Auditing** | [`policy`](#policy), [`policy-discover`](#policy-discover), [`policy-status`](#policy-status), [`policy-diff`](#policy-diff), [`rule-verify`](#rule-verify), [`baseline`](#baseline), [`bundle`](#bundle) |
48
49
 
49
50
  <!-- END FORGELOOP GENERATED: cli-command-index -->
@@ -52,6 +53,163 @@ ForgeLoop uses a definition-driven command-line parser:
52
53
 
53
54
  ## 1. Setup & Maintenance
54
55
 
56
+ ## Durable Actions, Approvals, and Trajectory
57
+
58
+ ForgeLoop is still a protocol/evidence layer, not an agent runtime. Use
59
+ `COMMIT_UNKNOWN` as a hard stop: do not retry until an external observation is
60
+ recorded with `action-reconcile`. `run-action` has no shell mode and executes
61
+ only exact argv. Caller-reported and externally observed provenance are not host authority, and a project capability policy cannot mint host authority.
62
+
63
+ ### `run-action`
64
+
65
+ <!-- BEGIN FORGELOOP GENERATED: cli:run-action:options -->
66
+
67
+ - `--path <directory>`: target project directory (default: current directory)
68
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
69
+ - `--action <id>`: stable durable action ID
70
+ - `--capability <capability>`: canonical action capability
71
+ - `--effect-class <class>`: durable action effect class
72
+ - `--target <target>`: bounded external action target
73
+ - `--idempotency-key <key>`: immutable logical action idempotency key
74
+ - `--requirement <id>`: bound completion requirement
75
+ - `--required-for-completion`: mark the action as required for completion
76
+ - `--approval <id>`: current fingerprint-bound approval
77
+ - `--timeout-ms <number>`: maximum command duration before termination
78
+ - `-- <argv...>`: exact command argv; shell mode is never used
79
+ - `--json`: emit structured output as JSON
80
+
81
+ <!-- END FORGELOOP GENERATED: cli:run-action:options -->
82
+
83
+ ### `action-propose`
84
+
85
+ <!-- BEGIN FORGELOOP GENERATED: cli:action-propose:options -->
86
+
87
+ - `--path <directory>`: target project directory (default: current directory)
88
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
89
+ - `--id <id>`: stable action ID
90
+ - `--capability <capability>`: canonical capability
91
+ - `--effect-class <class>`: effect class
92
+ - `--target <target>`: bounded action target
93
+ - `--operation <text>`: bounded operation description
94
+ - `--idempotency-key <key>`: logical action idempotency key
95
+ - `--requirement <id>`: bound requirement
96
+ - `--required-for-completion`: mark required for completion
97
+ - `--json`: emit structured output as JSON
98
+
99
+ <!-- END FORGELOOP GENERATED: cli:action-propose:options -->
100
+
101
+ ### `action-record`
102
+
103
+ <!-- BEGIN FORGELOOP GENERATED: cli:action-record:options -->
104
+
105
+ - `--path <directory>`: target project directory (default: current directory)
106
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
107
+ - `--action <id>`: durable action ID
108
+ - `--state <state>`: next canonical action state
109
+ - `--provenance <value>`: CALLER_REPORTED or EXTERNAL_OBSERVED
110
+ - `--evidence-ref <ref>`: bounded external evidence reference
111
+ - `--json`: emit structured output as JSON
112
+
113
+ <!-- END FORGELOOP GENERATED: cli:action-record:options -->
114
+
115
+ ### `action-show`
116
+
117
+ <!-- BEGIN FORGELOOP GENERATED: cli:action-show:options -->
118
+
119
+ - `--path <directory>`: target project directory (default: current directory)
120
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
121
+ - `--action <id>`: durable action ID
122
+ - `--json`: emit structured output as JSON
123
+
124
+ <!-- END FORGELOOP GENERATED: cli:action-show:options -->
125
+
126
+ ### `action-verify`
127
+
128
+ <!-- BEGIN FORGELOOP GENERATED: cli:action-verify:options -->
129
+
130
+ - `--path <directory>`: target project directory (default: current directory)
131
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
132
+ - `--action <id>`: durable action ID
133
+ - `--evidence <ref>`: canonical execution or check reference proving the postcondition
134
+ - `--json`: emit structured output as JSON
135
+
136
+ <!-- END FORGELOOP GENERATED: cli:action-verify:options -->
137
+
138
+ ### `action-authorize`
139
+
140
+ <!-- BEGIN FORGELOOP GENERATED: cli:action-authorize:options -->
141
+
142
+ - `--path <directory>`: target project directory (default: current directory)
143
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
144
+ - `--action <id>`: durable action ID
145
+ - `--approval <id>`: current fingerprint-bound approval
146
+ - `--json`: emit structured output as JSON
147
+
148
+ <!-- END FORGELOOP GENERATED: cli:action-authorize:options -->
149
+
150
+ ### `action-reconcile`
151
+
152
+ <!-- BEGIN FORGELOOP GENERATED: cli:action-reconcile:options -->
153
+
154
+ - `--path <directory>`: target project directory (default: current directory)
155
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
156
+ - `--action <id>`: ambiguous durable action ID
157
+ - `--outcome <outcome>`: externally observed reconciliation outcome
158
+ - `--evidence-ref <ref>`: bounded external evidence reference (repeatable)
159
+ - `--observed-at <timestamp>`: external observation timestamp
160
+ - `--json`: emit structured output as JSON
161
+
162
+ <!-- END FORGELOOP GENERATED: cli:action-reconcile:options -->
163
+
164
+ ### `metrics`
165
+
166
+ <!-- BEGIN FORGELOOP GENERATED: cli:metrics:options -->
167
+
168
+ - `--path <directory>`: target project directory (default: current directory)
169
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
170
+ - `--json`: emit trajectory metrics as JSON
171
+
172
+ <!-- END FORGELOOP GENERATED: cli:metrics:options -->
173
+
174
+ ### `eval`
175
+
176
+ <!-- BEGIN FORGELOOP GENERATED: cli:eval:options -->
177
+
178
+ - `--path <directory>`: target project directory (default: current directory)
179
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
180
+ - `--scenario <path>`: project-local trajectory scenario JSON
181
+ - `--json`: emit evaluation as JSON
182
+
183
+ <!-- END FORGELOOP GENERATED: cli:eval:options -->
184
+
185
+ ### `approval-request`
186
+
187
+ <!-- BEGIN FORGELOOP GENERATED: cli:approval-request:options -->
188
+
189
+ - `--path <directory>`: target project directory (default: current directory)
190
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
191
+ - `--approval <id>`: approval artifact ID
192
+ - `--action <id>`: bound action ID
193
+ - `--reason <text>`: bounded approval reason
194
+ - `--json`: emit structured output as JSON
195
+
196
+ <!-- END FORGELOOP GENERATED: cli:approval-request:options -->
197
+
198
+ ### `approval-resolve`
199
+
200
+ <!-- BEGIN FORGELOOP GENERATED: cli:approval-resolve:options -->
201
+
202
+ - `--path <directory>`: target project directory (default: current directory)
203
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
204
+ - `--approval <id>`: approval artifact ID
205
+ - `--decision <decision>`: approval decision
206
+ - `--authority <kind>`: CALLER_ACKNOWLEDGED or HOST_ATTESTED
207
+ - `--host-grant-ref <ref>`: host boundary grant reference
208
+ - `--reason <text>`: bounded resolution reason
209
+ - `--json`: emit structured output as JSON
210
+
211
+ <!-- END FORGELOOP GENERATED: cli:approval-resolve:options -->
212
+
55
213
  ### `protocol-info`
56
214
 
57
215
  Reports the public compatibility handshake required by external ForgeLoop harnesses.
@@ -496,6 +654,7 @@ Records an append-only diagnosis event in the lifecycle event ledger for the act
496
654
 
497
655
  - `--path <directory>`: target project directory (default: current directory)
498
656
  - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
657
+ - `--file <path>`: structured diagnostic case JSON file (mutually exclusive with legacy diagnosis fields)
499
658
  - `--hypothesis <text>`: specific root-cause hypothesis explaining the verification failure
500
659
  - `--failure-class <class>`: canonical failure class taxonomy
501
660
  - `--evidence-ref <check-id>`: reference to failed/blocked check from current cycle (repeatable)
@@ -516,6 +675,63 @@ Records an append-only diagnosis event in the lifecycle event ledger for the act
516
675
  --next-safe-action="Adjust offset +1 in slice.js"
517
676
  ```
518
677
 
678
+ ### `record-intervention`
679
+
680
+ Records an append-only intervention bound to hypotheses; the described change is never executed by ForgeLoop.
681
+
682
+ - **Purpose**: Records corrective or experimental changes (code, config, tests, instrumentation) associated with one or more hypotheses.
683
+ - **When to use**: In `CORRECTING` phase after a structured diagnostic case has been recorded.
684
+ - **Mutation**: Appends `INTERVENTION_RECORDED` to event ledger.
685
+ - **Options**:
686
+
687
+ <!-- BEGIN FORGELOOP GENERATED: cli:record-intervention:options -->
688
+
689
+ - `--path <directory>`: target project directory (default: current directory)
690
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
691
+ - `--file <path>`: intervention JSON file describing the recorded change (never executed)
692
+ - `--json`: emit structured output as JSON
693
+
694
+ <!-- END FORGELOOP GENERATED: cli:record-intervention:options -->
695
+
696
+ - **Example**:
697
+
698
+ ```bash
699
+ forgeloop record-intervention --task checkout --file intervention.json --json
700
+ ```
701
+
702
+ ### `record-hypothesis-disposition`
703
+
704
+ Records an evidence-bound hypothesis disposition update in the lifecycle event ledger.
705
+
706
+ - **Purpose**: Updates hypothesis status (SUPPORTED, WEAKENED, FALSIFIED, SUPERSEDED, UNRESOLVED) based on recorded evidence.
707
+ - **When to use**: After new verification evidence resolves an open hypothesis.
708
+ - **Mutation**: Appends `HYPOTHESIS_DISPOSITION_RECORDED` to event ledger.
709
+ - **Options**:
710
+
711
+ <!-- BEGIN FORGELOOP GENERATED: cli:record-hypothesis-disposition:options -->
712
+
713
+ - `--path <directory>`: target project directory (default: current directory)
714
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
715
+ - `--hypothesis <id>`: existing hypothesis ID to disposition
716
+ - `--status <status>`: SUPPORTED, WEAKENED, FALSIFIED, SUPERSEDED, or UNRESOLVED
717
+ - `--evidence-ref <check-id>`: check ID supporting this disposition (repeatable)
718
+ - `--reason <text>`: evidence-bound reason for the disposition
719
+ - `--json`: emit structured output as JSON
720
+
721
+ <!-- END FORGELOOP GENERATED: cli:record-hypothesis-disposition:options -->
722
+
723
+ - **Example**:
724
+
725
+ ```bash
726
+ forgeloop record-hypothesis-disposition \
727
+ --task checkout \
728
+ --hypothesis h-timeout-latency \
729
+ --status SUPPORTED \
730
+ --evidence-ref checkout-tests \
731
+ --reason "Instrumented dependency time exceeded the timeout." \
732
+ --json
733
+ ```
734
+
519
735
  ### `validate-state`
520
736
 
521
737
  Validates `.forgeloop/task-state/<taskKey>/work-state.json` structure, hash chain, and repository binding.
@@ -821,7 +1037,7 @@ Displays human-readable or structured summary of current task state.
821
1037
 
822
1038
  ### `inspect`
823
1039
 
824
- Inspects checkout changes and compares them against contract deliverables.
1040
+ Inspects checkout changes and compares them against contract deliverables. With `--task <id>`, human output renders a task inspection report (phase, cycle, ledger/snapshot health, progress, verification attempts, diagnostics, failure surface, signals, next command); `--json` keeps the full additive `taskInspection` section.
825
1041
 
826
1042
  - **Purpose**: Shows modified files, untracked files, and deliverable coverage.
827
1043
  - **Mutation**: Read-only.
@@ -842,6 +1058,81 @@ Inspects checkout changes and compares them against contract deliverables.
842
1058
  forgeloop inspect --json
843
1059
  ```
844
1060
 
1061
+ ### `history`
1062
+
1063
+ Shows chronological protocol history reconstructed from canonical ForgeLoop state.
1064
+
1065
+ - **Purpose**: Answers "what happened during this task?" with deterministic, read-only reconstruction from the event ledger.
1066
+ - **Mutation**: Read-only.
1067
+ - **Options**:
1068
+
1069
+ <!-- BEGIN FORGELOOP GENERATED: cli:history:options -->
1070
+
1071
+ - `--path <directory>`: target project directory (default: current directory)
1072
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
1073
+ - `--type <list>`: comma-separated event types or categories to include
1074
+ - `--phase <list>`: comma-separated lifecycle phases to include
1075
+ - `--failures`: show only failed/blocked verification events
1076
+ - `--checks`: show only verification events
1077
+ - `--since <timestamp>`: include events at or after this timestamp
1078
+ - `--until <timestamp>`: include events at or before this timestamp
1079
+ - `--limit <number>`: show only the last N events after filtering
1080
+ - `--compact`: one line per event
1081
+ - `--verbose`: show full event data
1082
+ - `--json`: emit structured history output as JSON
1083
+
1084
+ <!-- END FORGELOOP GENERATED: cli:history:options -->
1085
+
1086
+ - **Example**:
1087
+
1088
+ ```bash
1089
+ forgeloop history --task auth-feature --json
1090
+ ```
1091
+
1092
+ ### `trace`
1093
+
1094
+ Emits detailed structured task trace with provenance and artifact relationships.
1095
+
1096
+ - **Purpose**: Machine-readable protocol reconstruction consumed by history, reflect, task-level inspect, and external integrations.
1097
+ - **Mutation**: Read-only.
1098
+ - **Options**:
1099
+
1100
+ <!-- BEGIN FORGELOOP GENERATED: cli:trace:options -->
1101
+
1102
+ - `--path <directory>`: target project directory (default: current directory)
1103
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
1104
+ - `--json`: emit structured trace output as JSON (default rendering is a summary)
1105
+
1106
+ <!-- END FORGELOOP GENERATED: cli:trace:options -->
1107
+
1108
+ - **Example**:
1109
+
1110
+ ```bash
1111
+ forgeloop trace --task auth-feature --json
1112
+ ```
1113
+
1114
+ ### `reflect`
1115
+
1116
+ Analyzes diagnostic and correction history deterministically for information gain, repeated failures, ineffective interventions, and oscillation.
1117
+
1118
+ - **Purpose**: Whole-task retrospective that reports whether the run actually learned anything, without calling an LLM.
1119
+ - **Mutation**: Read-only.
1120
+ - **Options**:
1121
+
1122
+ <!-- BEGIN FORGELOOP GENERATED: cli:reflect:options -->
1123
+
1124
+ - `--path <directory>`: target project directory (default: current directory)
1125
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
1126
+ - `--json`: emit structured reflection output as JSON
1127
+
1128
+ <!-- END FORGELOOP GENERATED: cli:reflect:options -->
1129
+
1130
+ - **Example**:
1131
+
1132
+ ```bash
1133
+ forgeloop reflect --task auth-feature --json
1134
+ ```
1135
+
845
1136
  ### `policy`
846
1137
 
847
1138
  Evaluates compliance against a named policy pack.