@cassiomc1/forgeloop 1.8.1 → 1.10.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 (93) hide show
  1. package/.cursor/rules/project-loop.mdc +6 -3
  2. package/.github/copilot-instructions.md +5 -0
  3. package/AGENTS.md +6 -0
  4. package/AGENT_COMPATIBILITY.md +15 -0
  5. package/CLAUDE.md +6 -0
  6. package/DELEGATION_PROTOCOL.md +6 -0
  7. package/DOCS_INDEX.md +9 -2
  8. package/ENG/accessibility-eng.md +12 -2
  9. package/ENG/design-code-eng.md +22 -1
  10. package/LOOP_ENGINEERING.md +41 -0
  11. package/LOOP_SYSTEM_DESIGN.md +33 -0
  12. package/ORCHESTRATOR_INTEGRATION.md +9 -0
  13. package/PROTOCOL_INTEGRATION.md +57 -0
  14. package/QUALITY_SCORECARD.md +2 -0
  15. package/README.md +51 -0
  16. package/TERMINOLOGY.md +12 -0
  17. package/THREAT_MODEL.md +48 -0
  18. package/completions/_forgeloop +5 -1
  19. package/completions/forgeloop.bash +9 -1
  20. package/completions/forgeloop.fish +27 -1
  21. package/docs/ADVISORY_CONTEXT.md +174 -0
  22. package/docs/AGENT_PROTOCOL_SUMMARY.md +33 -2
  23. package/docs/ARTIFACT_REFERENCE.md +142 -0
  24. package/docs/CLI_REFERENCE.md +124 -1
  25. package/docs/CROSS_HARNESS_CONTINUITY.md +85 -0
  26. package/docs/DOCUMENTATION_GUIDE.md +7 -0
  27. package/docs/GETTING_STARTED.md +22 -0
  28. package/docs/KNOWLEDGE_SOURCES.md +171 -0
  29. package/docs/MCP.md +17 -1
  30. package/docs/RECIPES.md +111 -0
  31. package/docs/RELEASE_CHECKLIST.md +14 -0
  32. package/docs/STRUCTURAL_QUALITY.md +350 -0
  33. package/docs/TROUBLESHOOTING.md +161 -2
  34. package/docs/UNIVERSAL_INTEGRATION.md +60 -0
  35. package/package.json +4 -1
  36. package/schemas/config.schema.json +46 -0
  37. package/schemas/handoff-envelope.schema.json +1 -0
  38. package/schemas/preflight.schema.json +2 -1
  39. package/schemas/structural-quality.schema.json +175 -0
  40. package/scripts/check-changelog-freshness.mjs +27 -3
  41. package/scripts/generate-agent-protocol-summary.mjs +18 -0
  42. package/src/cli.js +24 -0
  43. package/src/commands/handoff-accept.js +36 -0
  44. package/src/commands/handoff-list.js +28 -2
  45. package/src/commands/handoff-show.js +27 -2
  46. package/src/commands/quality-baseline.js +28 -0
  47. package/src/commands/quality-status.js +34 -0
  48. package/src/commands/quality-verify.js +30 -0
  49. package/src/commands/reconcile-continuity.js +4 -0
  50. package/src/core/advisory-context/constants.js +74 -0
  51. package/src/core/advisory-context/provider.js +287 -0
  52. package/src/core/advisory-context/service.js +140 -0
  53. package/src/core/artifact-registry.js +12 -0
  54. package/src/core/audit.js +38 -0
  55. package/src/core/bundles.js +134 -1
  56. package/src/core/cli-command-definitions.js +62 -0
  57. package/src/core/command-executors.js +28 -0
  58. package/src/core/command-input.js +23 -1
  59. package/src/core/completion-artifacts.js +2 -0
  60. package/src/core/completion.js +42 -0
  61. package/src/core/config.js +3 -0
  62. package/src/core/continuity-lint.js +89 -0
  63. package/src/core/continuity-reconciliation.js +16 -0
  64. package/src/core/continuity.js +10 -11
  65. package/src/core/error-codes.js +186 -0
  66. package/src/core/events.js +32 -0
  67. package/src/core/execution-profile-context.js +15 -1
  68. package/src/core/filesystem.js +34 -3
  69. package/src/core/handoff-acceptance.js +277 -0
  70. package/src/core/handoff.js +41 -8
  71. package/src/core/inspect.js +64 -0
  72. package/src/core/integration-invocation-policy.js +34 -2
  73. package/src/core/integration-resources.js +38 -1
  74. package/src/core/next-action-model.js +11 -1
  75. package/src/core/next-action-phases.js +84 -5
  76. package/src/core/phase.js +9 -1
  77. package/src/core/portable-context.js +103 -0
  78. package/src/core/preflight.js +33 -0
  79. package/src/core/protocol-info.js +33 -2
  80. package/src/core/runtime-context.js +58 -0
  81. package/src/core/schema-validation.js +1 -0
  82. package/src/core/structural-quality/artifacts.js +329 -0
  83. package/src/core/structural-quality/constants.js +67 -0
  84. package/src/core/structural-quality/policy.js +227 -0
  85. package/src/core/structural-quality/provider.js +287 -0
  86. package/src/core/structural-quality/sentrux-mcp.js +477 -0
  87. package/src/core/structural-quality/service.js +1138 -0
  88. package/src/core/structural-quality/source-fingerprint.js +112 -0
  89. package/src/core/structural-quality/status.js +3 -0
  90. package/src/core/task-paths.js +24 -0
  91. package/src/core/templates.js +1 -0
  92. package/src/integration.d.ts +141 -0
  93. package/src/integration.js +36 -0
