@cassiomc1/forgeloop 1.9.0 → 1.10.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 (103) hide show
  1. package/AGENT_COMPATIBILITY.md +15 -0
  2. package/DELEGATION_PROTOCOL.md +6 -0
  3. package/DOCS_INDEX.md +13 -2
  4. package/LOOP_ENGINEERING.md +17 -4
  5. package/LOOP_SYSTEM_DESIGN.md +56 -0
  6. package/ORCHESTRATOR_INTEGRATION.md +9 -0
  7. package/PROTOCOL_INTEGRATION.md +31 -0
  8. package/QUALITY_SCORECARD.md +2 -2
  9. package/README.md +53 -0
  10. package/TERMINOLOGY.md +12 -0
  11. package/THREAT_MODEL.md +24 -0
  12. package/completions/_forgeloop +2 -1
  13. package/completions/forgeloop.bash +3 -1
  14. package/completions/forgeloop.fish +9 -1
  15. package/docs/ADVISORY_CONTEXT.md +174 -0
  16. package/docs/AGENT_PROTOCOL_SUMMARY.md +28 -2
  17. package/docs/ARTIFACT_REFERENCE.md +29 -0
  18. package/docs/CLI_REFERENCE.md +40 -0
  19. package/docs/CODE_ATTESTATION.md +9 -0
  20. package/docs/CROSS_HARNESS_CONTINUITY.md +85 -0
  21. package/docs/DOCUMENTATION_GUIDE.md +11 -4
  22. package/docs/EXECUTION_PROFILE_BENCHMARKS.md +10 -0
  23. package/docs/GETTING_STARTED.md +22 -0
  24. package/docs/KNOWLEDGE_SOURCES.md +10 -0
  25. package/docs/MCP.md +29 -1
  26. package/docs/PACKAGE_CONTENTS.md +83 -0
  27. package/docs/RECIPES.md +80 -0
  28. package/docs/RELEASE_CHECKLIST.md +22 -0
  29. package/docs/REVISION_PROVIDERS.md +9 -0
  30. package/docs/TROUBLESHOOTING.md +66 -2
  31. package/docs/UNIVERSAL_INTEGRATION.md +60 -0
  32. package/docs/assets/diagrams/forgeloop-code-attestation-flow.html +13 -2
  33. package/docs/assets/diagrams/forgeloop-code-attestation-flow.receipt.json +6 -6
  34. package/docs/assets/diagrams/forgeloop-code-attestation-flow.svg +10 -1
  35. package/docs/assets/diagrams/forgeloop-engineering-flow.html +22 -11
  36. package/docs/assets/diagrams/forgeloop-engineering-flow.receipt.json +6 -6
  37. package/docs/assets/diagrams/forgeloop-engineering-flow.svg +17 -8
  38. package/docs/assets/diagrams/forgeloop-verification-trust-flow.html +14 -3
  39. package/docs/assets/diagrams/forgeloop-verification-trust-flow.receipt.json +6 -6
  40. package/docs/assets/diagrams/forgeloop-verification-trust-flow.svg +10 -1
  41. package/docs/diagrams/README.md +17 -0
  42. package/docs/diagrams/forgeloop-code-attestation-flow.workflow.json +383 -57
  43. package/docs/diagrams/forgeloop-engineering-flow.workflow.json +374 -55
  44. package/docs/diagrams/forgeloop-verification-trust-flow.workflow.json +328 -47
  45. package/docs/diagrams/reviews/forgeloop-code-attestation-flow.review.json +4 -4
  46. package/docs/diagrams/reviews/forgeloop-engineering-flow.review.json +4 -4
  47. package/docs/diagrams/reviews/forgeloop-verification-trust-flow.review.json +4 -4
  48. package/package.json +14 -4
  49. package/schemas/handoff-envelope.schema.json +1 -0
  50. package/scripts/CI_VALIDATORS.md +24 -0
  51. package/scripts/check-changelog-freshness.mjs +27 -3
  52. package/scripts/check-critical-coverage.mjs +9 -0
  53. package/scripts/generate-agent-protocol-summary.mjs +18 -0
  54. package/src/cli.js +6 -0
  55. package/src/commands/doctor.js +11 -10
  56. package/src/commands/handoff-accept.js +36 -0
  57. package/src/commands/handoff-list.js +28 -2
  58. package/src/commands/handoff-show.js +27 -2
  59. package/src/commands/reconcile-continuity.js +4 -0
  60. package/src/core/actions.js +2 -2
  61. package/src/core/advisory-context/constants.js +74 -0
  62. package/src/core/advisory-context/provider.js +287 -0
  63. package/src/core/advisory-context/service.js +140 -0
  64. package/src/core/approvals.js +2 -2
  65. package/src/core/artifacts.js +3 -3
  66. package/src/core/checks.js +0 -33
  67. package/src/core/cli-command-definitions.js +17 -0
  68. package/src/core/command-executors.js +12 -0
  69. package/src/core/command-input.js +11 -1
  70. package/src/core/completion.js +2 -2
  71. package/src/core/continuity-lint.js +89 -0
  72. package/src/core/continuity-reconciliation.js +16 -0
  73. package/src/core/continuity.js +10 -11
  74. package/src/core/error-codes.js +113 -0
  75. package/src/core/events.js +37 -5
  76. package/src/core/execution-profile-context.js +15 -1
  77. package/src/core/execution-profile.js +18 -5
  78. package/src/core/filesystem.js +18 -2
  79. package/src/core/handoff-acceptance.js +277 -0
  80. package/src/core/handoff.js +41 -8
  81. package/src/core/integration-invocation-policy.js +19 -2
  82. package/src/core/integration-resources.js +21 -1
  83. package/src/core/next-action-pending-actions.js +255 -0
  84. package/src/core/next-action-phases.js +26 -764
  85. package/src/core/next-action-planned-phase.js +51 -0
  86. package/src/core/next-action-quality-guidance.js +19 -0
  87. package/src/core/next-action-recovery-phases.js +97 -0
  88. package/src/core/next-action-refresh.js +20 -0
  89. package/src/core/next-action-review-phase.js +189 -0
  90. package/src/core/next-action-verification-phase.js +192 -0
  91. package/src/core/portable-context.js +103 -0
  92. package/src/core/protocol-info.js +18 -2
  93. package/src/core/runtime-context.js +31 -0
  94. package/src/core/task-recovery.js +2 -2
  95. package/src/core/transaction-maintenance.js +70 -0
  96. package/src/core/transaction.js +31 -10
  97. package/src/core/work-state.js +5 -5
  98. package/src/integration.d.ts +135 -3
  99. package/src/integration.js +23 -0
  100. package/src/core/cli-metadata.js +0 -23
  101. package/src/core/decision-classification.js +0 -55
  102. package/src/core/gates.js +0 -57
  103. package/src/core/workflow-compatibility.js +0 -151
