@cassiomc1/forgeloop 1.5.0 → 1.6.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 (126) hide show
  1. package/DOCS_INDEX.md +13 -8
  2. package/EXECUTION_STATE.md +20 -0
  3. package/LOOP_ENGINEERING.md +81 -0
  4. package/LOOP_SYSTEM_DESIGN.md +32 -0
  5. package/PROTOCOL_INTEGRATION.md +46 -0
  6. package/QUALITY_SCORECARD.md +2 -0
  7. package/README.md +31 -9
  8. package/THIRD_PARTY_NOTICES.md +15 -0
  9. package/THREAT_MODEL.md +39 -0
  10. package/docs/ARTIFACT_REFERENCE.md +140 -0
  11. package/docs/CLI_REFERENCE.md +294 -3
  12. package/docs/DIAGNOSTIC_MODEL.md +181 -0
  13. package/docs/DOCUMENTATION_GUIDE.md +22 -13
  14. package/docs/EXECUTION_TRACE.md +76 -0
  15. package/docs/MCP.md +33 -0
  16. package/docs/RECIPES.md +67 -0
  17. package/docs/TROUBLESHOOTING.md +106 -2
  18. package/docs/assets/diagrams/forgeloop-engineering-flow.html +13797 -0
  19. package/docs/assets/diagrams/forgeloop-engineering-flow.receipt.json +37 -0
  20. package/docs/assets/diagrams/forgeloop-engineering-flow.svg +5002 -0
  21. package/docs/diagrams/README.md +55 -0
  22. package/docs/diagrams/forgeloop-engineering-flow.workflow.json +122 -0
  23. package/docs/diagrams/manifest.json +42 -0
  24. package/docs/diagrams/reviews/forgeloop-engineering-flow.review.json +20 -0
  25. package/package.json +8 -6
  26. package/schemas/action.schema.json +100 -0
  27. package/schemas/approval.schema.json +51 -0
  28. package/schemas/capability-policy.schema.json +41 -0
  29. package/schemas/diagnostic-case.schema.json +85 -0
  30. package/schemas/execution-receipt.schema.json +16 -0
  31. package/schemas/hypothesis-disposition.schema.json +16 -0
  32. package/schemas/intervention.schema.json +27 -0
  33. package/schemas/policy-lock.schema.json +1 -0
  34. package/schemas/policy-snapshot.schema.json +2 -0
  35. package/schemas/trajectory-evaluation.schema.json +64 -0
  36. package/schemas/trajectory-scenario.schema.json +42 -0
  37. package/src/cli.js +94 -0
  38. package/src/commands/action-authorize.js +41 -0
  39. package/src/commands/action-propose.js +10 -0
  40. package/src/commands/action-reconcile.js +10 -0
  41. package/src/commands/action-record.js +47 -0
  42. package/src/commands/action-show.js +10 -0
  43. package/src/commands/action-verify.js +10 -0
  44. package/src/commands/advance.js +7 -2
  45. package/src/commands/approval-request.js +64 -0
  46. package/src/commands/approval-resolve.js +10 -0
  47. package/src/commands/baseline.js +3 -3
  48. package/src/commands/eval.js +6 -0
  49. package/src/commands/history.js +18 -0
  50. package/src/commands/init.js +2 -2
  51. package/src/commands/inspect.js +49 -0
  52. package/src/commands/metrics.js +7 -0
  53. package/src/commands/next.js +8 -2
  54. package/src/commands/policy-discover.js +2 -2
  55. package/src/commands/record-diagnosis.js +37 -1
  56. package/src/commands/record-hypothesis-disposition.js +45 -0
  57. package/src/commands/record-intervention.js +35 -0
  58. package/src/commands/reflect.js +38 -0
  59. package/src/commands/report.js +9 -1
  60. package/src/commands/run-action.js +18 -0
  61. package/src/commands/trace.js +34 -0
  62. package/src/commands/validate-protocol.js +21 -13
  63. package/src/core/action-authorization.js +106 -0
  64. package/src/core/action-constants.js +86 -0
  65. package/src/core/action-execution.js +105 -0
  66. package/src/core/action-ledger-projection.js +302 -0
  67. package/src/core/action-model.js +581 -0
  68. package/src/core/action-readiness.js +141 -0
  69. package/src/core/action-reconciliation-policy.js +49 -0
  70. package/src/core/action-reconciliation.js +66 -0
  71. package/src/core/action-verification.js +111 -0
  72. package/src/core/actions.js +462 -0
  73. package/src/core/approvals.js +405 -0
  74. package/src/core/artifact-registry.js +48 -0
  75. package/src/core/audit.js +25 -0
  76. package/src/core/bundles.js +15 -0
  77. package/src/core/capability-policy.js +226 -0
  78. package/src/core/cli-command-definitions.js +210 -1
  79. package/src/core/command-executors.js +171 -15
  80. package/src/core/command-runtime.js +12 -1
  81. package/src/core/completion-artifacts.js +37 -12
  82. package/src/core/completion-recovery-rebind.js +194 -0
  83. package/src/core/completion.js +70 -0
  84. package/src/core/continuity-reconciliation.js +24 -5
  85. package/src/core/diagnostic-model.js +396 -0
  86. package/src/core/diagnostic-projection.js +51 -0
  87. package/src/core/diagnostic-record.js +360 -0
  88. package/src/core/error-codes.js +343 -0
  89. package/src/core/events.js +41 -1
  90. package/src/core/execution-prerequisites.js +4 -1
  91. package/src/core/execution.js +26 -188
  92. package/src/core/failure-signature.js +70 -0
  93. package/src/core/failure-surface.js +57 -0
  94. package/src/core/history.js +110 -0
  95. package/src/core/hypothesis-projection.js +85 -0
  96. package/src/core/information-gain-projection.js +283 -0
  97. package/src/core/information-gain.js +138 -0
  98. package/src/core/inspect.js +105 -7
  99. package/src/core/integration-invocation-policy.js +47 -0
  100. package/src/core/integration-resources.js +51 -0
  101. package/src/core/next-action-model.js +35 -1
  102. package/src/core/next-action.js +459 -3
  103. package/src/core/phase.js +40 -21
  104. package/src/core/policy-engine.js +113 -6
  105. package/src/core/preflight-consistency.js +31 -5
  106. package/src/core/preflight.js +19 -2
  107. package/src/core/prepared-execution.js +227 -0
  108. package/src/core/progress.js +41 -4
  109. package/src/core/protocol-info.js +48 -0
  110. package/src/core/protocol.js +14 -0
  111. package/src/core/receipt.js +1 -0
  112. package/src/core/reconcile-closure.js +15 -12
  113. package/src/core/reflection.js +305 -0
  114. package/src/core/resumability.js +57 -3
  115. package/src/core/schema-validation.js +8 -0
  116. package/src/core/strategy-analysis.js +97 -0
  117. package/src/core/task-paths.js +28 -0
  118. package/src/core/task-snapshot.js +53 -0
  119. package/src/core/templates.js +8 -0
  120. package/src/core/trace.js +548 -0
  121. package/src/core/trajectory-evaluation.js +71 -0
  122. package/src/core/trajectory-metrics.js +80 -0
  123. package/src/core/transaction.js +8 -0
  124. package/src/core/work-state.js +10 -5
  125. package/docs/assets/forgeloop-flow.svg +0 -1
  126. package/docs/forgeloop-flow.mmd +0 -51