package/THREAT_MODEL.md CHANGED
@@ -124,6 +124,54 @@ provide a universal exactly-once guarantee.
124
124
  | Signature confusion | A plain digest or platform publication signal is presented as a cryptographic signature | External signing-provider boundary | `ATTESTED` requires a valid external signature under the requested signer policy; private keys and tokens never enter persisted artifacts | Trust in the external signer and transparency infrastructure remains outside ForgeLoop | `tests/signing-provider.test.js` |
125
125
  | Incomplete revision coverage | A changed source path has no valid task attestation or overlaps another task with a conflicting digest | Provider-neutral range coverage evaluator | Changed, covered, uncovered, and overlapping paths are computed from the selected revision provider; enforcement fails closed on gaps or conflicts | Coverage is limited to the provider's observable revision/content boundary | `tests/attestation-coverage.test.js`, `tests/generic-ci-attestation.test.js` |
126
126
 
127
+ ## Advisory context provider boundary
128
+
129
+ Advisory provider output is untrusted external input. ForgeLoop exposes only a
130
+ bounded, allowlisted, non-evidence and non-executable projection through the
131
+ Integration API. Provider identity and availability are explicit; no provider
132
+ is discovered or invoked by lifecycle commands, and provider text is never
133
+ treated as trusted protocol input.
134
+
135
+ | Threat | Mitigation | Residual limitation | Test evidence |
136
+ | --- | --- | --- | --- |
137
+ | Prompt injection in advisory results | Portable text checks, authority-field stripping, and `actionability: NON_EXECUTABLE` prevent provider text from becoming commands or lifecycle instructions | A host may still choose to display or act on advisory text outside ForgeLoop | `tests/advisory-context-security.test.js`, `tests/portable-context.test.js` |
138
+ | Sensitive provider-output leakage | Secret-like values are rejected in selected portable fields; unknown fields are discarded before logging or projection | Unknown encodings and secrets returned only through an external host remain outside this scanner | `tests/advisory-context-security.test.js` |
139
+ | Provider identity substitution | Registry key and resolved provider `id` must match the declared identity | A host that controls the runtime registry can replace its own provider before the call | `tests/advisory-context-runtime.test.js` |
140
+ | Unbounded provider retrieval | Query, item, total-output, raw-result, and timeout budgets are normalized and enforced before/while provider execution | The host controls provider resource usage outside the bounded call | `tests/advisory-context-service.test.js`, `tests/advisory-context-provider.test.js` |
141
+ | Historical command replay from advisory text | Advisory output cannot satisfy command input, evidence, state, or next-action authority; recall is never automatic | A receiving host must still avoid copying untrusted text into its own command runner | `tests/advisory-context-security.test.js` |
142
+ | Handoff acceptance replay | Acceptance is keyed by the immutable handoff and consumer identity and is checked against the append-only ledger | External systems may still deliver duplicate messages; callers must surface the canonical rejection | `tests/handoff-acceptance.test.js` |
143
+ | Handoff double-consumption race | Serialized ledger append and exactly-once acceptance projection permit one consumer; same-consumer retry is idempotent | Filesystem privilege outside ForgeLoop can still corrupt local artifacts | `tests/handoff-acceptance.test.js`, `tests/concurrent-ledger.test.js` |
144
+ | Stale Git checkout acceptance | Acceptance compares the handoff snapshot with the current branch and HEAD, work-state, contract, route, and changed paths | A separately privileged process can change the checkout immediately after validation | `tests/handoff-acceptance.test.js` |
145
+ | Stale contract/route handoff | Handoff creation and acceptance bind contract and route fingerprints and fail closed on drift | The caller must create a fresh handoff after a legitimate contract or route change | `tests/handoff-envelope.test.js`, `tests/handoff-acceptance.test.js` |
146
+ | Invalid ledger projection | Handoff readers validate digest, event relationships, and the complete ledger; invalid history projects `INCONSISTENT`, never `OPEN` or `ACCEPTED` | Local consistency validation is not remote attestation against a privileged rewrite | `tests/handoff-acceptance.test.js`, `tests/handoff-tamper.test.js` |
147
+
148
+ ForgeLoop does not make advisory text trusted. It makes the boundary explicit,
149
+ bounded, and fail-closed where protocol-owned interpretation is required.
150
+
151
+ ## Structural-quality provider boundary
152
+
153
+ Structural-quality observations are untrusted external data. The built-in
154
+ adapter fixes the executable name to `sentrux`, passes `--mcp` with
155
+ `shell: false`, validates the MCP handshake and minimum version, bounds
156
+ combined stdout/stderr, and terminates a hung process. Project configuration
157
+ cannot choose an executable path, shell fragment, arbitrary arguments, or a
158
+ score. Runtime hosts may inject a provider only through the typed integration
159
+ context.
160
+
161
+ | Threat | Mitigation | Residual limitation | Test evidence |
162
+ | --- | --- | --- | --- |
163
+ | Malicious config launches `./sentrux` or another arbitrary executable | Config normalization rejects executable/argv/shell fields; built-in resolution uses the fixed `sentrux` command and shell-free spawn | A privileged host can launch its own process outside ForgeLoop | `tests/sentrux-structural-quality-provider.test.js` |
164
+ | PATH resolves an unexpected executable | Provider/version/transport identity is recorded and the provider boundary remains explicit; portable artifacts omit absolute executable paths | PATH itself is host-managed and cannot prove binary provenance | `tests/sentrux-structural-quality-provider.test.js` |
165
+ | Provider hangs, floods stdout/stderr, or sends malformed JSON-RPC | Monotonic request IDs, strict response validation, bounded output, timeout, SIGTERM, and bounded forced termination fail closed | A hostile process may still consume resources until the OS releases it | `tests/sentrux-structural-quality-provider.test.js` |
166
+ | Provider leaks confidential fields or outside-project paths | Normalization applies secret scanning, string/list limits, project containment, and safe relative paths before persistence | Unknown encodings may require host-level review | `tests/structural-quality-provider.test.js` |
167
+ | Provider version or provider configuration changes after baseline | Version, provider-config, policy, route, contract, and scope fingerprints bind baseline/current comparison; incompatible drift is incomparable | External files can change again after validation; architecture-rule provenance is intentionally a separate sensor | `tests/structural-quality-lifecycle.test.js`, `tests/structural-quality-policy.test.js` |
168
+ | Agent launders a regression by replacing the baseline | Replacement is allowed only before `EXECUTING`; superseded fingerprints remain in the ledger | A separately privileged actor can rewrite all local artifacts | `tests/structural-quality-artifacts.test.js` |
169
+ | Bundle quality evidence is tampered | Bundle import revalidates typed artifacts, bindings, fingerprints, cycle, and check references without rescanning | Local consistency is not remote attestation | `tests/structural-quality-bundle.test.js` |
170
+ | Observe or diagnostic absence is misreported as success | Unavailable evidence maps to `NOT_OBSERVED`, absent diagnostics remain `null`, and only gate PASS satisfies the quality requirement | Provider capability still determines diagnostic detail | `tests/structural-quality-lifecycle.test.js`, `tests/sentrux-structural-quality-provider.test.js` |
171
+
172
+ ForgeLoop never changes Sentrux analytics preferences, installs the provider,
173
+ or treats Sentrux Free diagnostics as necessary for score correctness.
174
+
127
175
  ## Boundary rules