@@ -0,0 +1,174 @@
1
+ # Advisory Context & External Provider Boundary
2
+
3
+ ## Overview
4
+
5
+ ForgeLoop treats external advisory context as **optional, host-injected, lazy,
6
+ and strictly advisory**.
7
+
8
+ The core invariant of the protocol is:
9
+
10
+ ```
11
+ MEMORY != STATE
12
+ MEMORY != EVIDENCE
13
+ MEMORY != AUTHORITY
14
+ MEMORY != COMPLETION
15
+ MEMORY != NEXT ACTION
16
+ ```
17
+
18
+ ForgeLoop contains **no built-in vector database, SQLite engine, or full-text search (FTS)** dependencies. Memory systems belong to hosts, IDEs, orchestrators, and harnesses. ForgeLoop provides the hardened runtime contract, trust boundary, portable text sanitization, and allowlist normalization.
19
+
20
+ ## Architectural Boundaries
21
+
22
+ 1. **Non-Authoritative (`ADVISORY`)**: Advisory memory can provide context or suggestions to an agent, but cannot dictate lifecycle state, phase transitions, or next actions.
23
+ 2. **Non-Evidence (`evidenceAuthority: "NONE"`)**: Stored memories or suggestions cannot satisfy verification requirements, pass gates, or serve as execution receipts.
24
+ 3. **Non-Executable (`actionability: "NON_EXECUTABLE"`)**: Output items cannot be executed directly as protocol commands.
25
+ 4. **Ephemeral & Unpersisted (`persisted: false`)**: ForgeLoop never persists external recall results to `.forgeloop/` state or the event ledger.
26
+ 5. **Lazy Provider Evaluation**: ForgeLoop runtime commands (`next`, `status`, `preflight`, `complete`, `task-show`, etc.) never invoke advisory memory providers. Recall occurs only when a host explicitly invokes the integration recall service.
27
+
28
+ ## Registering Providers
29
+
30
+ Hosts configure providers through the runtime context:
31
+
32
+ ```javascript
33
+ import { createForgeLoopContext } from "@cassiomc1/forgeloop/integration";
34
+
35
+ const runtimeContext = createForgeLoopContext({
36
+ advisoryContextProviders: {
37
+ "my-memory": {
38
+ id: "my-memory",
39
+ version: "1.0.0",
40
+ async recall({ projectPath, taskId, query, limit, maxItemChars, maxTotalChars, timeoutMs }) {
41
+ // Query host vector database, knowledge base, or memory cache
42
+ return {
43
+ items: [
44
+ {
45
+ title: "Previous Architecture Decision",
46
+ summary: "Decided to use rotating refresh tokens with 15-minute expiry.",
47
+ sourceRef: "docs/decisions/auth-tokens.md",
48
+ confidence: 0.95,
49
+ },
50
+ ],
51
+ };
52
+ },
53
+ },
54
+ },
55
+ });
56
+ ```
57
+
58
+ Provider IDs must match `^[a-z0-9][a-z0-9_-]*$`. Providers may be plain objects or async factory functions. The registry key and the resolved provider `id` must match exactly; a factory that resolves to another identity fails with `E_ADVISORY_CONTEXT_PROVIDER_INVALID` before `recall` is called.
59
+
60
+ ## Querying Advisory Context
61
+
62
+ Hosts explicitly invoke `recallAdvisoryContext`:
63
+
64
+ ```javascript
65
+ import { recallAdvisoryContext } from "@cassiomc1/forgeloop/integration";
66
+
67
+ const result = await recallAdvisoryContext({
68
+ target: "/path/to/project",
69
+ taskId: "auth-impl-42",
70
+ providerName: "my-memory",
71
+ query: "token refresh strategy",
72
+ limit: 5,
73
+ runtimeContext,
74
+ });
75
+ ```
76
+
77
+ ### Result Schema
78
+
79
+ Every returned result is normalized, frozen, and stamped with immutable trust metadata:
80
+
81
+ ```json
82
+ {
83
+ "provider": {
84
+ "id": "my-memory",
85
+ "version": "1.0.0"
86
+ },
87
+ "taskId": "auth-impl-42",
88
+ "authority": "ADVISORY",
89
+ "evidenceAuthority": "NONE",
90
+ "actionability": "NON_EXECUTABLE",
91
+ "trustRole": "NON_EVIDENCE_ADVISORY_CONTEXT",
92
+ "persisted": false,
93
+ "items": [
94
+ {
95
+ "title": "Previous Architecture Decision",
96
+ "summary": "Decided to use rotating refresh tokens with 15-minute expiry.",
97
+ "sourceRef": "docs/decisions/auth-tokens.md",
98
+ "confidence": 0.95,
99
+ "itemFingerprint": "4a7d...3b1f"
100
+ }
101
+ ]
102
+ }
103
+ ```
104
+
105
+ ## Normalization & Authority Stripping
106
+
107
+ ForgeLoop checks the raw result shape and item count, then selects bounded items and projects only allowlisted fields before portable safety inspection. Unknown raw fields—including secret-like or cyclic metadata—are discarded and are never copied or logged. A secret in a selected field still fails closed.
108
+
109
+ Any raw fields returned by a provider that attempt to assert protocol authority are completely stripped during normalization:
110
+
111
+ - `nextAction`, `command`, `phase`
112
+ - `evidence`, `approval`, `authority`
113
+ - `writeClaims`, `changedPaths`, `checkIds`
114
+
115
+ Only allowlisted fields (`title`, `summary`, `sourceRef`, `observedAt`, `confidence`) survive. Each item receives a deterministic SHA-256 `itemFingerprint`.
116
+
117
+ ## Portable Safety Boundary
118
+
119
+ All text flowing into or out of advisory recall is verified:
120
+
121
+ - **Control Character Rejection**: ASCII control characters (`\x00-\x08`, `\x0B-\x0C`, `\x0E-\x1F`, `\x7F`) throw `E_PORTABLE_CONTEXT_INVALID`.
122
+ - **Secret Scanning**: Inputs and outputs containing secret tokens (e.g., `Bearer <token>`, `ghp_`, AWS keys, private keys) throw `E_PORTABLE_CONTEXT_INVALID`.
123
+ - **Budget Enforcements**:
124
+
125
+ - Max query characters: 1,000 chars (`E_ADVISORY_CONTEXT_QUERY_INVALID`)
126
+ - Max item summary: 4,000 chars (`E_ADVISORY_CONTEXT_OUTPUT_LIMIT`)
127
+ - Default item limit: 6 items (max 20)
128
+ - Default total characters: 6,000 chars (max 16,000) (`E_ADVISORY_CONTEXT_OUTPUT_LIMIT`)
129
+ - Raw provider result ceiling: 100 items (`E_ADVISORY_CONTEXT_OUTPUT_LIMIT`)
130
+ - Default timeout: 5,000 ms, max 30,000 ms (`E_ADVISORY_CONTEXT_TIMEOUT`)
131
+
132
+ ForgeLoop normalizes recall limits before provider dispatch. Valid oversized
133
+ integer requests are clamped to the canonical maxima, and non-finite,
134
+ non-integer, below-minimum, string, boolean, object, or null values fail before
135
+ provider lookup with `E_ADVISORY_CONTEXT_REQUEST_INVALID`. Providers therefore
136
+ never receive caller-requested budgets above ForgeLoop's supported maxima.
137
+
138
+ ## Replay safety and failure handling
139
+
140
+ Advisory recall is an explicit host operation. ForgeLoop does not record a
141
+ provider query, provider response, or item fingerprint in the task event ledger,
142
+ and a later recall is never treated as proof that an earlier response was
143
+ current. Hosts should re-query when context is needed and must independently
144
+ validate any proposed action or lifecycle step against canonical state.
145
+
146
+ Provider failures remain advisory failures and do not block the canonical loop.
147
+ The public boundary reports these stable codes:
148
+
149
+ | Code | Meaning |
150
+ | --- | --- |
151
+ | `E_ADVISORY_CONTEXT_PROVIDER_INVALID` | Provider identity or recall contract is invalid. |
152
+ | `E_ADVISORY_CONTEXT_PROVIDER_UNAVAILABLE` | The requested provider is not registered in the runtime context. |
153
+ | `E_ADVISORY_CONTEXT_QUERY_INVALID` | The query is empty, unsafe, or exceeds the query budget. |
154
+ | `E_ADVISORY_CONTEXT_REQUEST_INVALID` | A recall budget has an invalid type, range, or numeric value. |
155
+ | `E_ADVISORY_CONTEXT_RESULT_INVALID` | The provider returned an invalid result shape. |
156
+ | `E_ADVISORY_CONTEXT_TIMEOUT` | Provider recall exceeded the bounded timeout. |
157
+ | `E_ADVISORY_CONTEXT_OUTPUT_LIMIT` | The raw or normalized provider output exceeded a bounded limit. |
158
+ | `E_PORTABLE_CONTEXT_INVALID` | Portable text contains unsafe controls, secrets, or unsupported content. |
159
+
160
+ ## What ForgeLoop Never Does Automatically
161
+
162
+ - It does not look up a provider on startup.
163
+ - It does not look up a provider for `status`, `next`, `preflight`, `complete`,
164
+ `task-show`, or the read-only `task/context` resource.
165
+ - It does not persist provider results, queries, or provider metadata in
166
+ `.forgeloop/` or the event ledger.
167
+ - It does not turn provider text into a command, lifecycle transition, check,
168
+ evidence record, approval, claim, or next action.
169
+ - It does not infer provider trust from a package version, a source path, or a
170
+ host label. The provider identity contract is resolved at the Integration
171
+ API boundary and remains descriptive rather than authenticated authority.
172
+
173
+ The host owns whether and when to display or use advisory context. ForgeLoop
174
+ owns only the bounded normalization and trust-role projection.
@@ -7,7 +7,7 @@
7
7
  ForgeLoop is a portable protocol and support CLI for verifiable engineering workflows. It records and validates task state, contracts, routing, checks, evidence, continuity, and optional code attestations. It does not become an agent scheduler, delegation service, source-control authority, or secret manager.