package/DOCS_INDEX.md CHANGED
@@ -18,8 +18,11 @@ integration and guide context. Use this map before editing documentation.
18
18
  | Cross-harness continuity | [`docs/CROSS_HARNESS_CONTINUITY.md`](./docs/CROSS_HARNESS_CONTINUITY.md) | Operational handoff and multi-tool resumption |
19
19
  | CLI command reference | [`docs/CLI_REFERENCE.md`](./docs/CLI_REFERENCE.md) | Full syntax, options, and JSON examples for all commands |
20
20
  | Artifact and schema reference | [`docs/ARTIFACT_REFERENCE.md`](./docs/ARTIFACT_REFERENCE.md) | Purpose, mutability, and trust classifications of `.forgeloop/` |
21
+ | Durable actions and trajectory evidence | [`docs/EXECUTION_TRACE.md`](./docs/EXECUTION_TRACE.md) and [`docs/RECIPES.md`](./docs/RECIPES.md) | Action provenance, reconciliation, metrics, and project-local evaluation |
21
22
  | Troubleshooting and recovery | [`docs/TROUBLESHOOTING.md`](./docs/TROUBLESHOOTING.md) | Symptom-first recovery and stable error code reference |
22
23
  | Operational recipes | [`docs/RECIPES.md`](./docs/RECIPES.md) | Short copy-paste recipes for daily workflows |
24
+ | Diagnostic model | [`docs/DIAGNOSTIC_MODEL.md`](./docs/DIAGNOSTIC_MODEL.md) | Structured diagnostic cases, interventions, hypothesis dispositions, information gain |
25
+ | Execution trace and observability | [`docs/EXECUTION_TRACE.md`](./docs/EXECUTION_TRACE.md) | `history`, `trace`, `reflect`, and task-level `inspect` read-only projections |
23
26
  | Universal integration API | [`docs/UNIVERSAL_INTEGRATION.md`](./docs/UNIVERSAL_INTEGRATION.md) | Programmatic integration subpath, envelope semantics, and consumer map |
24
27
  | Local-first MCP adapter | [`docs/MCP.md`](./docs/MCP.md) | stdio default, optional strict loopback HTTP; server modes/capabilities and canonical resources |
25
28
  | Documentation guide | [`docs/DOCUMENTATION_GUIDE.md`](./docs/DOCUMENTATION_GUIDE.md) | Rules and checklist for modifying documentation |
@@ -34,7 +37,8 @@ integration and guide context. Use this map before editing documentation.
34
37
  | Artifact and phase schemas | [`schemas/`](./schemas/) and [`CONTRACT_COVERAGE.md`](./CONTRACT_COVERAGE.md) | Versioned machine-readable contract |
35
38
  | CLI/package behavior | [`src/`](./src/) and [`tests/`](./tests/) | Executable implementation and regression evidence |
36
39
  | Guide content | [`ENG/`](./ENG/) | Context-specific, English-only operational guides |
37
- | Diagram | [`docs/forgeloop-flow.mmd`](./docs/forgeloop-flow.mmd) | Canonical Mermaid source; SVG is generated output |
40
+ | Diagram governance | [`docs/diagrams/manifest.json`](./docs/diagrams/manifest.json) | Authoritative taxonomy, renderer mapping, canonical purposes, artifact ownership, and references |
41
+ | Diagram maintainer entrypoint | [`docs/diagrams/README.md`](./docs/diagrams/README.md) | Typed Archify source, animated HTML explorer, animated SVG fallback, review, and regeneration workflow |
38
42
 