128
176
 
129
177
  - Safe paths are checked before reading or writing; no protocol field is a
@@ -1,7 +1,7 @@
1
1
  #compdef forgeloop
2
2
  # Generated by scripts/generate-shell-completions.mjs. Do not edit.
3
3
  _arguments \
4
- '1:command:(action-authorize action-propose action-reconcile action-record action-show action-verify activate advance approval-request approval-resolve attestation-create attestation-status attestation-verify attestation-verify-range audit baseline bundle clear-continuity clear-state complete continuity doctor efficiency eval handoff-create handoff-list handoff-show history init inspect metrics migrate-protocol next policy policy-diff policy-discover policy-status preflight prepare-completion profile-interview progress protocol-info reconcile-closure reconcile-continuity record-check record-continuity record-decision-criterion record-diagnosis record-hypothesis-disposition record-intervention record-terminal-result reflect report responsibility-set responsibility-status route rule-verify run-action run-check status task-create task-list task-lock-status task-migrate task-recover task-repair-legacy-recovery task-resume task-scope task-show task-unlock trace update usage-record validate-protocol validate-receipt validate-state verify-scope workspace-bind workspace-status)' \
4
+ '1:command:(action-authorize action-propose action-reconcile action-record action-show action-verify activate advance approval-request approval-resolve attestation-create attestation-status attestation-verify attestation-verify-range audit baseline bundle clear-continuity clear-state complete continuity doctor efficiency eval handoff-accept handoff-create handoff-list handoff-show history init inspect metrics migrate-protocol next policy policy-diff policy-discover policy-status preflight prepare-completion profile-interview progress protocol-info quality-baseline quality-status quality-verify reconcile-closure reconcile-continuity record-check record-continuity record-decision-criterion record-diagnosis record-hypothesis-disposition record-intervention record-terminal-result reflect report responsibility-set responsibility-status route rule-verify run-action run-check status task-create task-list task-lock-status task-migrate task-recover task-repair-legacy-recovery task-resume task-scope task-show task-unlock trace update usage-record validate-protocol validate-receipt validate-state verify-scope workspace-bind workspace-status)' \
5
5
  '*::options:->options'