8
8
 
9
9
  Protocol version: 1
10
- Package version: 1.9.0
10
+ Package version: 1.10.1
11
11
 
12
12
  ## Canonical loop
13
13
 
@@ -74,7 +74,8 @@ Phases: RECEIVED, DISCOVERING, CONTRACT_READY, ROUTED, DESIGNING, PLANNED, EXECU
74
74
  | Feature | Version | Supported |
75
75
  | --- | --- | --- |
76
76
  | adaptiveExecutionProfiles | 1 | yes |
77
- | canonicalHandoffs | 1 | yes |
77
+ | advisoryContextProviders | 1 | yes |
78
+ | canonicalHandoffs | 2 | yes |
78
79
  | capabilityPolicy | 1 | yes |
79
80
  | codeAttestation | 1 | yes |
80
81
  | compactLifecycleOutput | 1 | yes |
@@ -100,6 +101,21 @@ Phases: RECEIVED, DISCOVERING, CONTRACT_READY, ROUTED, DESIGNING, PLANNED, EXECU
100
101
  | verificationExecutionIsolation | 1 | yes |
101
102
  | workspaceBinding | 1 | yes |
102
103
 
104
+ ## Capability contracts
105
+
106
+ - `canonicalHandoffs` v2: immutable, supported, and
107
+ ledger-backed for exactly-once operational acceptance through
108
+ `handoff-accept`. Acceptance statuses are
109
+ `OPEN` / `ACCEPTED` / `UNBOUND` / `INCONSISTENT`; it creates no claims,
110
+ evidence, or lifecycle authority.
111
+ - `advisoryContextProviders` v1: provider-neutral,
112
+ Integration-API-only, lazy, and opt-in. Provider results are not persisted by
113
+ ForgeLoop and are never lifecycle state, evidence, authority, or executable
114
+ instructions.
115
+
116
+ Protocol v1, schema v1, and Integration API v1 remain independent of these
117
+ capability-family versions.
118
+
103
119
  ## Public artifact registry