39
43
  ## Audience map
40
44
 
@@ -88,25 +92,26 @@ process into adapters or README sections; link to the canonical source.
88
92
  ## Verification and release
89
93
 
90
94
  The Node regression suite, ESLint, c8, dependency policy, package boundary,
91
- and Mermaid render are the local executable checks. Python validators remain
95
+ and Archify diagram render are the local executable checks. Python validators remain
92
96
  frozen CI-only compatibility tools because they cover historical Markdown,
93
97
  loop, and secret-scanning contracts that have not been migrated to Node. Their
94
98
  scope, exact commands, and migration boundary are recorded in
95
99
  [`scripts/CI_VALIDATORS.md`](./scripts/CI_VALIDATORS.md).
96
100
 
97
101
  The package has no runtime dependencies. Development dependencies are limited
98
- to ESLint, c8, and Mermaid CLI and are checked by
102
+ to ESLint and c8 and are checked by
99
103
  `npm run dependency:policy`. GitHub Actions use `npm ci`, pinned action SHAs,
100
104
  CodeQL, dependency review, and generated-release notes; npm publication still
101
105
  uses trusted OIDC publishing and is not implied by local verification.
102
106
 
103
107
  ## Editing rules
104
108
 
105
- - Keep lifecycle prose, the Mermaid source, and the text-only README fallback
106
- synchronized.
107
- - Keep generated `docs/assets/forgeloop-flow.svg` synchronized with the Mermaid
108
- source by running `npm run docs:flow` and `npm run docs:check`. CI validates
109
- the source fingerprint instead of comparing renderer-specific SVG geometry.
109
+ - Keep lifecycle prose, the typed Archify source, generated outputs, and the
110
+ text-only README fallback synchronized.
111
+ - Keep the generated HTML, SVG, and receipt synchronized with the Archify
112
+ source by running `npm run docs:diagrams` and `npm run docs:check`. CI
113
+ validates the renderer pin, source fingerprint, artifact hashes, and SVG
114
+ safety constraints.
110
115
  - Preserve the distinction between implemented behavior, local evidence, and
111
116
  external publication or production state.
112
117
  - Run `npm run lint`, `npm run coverage`, `npm run pack:check`, and the Python
@@ -179,3 +179,23 @@ repository context and is always operational context rather than evidence.
179
179
  | Stale | Any | Changed | Run `forgeloop route` and `forgeloop preflight` to revalidate |
180
180
  | Invalid / Corrupted | Any | Any | Fail closed; inspect errors via `forgeloop doctor --json` |
181
181
  | Different Task ID | Present | Any | Do not merge contexts; clear or finish previous task first |