6
6
  case $words[2] in
7
7
  action-authorize) _arguments '--action[durable action ID]' '--approval[current fingerprint-bound approval]' '--help[show this help]' '--json[emit structured output as JSON]' '--path[target project directory (default: current directory)]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
@@ -28,6 +28,7 @@ case $words[2] in
28
28
  doctor) _arguments '--adopt[preserve an existing adapter in the manifest]' '--fix[restore missing managed template files]' '--help[show this help]' '--json[emit doctor findings as JSON]' '--path[target project directory (default: current directory)]' '--strict[treat warnings as unhealthy]' '--version[show the installed package version]' ;;
29
29
  efficiency) _arguments '--baseline[optional comparable efficiency baseline JSON]' '--help[show this help]' '--json[emit efficiency metrics as JSON]' '--path[target project directory (default: current directory)]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
30
30
  eval) _arguments '--help[show this help]' '--json[emit evaluation as JSON]' '--path[target project directory (default: current directory)]' '--scenario[project-local trajectory scenario JSON]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
31
+ handoff-accept) _arguments '--consumer-id[consumer identifier accepting the handoff]' '--handoff[handoff identifier]' '--harness[optional harness accepting the handoff]' '--help[show this help]' '--json[emit acceptance result as JSON]' '--path[target project directory (default: current directory)]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
31
32
  handoff-create) _arguments '--help[show this help]' '--json[emit handoff as JSON]' '--note[non-authoritative handoff note]' '--path[target project directory (default: current directory)]' '--recipient[non-authoritative recipient hint]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
32
33
  handoff-list) _arguments '--help[show this help]' '--json[emit handoff list as JSON]' '--path[target project directory (default: current directory)]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
33
34
  handoff-show) _arguments '--help[show this help]' '--id[handoff identifier]' '--json[emit handoff as JSON]' '--path[target project directory (default: current directory)]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
@@ -46,6 +47,9 @@ case $words[2] in
46
47
  profile-interview) _arguments '--dry-run[show planned interview questions without changing files]' '--help[show this help]' '--json[emit structured output as JSON]' '--path[target project directory (default: current directory)]' '--version[show the installed package version]' ;;
47
48
  progress) _arguments '--help[show this help]' '--json[emit progress evaluation as JSON]' '--path[target project directory (default: current directory)]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
48
49
  protocol-info) _arguments '--help[show this help]' '--json[emit complete machine-readable protocol metadata]' '--path[target project directory (default: current directory)]' '--version[show the installed package version]' ;;
50
+ quality-baseline) _arguments '--help[show this help]' '--json[emit baseline result as JSON]' '--path[target project directory (default: current directory)]' '--replace[replace a different baseline before EXECUTING]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--timeout-ms[bounded analyzer timeout in milliseconds]' '--version[show the installed package version]' ;;
51
+ quality-status) _arguments '--help[show this help]' '--json[emit persisted structural-quality status as JSON]' '--path[target project directory (default: current directory)]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
52
+ quality-verify) _arguments '--help[show this help]' '--json[emit structural-quality verification as JSON]' '--path[target project directory (default: current directory)]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--timeout-ms[bounded analyzer timeout in milliseconds]' '--version[show the installed package version]' ;;
49
53
  reconcile-closure) _arguments '--[exact command argv to execute as objective-satisfaction evidence]' '--details[additional structured execution details]' '--help[show this help]' '--id[contract verification item id used as evidence]' '--json[emit structured output as JSON]' '--path[target project directory (default: current directory)]' '--requirement[exact contract verification item requirement text]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