104
120
 
105
121
  | Key | Scope | Path | Schema | Trust role |
@@ -248,6 +264,12 @@ Phases: RECEIVED, DISCOVERING, CONTRACT_READY, ROUTED, DESIGNING, PLANNED, EXECU
248
264
  | responsibility-set | MUTATING | Creates immutable, mechanically verifiable constraints for a task pass. |
249
265
  | responsibility-status | READ_ONLY | Validates active responsibility constraints against current paths, inputs, and checks. |
250
266
 
267
+ ### task
268
+
269
+ | Command | Mutation | Purpose |
270
+ | --- | --- | --- |
271
+ | handoff-accept | MUTATING | Accepts an immutable handoff exactly once in the task event ledger. |
272
+
251
273
  ### verification
252
274
 
253
275
  | Command | Mutation | Purpose |
@@ -301,8 +323,12 @@ Phases: RECEIVED, DISCOVERING, CONTRACT_READY, ROUTED, DESIGNING, PLANNED, EXECU
301
323
  | E_ATTESTATION_TARGET_REF_INVALID | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
302
324
  | E_ATTESTATION_UNSIGNED | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
303
325
  | E_CLI_INVOCATION_INVALID | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
326
+ | E_HANDOFF_ACCEPTANCE_INCONSISTENT | Handoff acceptance disagrees with task event ledger history. |
327
+ | E_HANDOFF_ACCEPTANCE_UNBOUND | Handoff snapshot lacks required workStateFingerprint binding. |
328
+ | E_HANDOFF_ALREADY_ACCEPTED | Handoff was already accepted by a different consumer. |
304
329
  | E_HANDOFF_INVALID | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
305
330
  | E_HANDOFF_NOT_FOUND | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
331
+ | E_HANDOFF_STALE | Handoff snapshot has drifted from the current canonical task state or repository. |
306
332
  | E_HANDOFF_STATE_UNAVAILABLE | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
307
333
  | E_HANDOFF_TAMPERED | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
308
334
  | E_RESPONSIBILITY_FROZEN_INPUT_DRIFT | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
@@ -950,6 +950,7 @@ completion, or authority evidence.
950
950
  - `phase` *(string, required, minLength: 1)*
951
951
  - `revision` *(integer, required, minimum: 0)*
952
952
  - `verificationCycle` *(integer, required, minimum: 1)*
953
+ - `workStateFingerprint` *(string, optional, pattern: `^[a-f0-9]{64}$`)*
953
954
  - `contractFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
954
955
  - `routeFingerprint` *(string or null, required)*
955
956
  - `repositoryFingerprint` *(object, required)*
@@ -965,6 +966,19 @@ completion, or authority evidence.
965
966
 
966
967
  <!-- END FORGELOOP GENERATED: schema:handoff-envelope -->
967
968
 
969
+ The handoff `state` binds the immutable snapshot to the exact
970
+ `workStateFingerprint`, contract identity, route identity, selected-guide
971
+ context, repository branch/HEAD fingerprint, changed paths, and historical
972
+ write claims observed at creation. `HANDOFF_CREATED` records the envelope's
973
+ relationship to the task ledger. A later `HANDOFF_ACCEPTED` event records only
974
+ that one consumer operationally consumed the unchanged snapshot; it does not
975
+ transfer claims, create evidence, or grant authority.
976
+
977
+ Acceptance status is a derived projection from the immutable handoff, its
978
+ digest, and the validated event ledger. Acceptance fields are intentionally not
979
+ stored in the handoff JSON itself. Invalid or mismatched ledger history
980
+ projects `INCONSISTENT`, never a successful acceptance.
981
+
968
982
  ### 2.27 `task-state/<taskKey>/responsibility.json`
969
983
 
970
984
  <!-- forgeloop-doc: schema=responsibility artifact=.forgeloop/task-state/<task-key>/responsibility.json -->
@@ -1203,3 +1217,18 @@ For `BASELINE` artifacts and `PASS`/`FAIL` evaluations, `sourceMaterialFingerpri
1203
1217
  and stable `sourceObservation` are conditionally required; their before and after
1204
1218
  fingerprints must equal the bound source fingerprint. `BLOCKED` and
1205
1219
  `NOT_OBSERVED` artifacts may omit these observed-source fields.