182
+
183
+ ## Durable actions are a separate external-state checkpoint
184
+
185
+ Action artifacts under `actions/` describe side-effect intent and its canonical
186
+ state; they do not replace `work-state.json`. Approval artifacts bind a single
187
+ decision to the exact action fingerprint, contract fingerprint, task revision,
188
+ and capability. Capability policy is configuration, not host authority.
189
+
190
+ `FORGELOOP_EXECUTED` means ForgeLoop launched exact argv through `run-action`;
191
+ `HOST_REPORTED` means an external host performed the operation; and
192
+ `EXTERNAL_OBSERVED` means a later observation supplied reconciliation evidence.
193
+ If the external outcome is uncertain, the action is `COMMIT_UNKNOWN`. It must
194
+ not be retried or used to satisfy required completion until
195
+ `forgeloop action-reconcile` records `COMMITTED`, `NOT_COMMITTED`, or
196
+ `UNKNOWN`. ForgeLoop does not claim universal exactly-once execution.
197
+
198
+ `metrics` and `eval` read the canonical trace, reflection, action artifacts, and
199
+ ledger events. They never mutate lifecycle truth, invent usage/cost data, or
200
+ create a second execution history; reference efficiency is emitted only when a
201
+ project-local scenario provides comparable steps.
@@ -27,6 +27,7 @@
27
27
  - [Precedence & Stop Conditions](#precedence)
28
28
  - [Final Delivery](#final-delivery)
29
29
  - [Cross-Harness Continuity](#cross-harness-execution-continuity)
30
+ - [Durable Actions and Trajectory Evidence](#durable-actions-and-trajectory-evidence)
30
31
  - [Multi-Task Concurrent Project State](#multi-task-concurrent-project-state)
31
32
 
32
33
  ## Protocol applicability
@@ -1278,6 +1279,86 @@ completion. `CONTINUITY_CANNOT_GRANT_AUTHORITY`: continuity cannot authorize an
1278
1279
  installation or external action. <a id="FL-CONT-001"></a> **FL-CONT-001 — A receiving harness MUST reconcile**
1279
1280
  continuity against the current work state and checkout before acting on it.
1280
1281
 
1282
+ ## Durable Actions and Trajectory Evidence
1283
+
1284
+ Durable actions extend the existing task protocol; they do not turn ForgeLoop
1285
+ into an agent runtime, scheduler, queue, or workflow engine. Action intent,
1286
+ approval, execution provenance, reconciliation, and evaluation are task-local
1287
+ artifacts whose chronology remains in the same hash-chained `events.ndjson`.
1288
+
1289
+ Every side-effecting action declares an explicit capability, effect class,
1290
+ bounded target, immutable idempotency key, and provenance. Project capability
1291
+ policy is a decision input (`ALLOW`, `DENY`, `REQUIRE_AUTHORITY`, or
1292
+ `REQUIRE_APPROVAL`); it is never host authority. `HOST_ATTESTED` authority can
1293
+ only cross the existing host trust boundary, and `run-action` accepts exact
1294
+ argv with no shell mode.
1295
+
1296
+ ### Durable action trust boundaries (hardened)
1297
+
1298
+ The following invariants are enforced in core code and are regression-tested:
1299
+
1300
+ - **Authorization is canonical.** No caller-controlled surface (`action-record`,
1301
+ CLI flags, MCP tool arguments, project files, environment) can mint
1302
+ `AUTHORIZED`. Only the core authorization service may transition
1303
+ `PROPOSED -> AUTHORIZED` — through `run-action`, or explicitly through
1304
+ `forgeloop action-authorize`, which is a pure adapter over the same service —
1305
+ and only after the current capability policy, the persisted policy lock, and
1306
+ the task policy snapshot agree. Every modern
1307
+ `ACTION_AUTHORIZED` event binds the capability decision, capability-policy
1308
+ fingerprint, policy-lock digest, task-policy digest, and — for
1309
+ `REQUIRE_AUTHORITY`/`REQUIRE_APPROVAL` — the exact host authority or
1310
+ fingerprint-bound approval. Post-authorization mutation of a bound approval
1311
+ artifact is readiness/audit-visible.
1312
+ - **Verification is canonical, independent, and requirement-bound.**
1313
+ `COMMITTED != VERIFIED`. A command exiting 0 proves only local completion.
1314
+ `VERIFIED` is produced exclusively by `forgeloop action-verify` (or the
1315
+ equivalent core service) against a passed ForgeLoop execution artifact that
1316
+ is independent of the action's own commit execution and whose immutable
1317
+ `requirement` exactly equals the action's requirement. New required actions
1318
+ must declare a non-empty requirement at proposal time; historical required
1319
+ artifacts without one remain readable but can never become trusted-satisfied.
1320
+ - **Reconciliation has exactly one replay truth.** A trusted `COMMITTED`
1321
+ settlement emits `ACTION_RECONCILED(outcome=COMMITTED)` (the transition) plus
1322
+ a same-revision informational mirror `ACTION_COMMIT_RECORDED(reconciled=true)`
1323
+ (corroboration only). Ledger replay applies the transition exactly once and
1324
+ validates mirror identity; forged or orphaned mirrors invalidate the ledger.
1325
+ - **Completion consumes readiness.** Required-action completion truth comes
1326
+ from the canonical action-readiness projection, never from raw state labels.
1327
+ A forged or legacy `VERIFIED` label without trusted authorization and
1328
+ canonical verification evidence yields `UNTRUSTED` and blocks completion.
1329
+ - **Settling ambiguity requires trust.** Recording an `UNKNOWN`
1330
+ reconciliation observation is always safe. Settling `COMMIT_UNKNOWN` as
1331
+ `COMMITTED` or `NOT_COMMITTED` requires a trusted out-of-band host authority
1332
+ context plus bounded evidence references bound to the event. Trusted
1333
+ `NOT_COMMITTED` returns the action to `PROPOSED`, so any retry re-evaluates
1334
+ policy, approval, authority, and the task policy snapshot; stale
1335
+ authorization can never be reused.
1336
+ - **STARTED marks the launch boundary.** Deterministic pre-launch checks
1337
+ (argv normalization, command resolution, installation authority, policy
1338
+ identity, approvals) all run before `ACTION_STARTED`; post-start outcomes
1339
+ remain conservative: spawn failure without launch is `FAILED`; anything
1340
+ unproven is `COMMIT_UNKNOWN`.
1341
+ - **Capability policy participates in policy identity.** When
1342
+ `.forgeloop/policy/capabilities.json` exists, its digest participates in the
1343
+ policy lock, the active task policy snapshot, and authorization evidence.
1344
+ Drift blocks before any side effect (`E_ACTION_POLICY_DRIFT`).
1345
+ - **Host context is out-of-band.** Trusted authority travels as an execution
1346
+ context object supplied by an embedding host (`executeForgeLoopCommand` /
1347
+ `createForgeLoopMcpServer({ authorityContextProvider })`). CLI flags such as
1348
+ `--authority HOST_ATTESTED` are requested kinds, never proof. MCP launch
1349
+ flags expose transport surfaces only; tool arguments can never carry
1350
+ `authorityContext`.
1351
+ - **Guidance never lies about authority.** `forgeloop next` returns a
1352
+ structured `authorityRequired` requirement for host-bound approvals instead
1353
+ of recommending a command that cannot satisfy the blocker.
1354
+
1355
+ Trajectory metrics and reference evaluations are read-only projections over the
1356
+ canonical trace, reflection, actions, and events. Missing tokens, costs,
1357
+ provider, model, or optimal-path data remain `null`/`UNKNOWN`; a comparative
1358
+ efficiency ratio exists only when a project-local reference scenario supplies
1359
+ `reference.comparableSteps`. Existing information-gain, intervention, failure
1360
+ signature, and oscillation diagnostics remain canonical.
1361
+
1281
1362
  ## Multi-task concurrent project state
1282
1363
 
1283
1364
  ForgeLoop supports isolated, concurrent tasks within the same repository workspace.
@@ -442,3 +442,35 @@ machine and not a general memory subsystem. Work state owns lifecycle truth;
442
442
  the checkout owns implementation truth; checks/executions own verification
443
443
  truth; completion owns certification. Continuity only narrows what a receiving
444
444
  executor should inspect and continue.
445
+
446
+ ## Durable action and trajectory boundary
447
+
448
+ Durable actions are protocol-owned task artifacts (`actions/`, `approvals/`,
449
+ and `evaluations/`) projected through the existing hash-chained event ledger.
450
+ They record intent, capability policy, approval binding, execution provenance,
451
+ commit uncertainty, reconciliation, and verification without introducing a
452
+ workflow runtime, scheduler, queue, or second ledger.
453
+
454
+ The external side-effect boundary is deliberately conservative: exact argv is
455
+ launched only through `run-action` with no shell mode; project capability
456
+ policy cannot manufacture `HOST_ATTESTED` authority, and trusted host context
457
+ travels out-of-band only (never inside command input, CLI flags, or tool
458
+ arguments). Authorization and verification are canonical core services:
459
+ callers cannot mint `AUTHORIZED` or `VERIFIED`, verification requires an
460
+ independent passed ForgeLoop execution artifact, and required completion
461
+ consumes the canonical action-readiness projection rather than raw state
462
+ labels. Capability policy participates in policy identity: its digest is bound
463
+ into the policy lock, the task policy snapshot, and authorization evidence, so
464
+ drift blocks before any side effect. A started action whose external result is
465
+ uncertain becomes `COMMIT_UNKNOWN`, which forbids retry until explicit
466
+ reconciliation; settling ambiguity as `COMMITTED`/`NOT_COMMITTED` requires
467
+ trusted host attestation plus evidence, and a trusted `NOT_COMMITTED` returns
468
+ the action to `PROPOSED` so stale authorization can never be reused. This
469
+ reduces duplicate-effect risk but cannot provide a universal exactly-once
470
+ guarantee for arbitrary external systems.
471
+
472
+ Metrics and trajectory evaluation are deterministic read-only projections of
473
+ canonical trace/reflection evidence. They preserve unknown usage values and
474
+ only compare efficiency when a project-local reference scenario exists. The
475
+ existing diagnostic and reflection model remains the authority for information
476
+ gain, intervention effectiveness, failure signatures, and oscillation.
@@ -277,6 +277,31 @@ configuration
277
277
  trust
278
278
  ```
279
279
 
280
+ For durable actions, trusted host authority travels **out-of-band** through the
281
+ programmatic integration API:
282
+
283
+ ```js
284
+ await executeForgeLoopCommand({
285
+ command: "approval-resolve",
286
+ projectPath,
287
+ input: { /* actor-controlled command input only */ },
288
+ authorityContext: trustedHostContext, // host-supplied, never from input
289
+ });
290
+ ```
291
+
292
+ `authorityContext` and `runtimeContext` are separate executor parameters; they
293
+ are never merged into `input`, never accepted as tool arguments, and cannot be
294
+ minted by CLI flags, project files, environment variables, or transport
295
+ sessions. MCP embeddings supply an immutable provider instead:
296
+
297
+ ```js
298
+ createForgeLoopMcpServer({
299
+ projectPath,
300
+ allowApprovalResolution: true, // transport surface only
301
+ authorityContextProvider: async ({ command }) => trustedContextOrNull,
302
+ });
303
+ ```
304
+
280
305
  The host-attested source must still resolve outside the actor-writable target. A
281
306
  project-local authority reference may identify a grant, but it does not create
282
307
  the root of trust.
@@ -396,3 +421,24 @@ hosts remain fully supported through the CLI and instruction adapters.
396
421
  requires ForgeLoop 1.4.0 or newer.
397
422
  <a id="FL-CLAIM-003"></a> **FL-CLAIM-003 — A reader without `validatedClaimProjection=true` MUST fail closed**
398
423
  and must not mutate claims.
424
+
425
+ ## Durable actions and authority boundary
426
+
427
+ Durable action support is additive to the integration contract. Read-only
428
+ resources may expose action, approval, metrics, evaluation, and capability
429
+ policy projections, but an integration must not treat transport metadata,
430
+ session IDs, project policy, or actor prose as host authority. `HOST_ATTESTED`
431
+ is accepted only from the existing host trust boundary.
432
+
433
+ `run-action` is an exact-argv surface with no shell mode. Hosts that perform an
434
+ operation themselves must record it as `HOST_REPORTED`; external observations
435
+ used to settle uncertainty are `EXTERNAL_OBSERVED`. A started action whose
436
+ external outcome cannot be proven is `COMMIT_UNKNOWN`: integrations must surface
437
+ `E_ACTION_RECONCILIATION_REQUIRED` and must not retry automatically. The only
438
+ forward path is explicit `action-reconcile` with bounded evidence.
439
+
440
+ Trajectory metrics and evaluations are read-only projections over canonical
441
+ events and trace/reflection data. Missing token/cost/model data remains unknown,
442
+ and efficiency is comparable only when a project-local scenario supplies a
443
+ positive reference step count. ForgeLoop remains an evidence protocol, not an
444
+ agent runtime or workflow engine.
@@ -31,6 +31,8 @@ policy are all present.
31
31
  | Contextual frontend taste | Taste is routed only to applicable premium frontend work, remains advisory, respects accessibility/performance/evidence, and has attribution without runtime dependency. |
32
32
  | Multi-agent coordination | Self-contained briefs, write/write and write/read ownership checks, dependency-set validation, reviewer independence, normalized results, and inline fallback. |
33
33
  | Security boundaries | Realpath containment, bounded untrusted JSON, threat model, nested secret scanning, publication evidence, and explicit authority rules. |
34
+ | Durable external actions | Immutable action identity, idempotency conflict rejection, capability policy, fingerprint-bound approvals, exact-argv provenance, `COMMIT_UNKNOWN` reconciliation, completion blocking, and audit evidence. |
35
+ | Trajectory evaluation | Read-only trace/reflection metrics, unknown usage preservation, canonical comparable-step definition, and scenario-bound efficiency without an arbitrary overall score. |
34
36
  | Maintenance quality | Small modules, built-in runtime, deterministic JSON contracts, malformed/version fixtures, package gates, and backward-compatible protocol versions. |
35
37
 
36
38
  ## Score rules
package/README.md CHANGED
@@ -75,6 +75,15 @@ forgeloop next --task demo --json
75
75
  O último comando informa a ação segura seguinte; ele não executa código nem
76
76
  agenda agentes.
77
77
 
78
+ ### Ações externas duráveis
79
+
80
+ Para efeitos externos, registre a intenção com `action-propose`, aplique a
81
+ política de capacidade e a aprovação vinculada ao fingerprint, e execute apenas
82
+ com `run-action` usando argv exato. Um resultado `COMMIT_UNKNOWN` nunca é
83
+ repetido automaticamente: observe o sistema externo e use `action-reconcile`.
84
+ As métricas mantêm tokens/custos como desconhecidos quando o host não os
85
+ fornece, e eficiência só existe quando um cenário de referência foi declarado.
86
+
78
87
  Antes de um harness criar ou retomar uma tarefa, ele pode confirmar a
79
88
  compatibilidade pública sem depender de detalhes internos:
80
89
 
@@ -260,12 +269,24 @@ See [`docs/CLI_REFERENCE.md`](./docs/CLI_REFERENCE.md) and [`LOOP_SYSTEM_DESIGN.
260
269
 
261
270
  ## Architecture flow
262
271
 
263
- The canonical source is [`docs/forgeloop-flow.mmd`](./docs/forgeloop-flow.mmd),
264
- and the committed render is [`docs/assets/forgeloop-flow.svg`](./docs/assets/forgeloop-flow.svg).
272
+ The canonical source is the typed Archify workflow
273
+ [`docs/diagrams/forgeloop-engineering-flow.workflow.json`](./docs/diagrams/forgeloop-engineering-flow.workflow.json).
274
+ The committed animated interactive explorer is
275
+ [`docs/assets/diagrams/forgeloop-engineering-flow.html`](./docs/assets/diagrams/forgeloop-engineering-flow.html),
276
+ which opens in the dark presentation stage and traces the workflow. The
277
+ animated, self-contained SVG fallback is
278
+ [`docs/assets/diagrams/forgeloop-engineering-flow.svg`](./docs/assets/diagrams/forgeloop-engineering-flow.svg),
279
+ and the deterministic hash receipt is
280
+ [`docs/assets/diagrams/forgeloop-engineering-flow.receipt.json`](./docs/assets/diagrams/forgeloop-engineering-flow.receipt.json).
281
+ The governance source is [`docs/diagrams/manifest.json`](./docs/diagrams/manifest.json),
282
+ and the source-bound visual approval is kept in
283
+ [`docs/diagrams/reviews/forgeloop-engineering-flow.review.json`](./docs/diagrams/reviews/forgeloop-engineering-flow.review.json).
265
284
  The broader architecture and boundaries are in
266
285
  [`LOOP_SYSTEM_DESIGN.md`](./LOOP_SYSTEM_DESIGN.md).
267
286
 
268
- ![ForgeLoop evidence-first engineering flow](./docs/assets/forgeloop-flow.svg)
287
+ [Open the animated ForgeLoop evidence-first engineering flow](./docs/assets/diagrams/forgeloop-engineering-flow.html)
288
+
289
+ ![ForgeLoop evidence-first engineering flow (animated SVG fallback)](./docs/assets/diagrams/forgeloop-engineering-flow.svg)
269
290
 
270
291
  Text-only fallback: discovery creates the contract and route; required gates
271
292
  and `PREFLIGHT_READY` authorize execution; verification creates structured
@@ -305,9 +326,10 @@ values are checked; and install-capable verification requires trusted host
305
326
  authority. See [`THREAT_MODEL.md`](./THREAT_MODEL.md) for the full inventory.
306
327
 
307
328
  Development tooling is intentionally separate from runtime dependencies. The
308
- repository policy allows only ESLint, c8, and Mermaid CLI as development
309
- dependencies; `npm run dependency:policy` fails if runtime or unapproved
310
- dependencies appear.
329
+ repository policy allows only ESLint and c8 as development dependencies;
330
+ `npm run dependency:policy` fails if runtime or unapproved dependencies
331
+ appear. The documentation renderer is vendored and pinned under
332
+ `vendor/archify/v2.15.0/` rather than installed as a package dependency.
311
333
 
312
334
  Para reportar vulnerabilidades ou contribuir com alterações, consulte
313
335
  [`SECURITY.md`](./SECURITY.md) e [`CONTRIBUTING.md`](./CONTRIBUTING.md).
@@ -377,7 +399,7 @@ npm run lint
377
399
  npm run coverage
378
400
  npm run pack:check
379
401
  npm run dependency:policy
380
- npm run docs:flow
402
+ npm run docs:diagrams
381
403
  npm run docs:check
382
404
  ```
383
405
 
@@ -387,8 +409,8 @@ npm run docs:check
387
409
  src/ npm CLI and protocol implementation
388
410
  schemas/ versioned artifact schemas
389
411
  ENG/ package-source engineering guides
390
- docs/forgeloop-flow.mmd canonical Mermaid source
391
- docs/assets/ committed diagram render
412
+ docs/diagrams/ typed Archify diagram source and inventory
413
+ docs/assets/diagrams/ committed HTML, SVG, and generation receipt
392
414
  scripts/ checks, renderer, release identity, CI notes
393
415
  tests/ Node and Python regression coverage
394
416
  .forgeloop/ project-scoped ForgeLoop configuration
@@ -64,6 +64,21 @@ inclusion does not install, bundle, or declare any project as a dependency of
64
64
  this collection. Check the specific project's current license, terms,
65
65
  dependencies, version, and distribution conditions before adoption.
66
66
 
67
+ ### Archify v2.15.0 — vendored documentation renderer
68
+
69
+ - Project/source: [tt-a1i/archify](https://github.com/tt-a1i/archify/tree/v2.15.0).
70
+ - Pinned source commit: `e1ac748f19cf805e44bf74fb93c796662152e273`.
71
+ - License declared by the upstream project: MIT; the vendored license is at
72
+ `vendor/archify/v2.15.0/archify/LICENSE`.
73
+ - Use in this collection: deterministic generation and validation of the
74
+ typed workflow diagram under `docs/diagrams/`.
75
+ - Boundary: this is a documentation-only vendored toolchain, not a ForgeLoop
76
+ runtime dependency. It is not installed from a registry, and its exact pin,
77
+ source, license, and raw-byte tree hashes are recorded in
78
+ `vendor/archify/v2.15.0/PIN.json`; output hashes are recorded in the receipt.
79
+ The vendor integrity check rejects modified, missing, extra, renamed, or
80
+ symlinked files before the renderer is trusted.
81
+
67
82
  ### Superpowers
68
83
 
69
84
  - Project: [Superpowers](https://github.com/obra/superpowers).
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` |
@@ -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`)*
@@ -571,6 +585,7 @@ silently ignored.
571
585
  - `digest` *(string, required, minLength: 1)*
572
586
  - `rulesDigest` *(string, required)*
573
587
  - `baselineDigest` *(string, required)*
588
+ - `capabilityPolicyDigest` *(string, optional, pattern: `^sha256:[a-f0-9]{64}$`)*
574
589
  - `capturedAt` *(string, optional)*
575
590
 
576
591
  <!-- END FORGELOOP GENERATED: schema:policy-lock -->
@@ -599,6 +614,8 @@ comparison explicitly `UNKNOWN` rather than assuming an empty baseline.
599
614
  - `rules` *(array<string,object>, required)*
600
615
  - `baseline` *(object, optional)*
601
616
  - `baselineDigest` *(string, optional)*
617
+ - `capabilityPolicyDigest` *(string, optional, pattern: `^sha256:[a-f0-9]{64}$`)*
618
+ - `capabilityPolicyFingerprint` *(string, optional, pattern: `^[a-f0-9]{64}$`)*
602
619
  - `capturedAt` *(string, optional)*
603
620
 
604
621
  <!-- END FORGELOOP GENERATED: schema:policy-snapshot -->
@@ -644,3 +661,126 @@ host-owned `grantRef`; the standalone CLI does not self-issue that authority.
644
661
  - `grantRef` *(string, optional, minLength: 1)*
645
662
 
646
663
  <!-- END FORGELOOP GENERATED: schema:task-recovery -->
664
+
665
+ ---
666
+
667
+ ### 2.20 `task-state/<taskKey>/actions/action-<id>.json`
668
+
669
+ <!-- forgeloop-doc: schema=action artifact=.forgeloop/task-state/<task-key>/actions/action-<id>.json -->
670
+
671
+ Durable external action artifact recording intent, capability policy binding,
672
+ authority, execution provenance, ambiguity, and reconciliation state for a
673
+ side-effecting operation. The `actionFingerprint` covers immutable identity
674
+ fields only; mutable state lives in `state` and `revision`.
675
+
676
+ #### Canonical Fields
677
+
678
+ <!-- BEGIN FORGELOOP GENERATED: schema:action -->
679
+
680
+ - `schemaVersion` *(number, required, const: 1)*
681
+ - `taskId` *(string, required, minLength: 1, maxLength: 256)*
682
+ - `actionId` *(string, required, pattern: `^action-[A-Za-z0-9_-]+$`)*
683
+ - `actionFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
684
+ - `effectClass` *(string, required, enum: `READ_ONLY`, `REVERSIBLE_WRITE`, `IRREVERSIBLE_WRITE`, `EXTERNAL_PUBLICATION`, `DESTRUCTIVE`)*
685
+ - `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`)*
686
+ - `operation` *(string, required, minLength: 1, maxLength: 512)*
687
+ - `target` *(string, required, minLength: 1, maxLength: 512)*
688
+ - `idempotencyKey` *(string or null, required)*
689
+ - `requiredForCompletion` *(boolean, required)*
690
+ - `requirement` *(string or null, required)*
691
+ - `provenance` *(string, required, enum: `FORGELOOP_EXECUTED`, `HOST_ATTESTED`, `CALLER_REPORTED`, `HOST_REPORTED`, `EXTERNAL_OBSERVED`)*
692
+ - `state` *(string, required, enum: `PROPOSED`, `AUTHORIZED`, `STARTED`, `COMMITTED`, `VERIFIED`, `FAILED`, `COMMIT_UNKNOWN`, `CANCELLED`)*
693
+ - `revision` *(integer, required, minimum: 0)*
694
+ - `createdAt` *(string, required, minLength: 1)*
695
+ - `updatedAt` *(string, required, minLength: 1)*
696
+ - `lastEvidenceRef` *(string or null, optional)*
697
+ - `lastReconciliationAt` *(string or null, optional)*
698
+ - `commitResultCode` *(object or null, optional)*
699
+
700
+ <!-- END FORGELOOP GENERATED: schema:action -->
701
+
702
+ ---
703
+
704
+ ### 2.21 `task-state/<taskKey>/approvals/approval-<id>.json`
705
+
706
+ <!-- forgeloop-doc: schema=approval artifact=.forgeloop/task-state/<task-key>/approvals/approval-<id>.json -->
707
+
708
+ Crash-safe durable approval request cryptographically bound to the exact action
709
+ fingerprint, contract fingerprint, task revision, and capability. Any drift
710
+ makes the approval stale. Resolution is one-time; approvals persist across
711
+ process and harness boundaries.
712
+
713
+ #### Canonical Fields
714
+
715
+ <!-- BEGIN FORGELOOP GENERATED: schema:approval -->
716
+
717
+ - `schemaVersion` *(number, required, const: 1)*
718
+ - `taskId` *(string, required, minLength: 1, maxLength: 256)*
719
+ - `approvalId` *(string, required, pattern: `^approval-[A-Za-z0-9_-]+$`)*
720
+ - `actionId` *(string, required, pattern: `^action-[A-Za-z0-9_-]+$`)*
721
+ - `actionFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
722
+ - `contractFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
723
+ - `taskRevision` *(integer, required, minimum: 0)*
724
+ - `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`)*
725
+ - `status` *(string, required, enum: `PENDING`, `APPROVED`, `REJECTED`)*
726
+ - `requestedAt` *(string, required, minLength: 1)*
727
+ - `reason` *(string or null, optional)*
728
+ - `decision` *(string, optional, enum: `APPROVED`, `REJECTED`)*
729
+ - `resolvedAt` *(string or null, optional)*
730
+ - `authorityKind` *(string, optional, enum: `CALLER_ACKNOWLEDGED`, `HOST_ATTESTED`)*
731
+ - `hostGrantRef` *(string or null, optional)*
732
+
733
+ <!-- END FORGELOOP GENERATED: schema:approval -->
734
+
735
+ ---
736
+
737
+ ### 2.22 `policy/capabilities.json`
738
+
739
+ <!-- forgeloop-doc: schema=capability-policy artifact=.forgeloop/policy/capabilities.json -->
740
+
741
+ Project-local machine-readable capability policy mapping canonical capability
742
+ values to ALLOW, DENY, REQUIRE_AUTHORITY, or REQUIRE_APPROVAL decisions. This
743
+ artifact is policy specification only; it can never mint host authority.
744
+
745
+ #### Canonical Fields
746
+
747
+ <!-- BEGIN FORGELOOP GENERATED: schema:capability-policy -->
748
+
749
+ - `schemaVersion` *(number, required, const: 1)*
750
+ - `defaultDecision` *(string, required, enum: `ALLOW`, `DENY`)*
751
+ - `rules` *(array<object>, required)*
752
+ - `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`)*
753
+ - `decision` *(string, required, enum: `ALLOW`, `DENY`, `REQUIRE_AUTHORITY`, `REQUIRE_APPROVAL`)*
754
+
755
+ <!-- END FORGELOOP GENERATED: schema:capability-policy -->
756
+
757
+ ---
758
+
759
+ ### 2.23 `task-state/<taskKey>/evaluations/eval-<id>.json`
760
+
761
+ <!-- forgeloop-doc: schema=trajectory-evaluation artifact=.forgeloop/task-state/<task-key>/evaluations/eval-<id>.json -->
762
+
763
+ Immutable trajectory evaluation result compiled from the canonical trace against
764
+ a project-local reference scenario. Evaluations are projections over canonical
765
+ evidence and never override lifecycle validation.
766
+
767
+ #### Canonical Fields
768
+
769
+ <!-- BEGIN FORGELOOP GENERATED: schema:trajectory-evaluation -->
770
+
771
+ - `schemaVersion` *(number, required, const: 1)*
772
+ - `evaluationId` *(string, required, pattern: `^eval-[A-Za-z0-9_-]+$`)*
773
+ - `scenarioId` *(string, required, minLength: 1, maxLength: 128)*
774
+ - `scenarioFingerprint` *(string, optional, pattern: `^[a-f0-9]{64}$`)*
775
+ - `taskId` *(string, required, minLength: 1, maxLength: 256)*
776
+ - `result` *(string, required, enum: `PASS`, `FAIL`)*
777
+ - `completionValid` *(boolean, required)*
778
+ - `safetyValid` *(boolean, required)*
779
+ - `missingMilestones` *(array<string>, optional)*
780
+ - `limits` *(object, optional)*
781
+ - `efficiency` *(object or null, optional)*
782
+ - `computedAt` *(string, optional, minLength: 1)*
783
+ - `source` *(string, optional, enum: `PROJECT_LOCAL_REFERENCE`)*
784
+ - `evaluationFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
785
+
786
+ <!-- END FORGELOOP GENERATED: schema:trajectory-evaluation -->