50
54
  reconcile-continuity) _arguments '--help[show this help]' '--json[emit structured output as JSON]' '--path[target project directory (default: current directory)]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
51
55
  record-check) _arguments '--command[recorded only as metadata; it is never executed]' '--details[additional structured check details]' '--evidence-kind[OBSERVED, INFERRED, NOT_VERIFIED, or BLOCKED]' '--execution-ref[ForgeLoop execution artifact reference]' '--exit-code[observed process exit code]' '--help[show this help]' '--id[stable check identifier]' '--json[emit structured output as JSON]' '--kind[check kind (default: command; use manual-review for manual evidence)]' '--path[target project directory (default: current directory)]' '--provenance[FORGELOOP_EXECUTED, ACTOR_REPORTED, or MANUAL_OBSERVATION]' '--requirement[completion requirement covered by the check]' '--result[observed result supplied by the actor]' '--status[passed, failed, blocked, or not-run]' '--task[task ID to operate on (when omitted, resolved from context or single active task)]' '--version[show the installed package version]' ;;
@@ -30,6 +30,7 @@ _forgeloop() {
30
30
  doctor) command="doctor" ;;
31
31
  efficiency) command="efficiency" ;;
32
32
  eval) command="eval" ;;
33
+ handoff-accept) command="handoff-accept" ;;
33
34
  handoff-create) command="handoff-create" ;;
34
35
  handoff-list) command="handoff-list" ;;
35
36
  handoff-show) command="handoff-show" ;;
@@ -48,6 +49,9 @@ _forgeloop() {
48
49
  profile-interview) command="profile-interview" ;;
49
50
  progress) command="progress" ;;
50
51
  protocol-info) command="protocol-info" ;;
52
+ quality-baseline) command="quality-baseline" ;;
53
+ quality-status) command="quality-status" ;;
54
+ quality-verify) command="quality-verify" ;;
51
55
  reconcile-closure) command="reconcile-closure" ;;
52
56
  reconcile-continuity) command="reconcile-continuity" ;;
53
57
  record-check) command="record-check" ;;
@@ -88,7 +92,7 @@ _forgeloop() {
88
92
  esac
89
93
  done
90
94
  if [[ -z "\${command}" && "\${cur}" != -* ]]; then
91
- COMPREPLY=( $(compgen -W 'action-authorize action-propose action-reconcile action-record action-show action-verify activate advance approval-request approval-resolve attestation-create attestation-status attestation-verify attestation-verify-range audit baseline bundle clear-continuity clear-state complete continuity doctor efficiency eval handoff-create handoff-list handoff-show history init inspect metrics migrate-protocol next policy policy-diff policy-discover policy-status preflight prepare-completion profile-interview progress protocol-info reconcile-closure reconcile-continuity record-check record-continuity record-decision-criterion record-diagnosis record-hypothesis-disposition record-intervention record-terminal-result reflect report responsibility-set responsibility-status route rule-verify run-action run-check status task-create task-list task-lock-status task-migrate task-recover task-repair-legacy-recovery task-resume task-scope task-show task-unlock trace update usage-record validate-protocol validate-receipt validate-state verify-scope workspace-bind workspace-status' -- "$cur") )
95
+ COMPREPLY=( $(compgen -W 'action-authorize action-propose action-reconcile action-record action-show action-verify activate advance approval-request approval-resolve attestation-create attestation-status attestation-verify attestation-verify-range audit baseline bundle clear-continuity clear-state complete continuity doctor efficiency eval handoff-accept handoff-create handoff-list handoff-show history init inspect metrics migrate-protocol next policy policy-diff policy-discover policy-status preflight prepare-completion profile-interview progress protocol-info quality-baseline quality-status quality-verify reconcile-closure reconcile-continuity record-check record-continuity record-decision-criterion record-diagnosis record-hypothesis-disposition record-intervention record-terminal-result reflect report responsibility-set responsibility-status route rule-verify run-action run-check status task-create task-list task-lock-status task-migrate task-recover task-repair-legacy-recovery task-resume task-scope task-show task-unlock trace update usage-record validate-protocol validate-receipt validate-state verify-scope workspace-bind workspace-status' -- "$cur") )
92
96
  return
93
97
  fi
94
98
  case "\${command}" in
@@ -116,6 +120,7 @@ _forgeloop() {
116
120
  doctor) COMPREPLY=( $(compgen -W '--adopt --fix --help --json --path --strict --version' -- "$cur") );;
117
121
  efficiency) COMPREPLY=( $(compgen -W '--baseline --help --json --path --task --version' -- "$cur") );;