1220
+
1221
+ ## Transaction diagnostics and retention
1222
+
1223
+ `.forgeloop/.txn/<transactionId>/manifest.json` records transaction identity,
1224
+ status, staged writes, and recovery diagnostics. `COMMITTED`, `ROLLED_BACK`,
1225
+ and `ABORTED` are terminal; an aborted staging callback did not publish its
1226
+ staged writes. A successful recovery is not reported as incomplete on the next
1227
+ doctor inspection. The transaction lock still protects recovery from live
1228
+ writers.
1229
+
1230
+ The repository maintenance command described in
1231
+ [CONTRIBUTING.md](../CONTRIBUTING.md#focused-verification-and-maintenance)
1232
+ compacts eligible stage/backup payloads only. It retains manifests and ledgers,
1233
+ so historical manifest enumeration remains linear. These diagnostics are not
1234
+ substitutes for a valid execution receipt or external-action reconciliation.
@@ -66,6 +66,7 @@ error codes. Default output and default JSON remain unchanged.
66
66
  | **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) |
67
67
  | **Policy & Auditing** | [`policy`](#policy), [`policy-discover`](#policy-discover), [`policy-status`](#policy-status), [`policy-diff`](#policy-diff), [`rule-verify`](#rule-verify), [`baseline`](#baseline), [`bundle`](#bundle) |
68
68
  | **workspace** | [`workspace-bind`](#workspace-bind), [`workspace-status`](#workspace-status) |
69
+ | **task** | [`handoff-accept`](#handoff-accept) |
69
70
  | **scope** | [`responsibility-set`](#responsibility-set), [`responsibility-status`](#responsibility-status) |
70
71
  | **attestation** | [`attestation-create`](#attestation-create), [`attestation-verify`](#attestation-verify), [`attestation-status`](#attestation-status), [`attestation-verify-range`](#attestation-verify-range) |
71
72
 
@@ -157,6 +158,9 @@ Lists immutable handoff snapshots for a task.
157
158
 
158
159
  - **Purpose**: Inspect existing handoff snapshots without changing them.
159
160
  - **Mutation**: Read-only.
161
+ - **Acceptance projection**: Derives `OPEN`, `ACCEPTED`, `UNBOUND`, or
162
+ `INCONSISTENT` from the validated event ledger. Invalid or unreadable ledgers
163
+ are fail-closed and expose `reasonCodes`; they are never treated as empty.
160
164
  - **Options**:
161
165
 
162
166
  <!-- BEGIN FORGELOOP GENERATED: cli:handoff-list:options -->
@@ -178,6 +182,8 @@ Lists immutable handoff snapshots for a task.
178
182
  Reads and verifies one immutable handoff snapshot.
179
183
 
180
184
  - **Purpose**: Inspect one handoff by ID and validate its digest and bindings.
185
+ - **Acceptance projection**: Uses the same fail-closed ledger-derived status as
186
+ `handoff-list`.
181
187
  - **Mutation**: Read-only.
182
188
  - **Options**:
183
189
 
@@ -196,6 +202,37 @@ Reads and verifies one immutable handoff snapshot.
196
202
  forgeloop handoff-show --task task-001 --id handoff-001 --json
197
203
  ```
198
204
 
205
+ ### `handoff-accept`
206
+
207
+ Records exactly-once acceptance of an immutable handoff into the task event ledger.
208
+
209
+ - **Purpose**: Bind an incoming consumer/harness to an immutable handoff snapshot.
210
+ - **Mutation**: Appends a `HANDOFF_ACCEPTED` event.
211
+ - **Freshness**: Acceptance requires the current canonical state and directly
212
+ observed repository branch/HEAD to match the immutable snapshot, including a
213
+ clean committed HEAD drift check.
214
+ - **Human output**: Reports `authority: OPERATIONAL_RECEIPT_ONLY`,
215
+ `evidence: NONE`, and `claims transferred: NO`; acceptance is exactly-once
216
+ operational receipt only.
217
+ - **Options**:
218
+
219
+ <!-- BEGIN FORGELOOP GENERATED: cli:handoff-accept:options -->
220
+
221
+ - `--path <directory>`: target project directory (default: current directory)
222
+ - `--task <id>`: task ID to operate on (when omitted, resolved from context or single active task)
223
+ - `--handoff <id>`: handoff identifier
224
+ - `--consumer-id <id>`: consumer identifier accepting the handoff
225
+ - `--harness <name>`: optional harness accepting the handoff
226
+ - `--json`: emit acceptance result as JSON
227
+
228
+ <!-- END FORGELOOP GENERATED: cli:handoff-accept:options -->
229
+
230
+ - **Example**:
231
+
232
+ ```bash
233
+ forgeloop handoff-accept --task task-001 --handoff handoff-001 --consumer-id agent-42 --json
234
+ ```
235
+
199
236
  ### `responsibility-set`
200
237
 
201
238
  Creates immutable constraints for the current task pass.
@@ -914,6 +951,9 @@ Records operational handoff context before pausing or switching tools.
914
951
  Reconciles continuity with the active work state and checkout.
915
952
 
916
953
  - **Purpose**: Compares continuity bindings against the canonical work state, contract, phase, repository fingerprint, and checkout state.
954
+ - **Lint**: Returns deterministic `PASS`/`WARN` findings for stale completed
955
+ item references, role conflicts, missing `inspectFirst` paths, and empty hint
956
+ sets without changing reconciliation classification.
917
957
  - **When to use**: When starting a session in an active task.
918
958
  - **Mutation**: Read-only.
919
959
  - **Options**:
@@ -139,3 +139,12 @@ distinguished from invalid attestations by the stable exit-code contract:
139
139
 
140
140
  See [`REVISION_PROVIDERS.md`](./REVISION_PROVIDERS.md) and
141
141
  [`SIGNING_PROVIDERS.md`](./SIGNING_PROVIDERS.md) for extension boundaries.
142
+
143
+ ## Receipt availability in repository CI
144
+
145
+ The repository audit workflow checks supplied task receipts individually with
146
+ an explicit task ID. A checkout without a receipt reports `NOT_VERIFIED`.
147
+ That is absence of lifecycle evidence, not an attestation trust level; it does
148
+ not mean `PROCESSED`, `VERIFIED`, or `ATTESTED`. CI does not fabricate a receipt
149
+ from successful repository tests. Transaction payload compaction preserves
150
+ the manifests and ledgers needed to inspect the original history.
@@ -114,6 +114,33 @@ exists, compare the current checkout, and only then follow `forgeloop next`.
114
114
  Handoff notes can focus inspection, but only valid execution evidence,
115
115
  completion receipts, and the append-only ledger can satisfy verification.
116
116
 
117
+ The complete immutable-handoff flow is:
118
+
119
+ ```bash
120
+ forgeloop handoff-create --task auth-feature --recipient codex --json
121
+ forgeloop handoff-list --task auth-feature --json
122
+ forgeloop handoff-show --task auth-feature --id <handoff-id> --json
123
+ forgeloop handoff-accept \
124
+ --task auth-feature \
125
+ --handoff <handoff-id> \
126
+ --consumer-id codex-session-42 \
127
+ --harness codex \
128
+ --json
129
+ ```
130
+
131
+ Before acceptance, the receiver must inspect the immutable snapshot and
132
+ reconcile all of its freshness bindings: the work-state fingerprint, contract
133
+ identity, route identity, selected guides, current repository branch, current
134
+ repository HEAD, changed paths, and the origin of the event ledger. Receiving a
135
+ file or message is not acceptance. `handoff-accept` is run only when the
136
+ receiving harness actually consumes the handoff.
137
+
138
+ Acceptance retry semantics are deterministic: retrying with the same
139
+ `consumerId` returns the existing operational receipt idempotently; a different
140
+ consumer fails with `E_HANDOFF_ALREADY_ACCEPTED`. An old unbound handoff remains
141
+ readable for historical continuity but is not acceptable and returns
142
+ `E_HANDOFF_ACCEPTANCE_UNBOUND`.
143
+
117
144
  ---
118
145
 
119
146
  ## 4. Harness A — Recording Handoff Context
@@ -251,3 +278,61 @@ Every discovery adapter (`AGENTS.md`, `CLAUDE.md`, `.cursor/rules/project-loop.m
251
278
  > Discover task namespaces with ForgeLoop; if exactly one active task is healthy it may be selected implicitly; if multiple active tasks exist, select with `--task` or `FORGELOOP_TASK`.
252
279
  > Inspect the existing task, reconcile continuity when present, inspect the checkout, and run `forgeloop next`.
253
280
  > A change of harness, model, provider, IDE, process, terminal, or session does not create a new task.
281
+
282
+ ---
283
+
284
+ ## 8. Canonical Handoff Acceptance & State Binding
285
+
286
+ ### 8.1 Work-State Binding
287
+
288
+ Handoff envelopes (`.forgeloop/task-state/<taskKey>/handoffs/handoff-*.json`) bind to the exact lifecycle state snapshot at creation time via `state.workStateFingerprint`.
289
+ The envelope itself remains strictly immutable after creation.
290
+ A handoff is acceptable only when both canonical state and the current repository
291
+ checkout still match that immutable snapshot. A clean Git HEAD or branch change
292
+ can make a handoff stale even when the worktree has no uncommitted changes.
293
+
294
+ ### 8.2 Exactly-Once Handoff Acceptance
295
+
296
+ Harnesses taking ownership of an existing handoff record their acceptance into the task event ledger using `handoff-accept`:
297
+
298
+ ```bash
299
+ forgeloop handoff-accept \
300
+ --task auth-feature \
301
+ --handoff handoff-001 \
302
+ --consumer-id agent-session-42 \
303
+ --harness cursor \
304
+ --json
305
+ ```
306
+
307
+ Acceptance enforces:
308
+
309
+ 1. **Unbroken Binding**: Handoff must contain `workStateFingerprint` (legacy unbound handoffs fail with `E_HANDOFF_ACCEPTANCE_UNBOUND`).
310
+ 2. **Freshness**: Work state, contract fingerprint, route fingerprint, changed paths, and the directly observed current repository branch and HEAD must match the handoff snapshot (any drift fails with `E_HANDOFF_STALE`).
311
+ 3. **Single Consumer**: The handoff can be accepted by at most one consumer. If another consumer attempts acceptance, it fails with `E_HANDOFF_ALREADY_ACCEPTED`. Retrying with the same `consumerId` is idempotent.
312
+ 4. **Ledger Integrity**: An immutable `HANDOFF_ACCEPTED` event is appended to `events.ndjson`.
313
+
314
+ Acceptance is exactly-once operational receipt only. It does not transfer claims,
315
+ delegate work, authorize actions, approve review, or create verification evidence.
316
+
317
+ ### 8.3 Acceptance Inspection
318
+
319
+ Commands `handoff-show` and `handoff-list` project current acceptance status:
320
+
321
+ - `OPEN`: Handoff is valid, bound, and waiting for acceptance.
322
+ - `ACCEPTED`: Successfully accepted by a specific consumer.
323
+ - `UNBOUND`: Legacy handoff envelope lacking work-state binding.
324
+ - `INCONSISTENT`: Digest, ledger validation, or acceptance event mismatch detected. An unreadable or invalid ledger is never projected as `OPEN` or `ACCEPTED`; its unique sorted ledger error codes are exposed as `reasonCodes`.
325
+
326
+ ### 8.4 Semantic Continuity Linting
327
+
328
+ When running `forgeloop reconcile-continuity`, ForgeLoop executes deterministic
329
+ semantic lint checks against schema-valid operational hints. It warns when a
330
+ remaining-work item or current focus ID is already in `state.completedSteps`,
331
+ when an ID appears in both `remainingWork` and `knownIssues`, or when a relative
332
+ `inspectFirst` path is missing from the target. If all operational hints are
333
+ empty, it emits the informational `CONTINUITY_EMPTY_HINT_SET` finding while the
334
+ lint status remains `PASS`.
335
+
336
+ Lint results use `{ status: "PASS" | "WARN", findings: [...] }`. They are
337
+ non-authoritative, non-evidence diagnostics and do not change reconciliation
338
+ classification or lifecycle state.
@@ -24,12 +24,12 @@ ForgeLoop strictly separates normative protocol definitions from operational doc
24
24
  When updating documentation, always derive content from its authoritative source:
25
25
 
26
26
  ```text
27
- CLI syntax truth -> CLI registry / parser (src/cli.js, src/core/cli-command-definitions.js, src/core/cli-metadata.js)
27
+ CLI syntax truth -> CLI registry / parser (src/cli.js, src/core/cli-command-definitions.js)
28
28
  Artifact shape truth -> JSON schemas (schemas/*.schema.json, src/core/artifact-registry.js)
29
29
  Lifecycle truth -> protocol / state machine (src/core/protocol.js)
30
30
  Reason-code truth -> exported protocol constants (src/core/error-codes.js, src/core/protocol.js)
31
31
  Guide registry truth -> canonical guide registry (src/config/guides.json)
32
- Package contents truth -> package.json + package tests (tests/package.test.js)
32
+ Package contents truth -> package.json + docs/PACKAGE_CONTENTS.md + package tests (tests/package.test.js)
33
33
  Documentation routing -> DOCS_INDEX.md
34
34
  Integration API truth -> src/integration.js (exports, envelope, limits, risk classes, resources)
35
35
  MCP behavior truth -> integrations/mcp/src/* and integrations/mcp/package.json
@@ -38,6 +38,13 @@ MCP package boundary -> MCP package tests + scripts/mcp-package-smoke.mjs
38
38
 
39
39
  Operational documentation must explain canonical behavior, not redefine it.
40
40
 
41
+ Terminology must remain consistent across active documents: say “advisory
42
+ context,” not “canonical memory”; “handoff acceptance,” not “ownership
43
+ transfer”; and “operational receipt,” not “delegation.” Advisory output is
44
+ never canonical state, evidence, authority, completion truth, or next-action
45
+ authority. `consumerId`, harness names, recipient hints, and transport labels
46
+ are descriptive values rather than authenticated identity or authority.
47
+
41
48
  Documentation-impact questions for integration/MCP changes:
42
49
 
43
50
  - Did a server mode or capability gate change?
@@ -112,7 +119,7 @@ conformance checks detect omissions.
112
119
 
113
120
  | Documentation Area | Canonical Machine Source | Conformance Validator |
114
121
  | --- | --- | --- |
115
- | **CLI commands & flags** | `CLI_COMMAND_METADATA` (`src/core/cli-metadata.js`) & `src/cli.js` | `scripts/validate_documentation_conformance.mjs` |
122
+ | **CLI commands & flags** | `CLI_COMMAND_DEFINITIONS` (`src/core/cli-command-definitions.js`) & `src/cli.js` | `scripts/validate_documentation_conformance.mjs` |
116
123
  | **Artifact paths** | `ARTIFACT_REGISTRY` & `task-paths.js` | `scripts/validate_documentation_conformance.mjs` |
117
124
  | **Artifact fields & types** | `schemas/*.schema.json` | `scripts/validate_documentation_conformance.mjs` |
118
125
  | **Enums & consts** | `schemas/*.schema.json` | `scripts/validate_documentation_conformance.mjs` |
@@ -121,7 +128,7 @@ conformance checks detect omissions.
121
128
  | **Stable error codes** | `PUBLIC_ERROR_CODES` (`src/core/error-codes.js`) | `scripts/validate_documentation_conformance.mjs` |
122
129
  | **Discovery resume rules** | `DISCOVERY_SURFACES` & `nativeShim` | `scripts/validate_documentation_conformance.mjs` |
123
130
  | **Task-layout path freshness** | `TASK_LAYOUT_DOCUMENTS` & `task-paths.js` | `scripts/validate_documentation_conformance.mjs` |
124
- | **Package-shipped docs** | `package.json` (`files`) | `tests/package.test.js` |
131
+ | **Package-shipped docs and runtime** | `package.json` (`files`) + `docs/PACKAGE_CONTENTS.md` | `tests/package.test.js` + `scripts/package_smoke.mjs` |
125
132
  | **Architecture and trust diagrams** | `docs/diagrams/manifest.json` plus each typed workflow source | `scripts/check-documentation-diagrams.mjs` and `scripts/documentation-diagram-inventory.mjs` |
126
133
 
127
134
  ---
@@ -421,3 +421,13 @@ The source policy is intentionally narrow: provider or host observations are
421
421
  accepted for benchmark claims, while actor-reported or absent telemetry stays
422
422
  non-comparable. This is an efficiency observation boundary, not verification
423
423
  evidence and not an external publication result.
424
+
425
+ ## Contract signals and exclusions
426
+
427
+ Profile selection reads string and structured success/verification
428
+ requirements, including nested requirements and explicit publication or
429
+ production-readiness types. Constraints and stop conditions describe
430
+ boundaries and are excluded from obligation scanning. For example, a
431
+ constraint saying “No publication” does not create a publication requirement.
432
+ An explicit route risk remains authoritative and can still raise the safety
433
+ floor. Profiles classify work; they do not grant execution authority.
@@ -439,6 +439,8 @@ the workflow needs those boundaries:
439
439
  forgeloop handoff-create --task <taskId> --note "Continue verification" --json
440
440
  forgeloop handoff-list --task <taskId> --json
441
441
  forgeloop handoff-show --task <taskId> --id <handoffId> --json
442
+ forgeloop handoff-accept --task <taskId> --handoff <handoffId> \
443
+ --consumer-id <consumerId> --harness <harness> --json
442
444
  forgeloop responsibility-set --task <taskId> --label implementation --allowed-path src --required-check unit-tests --json
443
445
  forgeloop responsibility-status --task <taskId> --json
444
446
  ```
@@ -450,6 +452,26 @@ not delegation or evidence. A responsibility label is descriptive, not a
450
452
  coder/reviewer/cleaner role, and its allowed paths, required checks, and frozen
451
453
  inputs are mechanically enforced when present.
452
454
 
455
+ ### Optional advisory context
456
+
457
+ An embedding host may inject an advisory provider through the Integration API
458
+ when extra context is useful. This is not part of the minimum quickstart:
459
+
460
+ ```javascript
461
+ const runtimeContext = createForgeLoopContext({
462
+ advisoryContextProviders: {
463
+ "host-context": {
464
+ id: "host-context",
465
+ recall: async ({ query }) => ({ items: await hostLookup(query) }),
466
+ },
467
+ },
468
+ });
469
+ ```
470
+
471
+ Recall is explicit, lazy, bounded, and non-persisted. Provider output is never
472
+ state, evidence, authority, completion truth, or executable instructions. See
473
+ [`ADVISORY_CONTEXT.md`](./ADVISORY_CONTEXT.md) for the full contract.
474
+
453
475
  ### Differential Verification Scope
454
476
 
455
477
  Configure a trusted scoped checker only when it can consume canonical paths:
@@ -8,6 +8,16 @@ Target: ForgeLoop 1.8.0 at current `main` state at review start
8
8
  This ledger records research inputs for the knowledge-integration review. It is
9
9
  not an endorsement list, a source-content mirror, or an evidence registry.
10
10
 
11
+ ## Current optional provider source class
12
+
13
+ This note is an operational boundary added after the historical snapshot above;
14
+ it does not rewrite that review's target version or accepted sources. A host may
15
+ provide external advisory context through the ForgeLoop Integration API, but a
16
+ knowledge source is not canonical task state, evidence, authority, completion,
17
+ or next-action authority. Provider results remain lazy, opt-in, bounded, and
18
+ non-persisted; provenance belongs to the host unless a separately versioned
19
+ canonical artifact is introduced.
20
+
11
21
  ## User-provided revised plan
12
22
 
13
23
  Source: user-provided `FORGELOOP_LUNA_KNOWLEDGE_INTEGRATION_PLAN_REVISED.md`
package/docs/MCP.md CHANGED
@@ -25,6 +25,9 @@ Two transports ship in one package:
25
25
  - **Recovery acknowledgement is not authorization.** `acknowledgeRecovery`
26
26
  in tool input only satisfies ForgeLoop's caller acknowledgement after the
27
27
  server was started with recovery capability.
28
+ - **Advisory context is host-injected only.** The core Integration API supports
29
+ explicit provider injection, but the stock MCP adapter must not fabricate,
30
+ auto-discover, or persist an advisory provider or its results.
28
31
 
29
32
  ## Modes
30
33
 
@@ -84,6 +87,19 @@ content.
84
87
  Raw recovery artifacts, transaction journals, lock files, and unbounded event
85
88
  ledgers are intentionally not exposed.
86
89
 
90
+ The `handoff-accept` mutating command is available only through a mode that
91
+ allows loop mutations; `readonly` intentionally hides it. When exposed, it
92
+ records one canonical `HANDOFF_ACCEPTED` operational receipt and preserves the
93
+ same freshness, consumer-idempotency, ledger, and no-claim-transfer rules as
94
+ the CLI and Integration API. MCP transport metadata cannot authenticate a
95
+ `consumerId`, establish authority, or turn receipt of a message into
96
+ acceptance.
97
+
98
+ Advisory provider recall is not a stock MCP resource or command. A host that
99
+ needs advisory context injects a provider into the core Integration API and
100
+ performs an explicit bounded recall itself. MCP must never auto-recall context
101
+ for startup, status, next, task/context, or any other canonical projection.
102
+
87
103
  The context resource is read-only. It lets an MCP host adapt presentation depth
88
104
  from the canonical resolved execution profile while preserving lifecycle
89
105
  phases, required gates, verification truth, authority, provenance, and
@@ -119,7 +135,7 @@ forgeloop-mcp-http --project /repo --mode safe # 127.0.0.1:3333
119
135
 
120
136
  | Component | Current contract |
121
137
  | --- | --- |
122
- | ForgeLoop core package | `>=1.5.0 <2` dependency range; current repository generation `1.9.x` |
138
+ | ForgeLoop core package | `>=1.5.0 <2` dependency range; current release `1.10.1` |
123
139
  | ForgeLoop protocol | `1` |
124
140
  | Integration API | `1` |
125
141
  | MCP package | `0.1.x` initial package |
@@ -171,3 +187,15 @@ list in [TROUBLESHOOTING](./TROUBLESHOOTING.md):
171
187
 
172
188
  Canonical ForgeLoop errors (e.g. `E_TASK_SCOPE_CONFLICT`,
173
189
  `E_TASK_CLAIM_OWNERSHIP_INCONSISTENT`) are always preserved verbatim.
190
+
191
+ ## Reproducible adapter verification
192
+
193
+ The adapter commits its own lockfile and declares both server and test-client
194
+ SDK versions. `npm run mcp:setup` installs that lock with lifecycle scripts
195
+ disabled, then substitutes the locally packed core offline. Packed smoke uses
196
+ the same dependency graph and substitutes both local tarballs using the system
197
+ `tar` command. This replacement does not resolve registry metadata or require a
198
+ warm npm cache; `npm ci` still retrieves the locked dependencies. Both paths
199
+ verify resolved dependency versions and print lock/tarball SHA-256 identities.
200
+ The adapter remains a separate package; these dependencies are not added to
201
+ the ForgeLoop core runtime.