118
122
  eval) COMPREPLY=( $(compgen -W '--help --json --path --scenario --task --version' -- "$cur") );;
123
+ handoff-accept) COMPREPLY=( $(compgen -W '--consumer-id --handoff --harness --help --json --path --task --version' -- "$cur") );;
119
124
  handoff-create) COMPREPLY=( $(compgen -W '--help --json --note --path --recipient --task --version' -- "$cur") );;
120
125
  handoff-list) COMPREPLY=( $(compgen -W '--help --json --path --task --version' -- "$cur") );;
121
126
  handoff-show) COMPREPLY=( $(compgen -W '--help --id --json --path --task --version' -- "$cur") );;
@@ -134,6 +139,9 @@ _forgeloop() {
134
139
  profile-interview) COMPREPLY=( $(compgen -W '--dry-run --help --json --path --version' -- "$cur") );;
135
140
  progress) COMPREPLY=( $(compgen -W '--help --json --path --task --version' -- "$cur") );;
136
141
  protocol-info) COMPREPLY=( $(compgen -W '--help --json --path --version' -- "$cur") );;
142
+ quality-baseline) COMPREPLY=( $(compgen -W '--help --json --path --replace --task --timeout-ms --version' -- "$cur") );;
143
+ quality-status) COMPREPLY=( $(compgen -W '--help --json --path --task --version' -- "$cur") );;
144
+ quality-verify) COMPREPLY=( $(compgen -W '--help --json --path --task --timeout-ms --version' -- "$cur") );;
137
145
  reconcile-closure) COMPREPLY=( $(compgen -W '-- --details --help --id --json --path --requirement --task --version' -- "$cur") );;
138
146
  reconcile-continuity) COMPREPLY=( $(compgen -W '--help --json --path --task --version' -- "$cur") );;
139
147
  record-check) COMPREPLY=( $(compgen -W '--command --details --evidence-kind --execution-ref --exit-code --help --id --json --kind --path --provenance --requirement --result --status --task --version' -- "$cur") );;
@@ -1,5 +1,5 @@
1
1
  # Generated by scripts/generate-shell-completions.mjs. Do not edit.
2
- complete -c forgeloop -f -n '__fish_use_subcommand' -a 'action-authorize action-propose action-reconcile action-record action-show action-verify activate advance approval-request approval-resolve attestation-create attestation-status attestation-verify attestation-verify-range audit baseline bundle clear-continuity clear-state complete continuity doctor efficiency eval handoff-create handoff-list handoff-show history init inspect metrics migrate-protocol next policy policy-diff policy-discover policy-status preflight prepare-completion profile-interview progress protocol-info reconcile-closure reconcile-continuity record-check record-continuity record-decision-criterion record-diagnosis record-hypothesis-disposition record-intervention record-terminal-result reflect report responsibility-set responsibility-status route rule-verify run-action run-check status task-create task-list task-lock-status task-migrate task-recover task-repair-legacy-recovery task-resume task-scope task-show task-unlock trace update usage-record validate-protocol validate-receipt validate-state verify-scope workspace-bind workspace-status'
2
+ complete -c forgeloop -f -n '__fish_use_subcommand' -a 'action-authorize action-propose action-reconcile action-record action-show action-verify activate advance approval-request approval-resolve attestation-create attestation-status attestation-verify attestation-verify-range audit baseline bundle clear-continuity clear-state complete continuity doctor efficiency eval handoff-accept handoff-create handoff-list handoff-show history init inspect metrics migrate-protocol next policy policy-diff policy-discover policy-status preflight prepare-completion profile-interview progress protocol-info quality-baseline quality-status quality-verify reconcile-closure reconcile-continuity record-check record-continuity record-decision-criterion record-diagnosis record-hypothesis-disposition record-intervention record-terminal-result reflect report responsibility-set responsibility-status route rule-verify run-action run-check status task-create task-list task-lock-status task-migrate task-recover task-repair-legacy-recovery task-resume task-scope task-show task-unlock trace update usage-record validate-protocol validate-receipt validate-state verify-scope workspace-bind workspace-status'
3
3
  complete -c forgeloop -f -n '__fish_seen_subcommand_from action-authorize' -l 'action' -d 'durable action ID'
4
4
  complete -c forgeloop -f -n '__fish_seen_subcommand_from action-authorize' -l 'approval' -d 'current fingerprint-bound approval'
5
5
  complete -c forgeloop -f -n '__fish_seen_subcommand_from action-authorize' -l 'help' -d 'show this help'
@@ -173,6 +173,14 @@ complete -c forgeloop -f -n '__fish_seen_subcommand_from eval' -l 'path' -d 'tar
173
173
  complete -c forgeloop -f -n '__fish_seen_subcommand_from eval' -l 'scenario' -d 'project-local trajectory scenario JSON'
174
174
  complete -c forgeloop -f -n '__fish_seen_subcommand_from eval' -l 'task' -d 'task ID to operate on (when omitted, resolved from context or single active task)'
175
175
  complete -c forgeloop -f -n '__fish_seen_subcommand_from eval' -l 'version' -d 'show the installed package version'
176
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-accept' -l 'consumer-id' -d 'consumer identifier accepting the handoff'
177
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-accept' -l 'handoff' -d 'handoff identifier'
178
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-accept' -l 'harness' -d 'optional harness accepting the handoff'
179
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-accept' -l 'help' -d 'show this help'
180
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-accept' -l 'json' -d 'emit acceptance result as JSON'
181
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-accept' -l 'path' -d 'target project directory (default: current directory)'
182
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-accept' -l 'task' -d 'task ID to operate on (when omitted, resolved from context or single active task)'
183
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-accept' -l 'version' -d 'show the installed package version'
176
184
  complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-create' -l 'help' -d 'show this help'
177
185
  complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-create' -l 'json' -d 'emit handoff as JSON'
178
186
  complete -c forgeloop -f -n '__fish_seen_subcommand_from handoff-create' -l 'note' -d 'non-authoritative handoff note'
@@ -279,6 +287,24 @@ complete -c forgeloop -f -n '__fish_seen_subcommand_from protocol-info' -l 'help
279
287
  complete -c forgeloop -f -n '__fish_seen_subcommand_from protocol-info' -l 'json' -d 'emit complete machine-readable protocol metadata'
280
288
  complete -c forgeloop -f -n '__fish_seen_subcommand_from protocol-info' -l 'path' -d 'target project directory (default: current directory)'
281
289
  complete -c forgeloop -f -n '__fish_seen_subcommand_from protocol-info' -l 'version' -d 'show the installed package version'
290
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-baseline' -l 'help' -d 'show this help'
291
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-baseline' -l 'json' -d 'emit baseline result as JSON'
292
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-baseline' -l 'path' -d 'target project directory (default: current directory)'
293
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-baseline' -l 'replace' -d 'replace a different baseline before EXECUTING'
294
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-baseline' -l 'task' -d 'task ID to operate on (when omitted, resolved from context or single active task)'
295
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-baseline' -l 'timeout-ms' -d 'bounded analyzer timeout in milliseconds'
296
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-baseline' -l 'version' -d 'show the installed package version'
297
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-status' -l 'help' -d 'show this help'
298
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-status' -l 'json' -d 'emit persisted structural-quality status as JSON'
299
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-status' -l 'path' -d 'target project directory (default: current directory)'
300
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-status' -l 'task' -d 'task ID to operate on (when omitted, resolved from context or single active task)'
301
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-status' -l 'version' -d 'show the installed package version'
302
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-verify' -l 'help' -d 'show this help'
303
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-verify' -l 'json' -d 'emit structural-quality verification as JSON'
304
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-verify' -l 'path' -d 'target project directory (default: current directory)'
305
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-verify' -l 'task' -d 'task ID to operate on (when omitted, resolved from context or single active task)'
306
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-verify' -l 'timeout-ms' -d 'bounded analyzer timeout in milliseconds'
307
+ complete -c forgeloop -f -n '__fish_seen_subcommand_from quality-verify' -l 'version' -d 'show the installed package version'
282
308
  complete -c forgeloop -f -n '__fish_seen_subcommand_from reconcile-closure' -l '' -d 'exact command argv to execute as objective-satisfaction evidence'
283
309
  complete -c forgeloop -f -n '__fish_seen_subcommand_from reconcile-closure' -l 'details' -d 'additional structured execution details'
284
310
  complete -c forgeloop -f -n '__fish_seen_subcommand_from reconcile-closure' -l 'help' -d 'show this help'
@@ -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.8.1
10
+ Package version: 1.10.0
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 |
@@ -90,6 +91,7 @@ Phases: RECEIVED, DISCOVERING, CONTRACT_READY, ROUTED, DESIGNING, PLANNED, EXECU
90
91
  | observabilityStability | n/a | yes |
91
92
  | reflection | 1 | yes |
92
93
  | responsibilityConstraints | 1 | yes |
94
+ | structuralQuality | 1 | yes |
93
95
  | structuredTrace | 1 | yes |
94
96
  | taskClaimRecovery | 1 | yes |
95
97
  | taskInspection | 1 | yes |
@@ -99,6 +101,21 @@ Phases: RECEIVED, DISCOVERING, CONTRACT_READY, ROUTED, DESIGNING, PLANNED, EXECU
99
101
  | verificationExecutionIsolation | 1 | yes |
100
102
  | workspaceBinding | 1 | yes |
101
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
+
102
119
  ## Public artifact registry
103
120
 
104
121
  | Key | Scope | Path | Schema | Trust role |
@@ -131,6 +148,7 @@ Phases: RECEIVED, DISCOVERING, CONTRACT_READY, ROUTED, DESIGNING, PLANNED, EXECU
131
148
  | session | SESSION | .forgeloop/sessions/<session-id>.json | activation | SESSION_MARKER |
132
149
  | sources | PROJECT | .forgeloop/sources.json | source-registry | SOURCE_ATTESTATION |
133
150
  | state | TASK | .forgeloop/task-state/<task-key>/work-state.json | work-state | CANONICAL_LIFECYCLE_STATE |
151
+ | structuralQuality | TASK | .forgeloop/task-state/<task-key>/structural-quality/baseline.json | structural-quality | STRUCTURAL_QUALITY_EVIDENCE |
134
152
  | usage | TASK | .forgeloop/task-state/<task-key>/usage.json | usage | INFORMATIONAL_USAGE_TELEMETRY |
135
153
  | verificationScope | TASK | .forgeloop/task-state/<task-key>/verification-scope.json | verification-scope | VERIFICATION_SCOPE_PLAN |
136
154
  | workspaceBinding | TASK | .forgeloop/task-state/<task-key>/workspace-binding.json | workspace-binding | WORKSPACE_IDENTITY_BINDING |
@@ -246,12 +264,21 @@ Phases: RECEIVED, DISCOVERING, CONTRACT_READY, ROUTED, DESIGNING, PLANNED, EXECU
246
264
  | responsibility-set | MUTATING | Creates immutable, mechanically verifiable constraints for a task pass. |
247
265
  | responsibility-status | READ_ONLY | Validates active responsibility constraints against current paths, inputs, and checks. |
248
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
+
249
273
  ### verification
250
274
 
251
275
  | Command | Mutation | Purpose |
252
276
  | --- | --- | --- |
253
277
  | audit | READ_ONLY | Performs read-only evaluation of verification receipt coverage and gate satisfaction. |
254
278
  | prepare-completion | MUTATING | Initializes execution-receipt.json with empty requirement evidence slots for the active cycle. |
279
+ | quality-baseline | EXTERNAL_EXECUTION | Captures an immutable provider-neutral structural-quality baseline through the trusted analyzer adapter. |
280
+ | quality-status | READ_ONLY | Projects persisted structural-quality baseline and evaluation status without invoking a provider. |
281
+ | quality-verify | EXTERNAL_EXECUTION | Captures one bounded structural-quality evaluation and projects it into canonical verification evidence. |
255
282
  | record-check | MUTATING | Records structured verification evidence (command, manual review, or test output) against a requirement. |
256
283
  | record-terminal-result | MUTATING | Records external terminal result evidence (PUBLICATION or PRODUCTION_READINESS) into receipt. |
257
284
  | report | READ_ONLY | Emits a human-readable or structured JSON summary report of protocol state. |
@@ -296,8 +323,12 @@ Phases: RECEIVED, DISCOVERING, CONTRACT_READY, ROUTED, DESIGNING, PLANNED, EXECU
296
323
  | E_ATTESTATION_TARGET_REF_INVALID | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
297
324
  | E_ATTESTATION_UNSIGNED | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
298
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. |
299
329
  | E_HANDOFF_INVALID | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
300
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. |
301
332
  | E_HANDOFF_STATE_UNAVAILABLE | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
302
333
  | E_HANDOFF_TAMPERED | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |
303
334
  | E_RESPONSIBILITY_FROZEN_INPUT_DRIFT | A ForgeLoop boundary, artifact, provider, or attestation validation condition was not satisfied. |