@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/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.8.x` |
138
+ | ForgeLoop core package | `>=1.5.0 <2` dependency range; current release `1.10.0` |
123
139
  | ForgeLoop protocol | `1` |
124
140
  | Integration API | `1` |
125
141
  | MCP package | `0.1.x` initial package |
package/docs/RECIPES.md CHANGED
@@ -28,6 +28,7 @@ Concise, copy-paste friendly recipes for common ForgeLoop tasks.
28
28
  20. [Configure Trusted Narrow Verification](#recipe-20--configure-trusted-narrow-verification)
29
29
  21. [Generate and Verify Code Attestation](#recipe-21--generate-and-verify-code-attestation)
30
30
  22. [Verify a Revision Range](#recipe-22--verify-a-revision-range)
31
+ 23. [Run Structural Quality Feedback](#recipe-23--run-structural-quality-feedback)
31
32
 
32
33
  ---
33
34
 
@@ -456,6 +457,86 @@ operational context only: a handoff is not delegation, authority, independent
456
457
  review evidence, or completion evidence. Use `continuity.json` for mutable
457
458
  resume notes and canonical execution artifacts for proof.
458
459
 
460
+ ### Recipe 18A — Accept an Immutable Handoff Exactly Once
461
+
462
+ After inspecting the snapshot and confirming that the receiving harness is
463
+ actually consuming it, record the operational receipt:
464
+
465
+ ```bash
466
+ forgeloop handoff-accept --task task-001 \
467
+ --handoff <handoffId> \
468
+ --consumer-id agent-session-42 \
469
+ --harness codex \
470
+ --json
471
+ ```
472
+
473
+ Retrying with the same consumer is idempotent. A different consumer receives
474
+ `E_HANDOFF_ALREADY_ACCEPTED`. Acceptance is operational only: it does not
475
+ transfer claims, create evidence, approve delegation, or grant authority.
476
+
477
+ ### Recipe 18B — Diagnose an Inconsistent Handoff
478
+
479
+ Inspect the derived projection and ledger before attempting any repair:
480
+
481
+ ```bash
482
+ forgeloop handoff-list --task task-001 --json
483
+ forgeloop handoff-show --task task-001 --id <handoffId> --json
484
+ forgeloop validate-protocol --task task-001 --json
485
+ ```
486
+
487
+ `INCONSISTENT` is fail-closed. Check the returned reason codes for a stale
488
+ contract/route/repository snapshot, an unbound legacy handoff, a digest mismatch,
489
+ or invalid acceptance history. Do not edit the immutable handoff or
490
+ `events.ndjson`; create a fresh handoff after the canonical issue is resolved.
491
+
492
+ ### Recipe 18C — Use an Advisory Provider from a Host Integration
493
+
494
+ Register a provider in runtime context and invoke recall explicitly:
495
+
496
+ ```javascript
497
+ import {
498
+ createForgeLoopContext,
499
+ recallAdvisoryContext,
500
+ } from "@cassiomc1/forgeloop/integration";
501
+
502
+ const runtimeContext = createForgeLoopContext({
503
+ advisoryContextProviders: {
504
+ "host-context": {
505
+ id: "host-context",
506
+ recall: async ({ query }) => ({ items: await hostLookup(query) }),
507
+ },
508
+ },
509
+ });
510
+
511
+ const result = await recallAdvisoryContext({
512
+ target: ".",
513
+ taskId: "task-001",
514
+ providerName: "host-context",
515
+ query: "current authentication constraints",
516
+ runtimeContext,
517
+ });
518
+ ```
519
+
520
+ Recall is lazy, bounded, opt-in, non-persisted, non-evidence, and
521
+ non-executable. Validate every proposed change against canonical state and
522
+ verification instead of executing provider text.
523
+
524
+ ### Recipe 18D — Resume with Continuity Lint Warnings
525
+
526
+ Treat lint findings as inspection hints only:
527
+
528
+ ```bash
529
+ forgeloop continuity --task task-001 --json
530
+ forgeloop reconcile-continuity --task task-001 --json
531
+ forgeloop next --task task-001 --json
532
+ ```
533
+
534
+ Findings such as `CONTINUITY_REMAINING_ALREADY_COMPLETED`,
535
+ `CONTINUITY_FOCUS_ALREADY_COMPLETED`, `CONTINUITY_ITEM_ROLE_CONFLICT`,
536
+ `CONTINUITY_INSPECT_PATH_MISSING`, and `CONTINUITY_EMPTY_HINT_SET` are
537
+ non-authoritative and non-evidence. Refresh the note with
538
+ `record-continuity` when useful, then follow the canonical next action.
539
+
459
540
  ---
460
541
 
461
542
  ### Recipe 19 — Apply a Responsibility Contract
@@ -551,6 +632,36 @@ coverage gap or conflicting task digest is invalid; provider or invocation
551
632
  failure is an error. This post-completion range result is distinct from the
552
633
  pre-completion verification scope used by one checker.
553
634
 
635
+ ---
636
+
637
+ ### Recipe 23 — Run Structural Quality Feedback
638
+
639
+ Enable `structuralQuality` in `.forgeloop/config.json` with `observe` for
640
+ non-blocking evidence or `gate` for a completion requirement. The configured
641
+ provider is selected by name; executable paths and shell fragments are not
642
+ accepted.
643
+
644
+ ```bash
645
+ # Capture after planning and before execution.
646
+ forgeloop quality-baseline --task task-001 --json
647
+
648
+ # Enter the normal lifecycle and evaluate the current verification cycle.
649
+ forgeloop advance --task task-001 --to EXECUTING --json
650
+ forgeloop advance --task task-001 --to VERIFYING --json
651
+ forgeloop quality-verify --task task-001 --json
652
+
653
+ # Inspect evidence without starting the provider.
654
+ forgeloop quality-status --task task-001 --json
655
+ ```
656
+
657
+ In `gate` mode, a failed comparison follows the existing
658
+ `VERIFYING -> DIAGNOSING -> CORRECTING -> VERIFYING` loop. Record a diagnosis
659
+ from the evaluation artifact before correcting code. In `observe` mode,
660
+ unavailable or incomparable evidence remains visible as `NOT_OBSERVED` and
661
+ does not block completion by itself. See
662
+ [`STRUCTURAL_QUALITY.md`](./STRUCTURAL_QUALITY.md) for policy, provider,
663
+ Sentrux, bundle, and error-code details.
664
+
554
665
  ## Run ForgeLoop through MCP (safe mode)
555
666
 
556
667
  Start the local MCP adapter and inspect what it exposes:
@@ -16,6 +16,20 @@ preparation and verification checklist; it does not authorize publication.
16
16
 
17
17
  ## Protocol and attestation
18
18
 
19
+ - [ ] `protocol-info` and the Integration API capability contracts agree.
20
+ - [ ] `canonicalHandoffs` v2 is advertised consistently.
21
+ - [ ] `advisoryContextProviders` v1 is advertised consistently.
22
+ - [ ] Advisory context remains Integration-API-only.
23
+ - [ ] `next`, `status`, and `task/context` invoke zero advisory providers.
24
+ - [ ] Advisory request budgets are normalized before provider invocation.
25
+ - [ ] Advisory results are never persisted by ForgeLoop.
26
+ - [ ] Same-consumer handoff acceptance is idempotent.
27
+ - [ ] Different-consumer handoff acceptance fails closed.
28
+ - [ ] Concurrent acceptance creates one `HANDOFF_ACCEPTED` event.
29
+ - [ ] Clean HEAD/branch drift rejects handoff acceptance.
30
+ - [ ] Stale contract/route identity rejects handoff creation or acceptance.
31
+ - [ ] An invalid event ledger projects `INCONSISTENT`.
32
+ - [ ] Continuity lint remains non-authoritative and non-evidence.
19
33
  - [ ] `npm run dependency:policy` passes without adding runtime dependencies.
20
34
  - [ ] `npm run lint` passes.
21
35
  - [ ] `npm test` passes.
@@ -0,0 +1,350 @@
1
+ # Structural Quality Feedback Loop
2
+
3
+ ForgeLoop can optionally compare the structure of a project before and after a
4
+ task. The provider is an external sensor; ForgeLoop owns the policy, evidence,
5
+ lifecycle, and completion decision.
6
+
7
+ ## 1. Purpose and boundaries
8
+
9
+ Structural quality answers whether the measured dependency structure changed
10
+ within the configured budget. It does not prove behavioral correctness,
11
+ security, performance, accessibility, maintainability in general, or product
12
+ quality. Tests, lint, security checks, performance checks, accessibility checks,
13
+ review, and publication remain separate evidence dimensions.
14
+
15
+ ForgeLoop persists only normalized, bounded, secret-free observations. The
16
+ resolved project path is execution context and is not written into portable
17
+ quality artifacts.
18
+
19
+ ## 2. Why structural quality is not a guide
20
+
21
+ Engineering guides tell an agent how to work. A structural-quality provider
22
+ measures the result of that work. The result is therefore a typed verification
23
+ artifact and a canonical check, not an `ENG/` guide or a replacement for one.
24
+
25
+ ## 3. The five metrics
26
+
27
+ Every provider observation contains integer scores from `0` through `10000`, a
28
+ finite raw value, and a canonical bottleneck. The current Sentrux adapter maps
29
+ these five root causes:
30
+
31
+ | Root cause | Meaning in the feedback loop |
32
+ | --- | --- |
33
+ | `modularity` | How cleanly responsibilities and communities are separated. |
34
+ | `acyclicity` | Whether dependency relationships remain free of prohibited cycles. |
35
+ | `depth` | The measured dependency-level depth of the project. |
36
+ | `equality` | How evenly structure is distributed across the measured modules. |
37
+ | `redundancy` | The amount of repeated or structurally redundant information. |
38
+
39
+ The aggregate `qualitySignal` is provider-supplied and normalized by ForgeLoop.
40
+ ForgeLoop does not reimplement graph analysis or claim that a high signal is a
41
+ universal software-quality score.
42
+
43
+ ## 4. Delta-first policy
44
+
45
+ Gate decisions compare the current observation with the immutable baseline.
46
+ By default, the aggregate budget is zero (`maxRegressionPoints: 0`), new cycles
47
+ are forbidden (`forbidNewCycles: true`), and individual dimension budgets are
48
+ unenforced (`null`), allowing flexible dimension trade-offs as long as aggregate
49
+ signal does not regress. A configured dimension budget is intentional policy and
50
+ is bound to the baseline by a policy fingerprint.
51
+
52
+ The comparison also checks provider identity, measurement model (`measurementModel`),
53
+ compatibility key (`compatibilityKey`), task/contract/route bindings, source
54
+ material fingerprints, scan scope, provider config fingerprints, and optional
55
+ cycle/minimum conditions. Any mismatch is incomparable; it is never treated as a pass.
56
+ An explicit per-dimension failure fails the gate even when the aggregate signal improves.
57
+ Architecture-rule provenance is recorded separately and does not change Structural
58
+ Quality comparability when the measured source and provider scope are unchanged.
59
+
60
+ ## 5. Modes
61
+
62
+ `structuralQuality` is absent by default for backward compatibility. When it is
63
+ present, the mode is exactly one of:
64
+
65
+ | Mode | Baseline and verification | Completion effect |
66
+ | --- | --- | --- |
67
+ | `off` | No provider lookup or quality artifacts. | None. |
68
+ | `observe` | Records available comparisons and visible limitations. | Never blocks completion by itself. |
69
+ | `gate` | Requires a bound baseline before execution and a comparable current-cycle pass before completion. | Missing, stale, blocked, incomparable, or failed evidence blocks the quality requirement. |
70
+
71
+ An unavailable provider is `NOT_OBSERVED` in `observe` mode and `BLOCKED` in
72
+ `gate` mode. Neither mode turns unavailable evidence into `PASS`.
73
+
74
+ ## 6. Configuration examples
75
+
76
+ ForgeLoop configuration lives in `.forgeloop/config.json`.
77
+
78
+ Recommended observation mode:
79
+
80
+ ```json
81
+ {
82
+ "schemaVersion": 1,
83
+ "protocolVersion": 1,
84
+ "complianceMode": "standard",
85
+ "structuralQuality": {
86
+ "mode": "observe",
87
+ "provider": "sentrux"
88
+ }
89
+ }
90
+ ```
91
+
92
+ Strict gate mode with an intentional 50-point modularity budget:
93
+
94
+ ```json
95
+ {
96
+ "schemaVersion": 1,
97
+ "protocolVersion": 1,
98
+ "complianceMode": "strict",
99
+ "structuralQuality": {
100
+ "mode": "gate",
101
+ "provider": "sentrux",
102
+ "maxRegressionPoints": 0,
103
+ "dimensionBudgets": {
104
+ "modularity": 50,
105
+ "acyclicity": 0,
106
+ "depth": null,
107
+ "equality": null,
108
+ "redundancy": null
109
+ },
110
+ "forbidNewCycles": true
111
+ }
112
+ }
113
+ ```
114
+
115
+ The provider name selects a registered provider only. Project configuration
116
+ cannot select an executable, shell, arbitrary arguments, score, baseline, or
117
+ provider-native command.
118
+
119
+ ## 7. Baseline and verify commands
120
+
121
+ Capture the baseline after planning and before entering execution:
122
+
123
+ ```bash
124
+ forgeloop quality-baseline --task <task-id> --json
125
+ ```
126
+
127
+ An intentional replacement is allowed only before `EXECUTING` and retains
128
+ supersession evidence:
129
+
130
+ ```bash
131
+ forgeloop quality-baseline --task <task-id> --replace --json
132
+ ```
133
+
134
+ In `VERIFYING`, evaluate the current cycle:
135
+
136
+ ```bash
137
+ forgeloop quality-verify --task <task-id> --json
138
+ ```
139
+
140
+ Inspect persisted evidence without starting a provider:
141
+
142
+ ```bash
143
+ forgeloop quality-status --task <task-id> --json
144
+ ```
145
+
146
+ The JSON envelopes preserve stable structural-quality error codes and never
147
+ include raw MCP streams.
148
+
149
+ ## 8. Failure-to-diagnosis workflow
150
+
151
+ When a gate evaluation fails, ForgeLoop records a failed
152
+ `structural-quality` check with the evaluation artifact, bottleneck, all
153
+ root-cause deltas, failed policy conditions, and stable reason codes. It does
154
+ not invent a diagnosis. Follow the normal lifecycle:
155
+
156
+ ```text
157
+ VERIFYING
158
+ -> DIAGNOSING record an evidence-backed hypothesis
159
+ -> CORRECTING make the scoped correction
160
+ -> VERIFYING evaluate the new verification cycle
161
+ -> REVIEWING only after current-cycle evidence and other checks pass
162
+ ```
163
+
164
+ Use `forgeloop next --task <task-id> --json` at each boundary. A repeated
165
+ hypothesis without new information remains subject to ForgeLoop's existing
166
+ diagnosis and stall rules.
167
+
168
+ ## 9. Optional bounded optimization
169
+
170
+ Optimization is advisory and disabled by default. If enabled with
171
+ `optimization.mode: "bounded"`, ForgeLoop may recommend at most two extra
172
+ evaluations in the current verification cycle. A passing baseline comparison
173
+ already satisfies completion; extra evaluations are never required.
174
+
175
+ The recommendation is suppressed when task scope is unavailable, stale, or
176
+ outside effective claims. A gain below `minGainPoints` converges the advisory
177
+ loop, and no optimization seeks a perfect `10000` score or widens the task.
178
+
179
+ ## 10. Provider contract and measurement model
180
+
181
+ The public provider boundary is vendor-neutral:
182
+
183
+ ```ts
184
+ type StructuralQualityProviderInput = {
185
+ projectPath: string;
186
+ taskId: string;
187
+ timeoutMs: number;
188
+ maxOutputBytes: number;
189
+ };
190
+
191
+ type StructuralQualityProvider = {
192
+ id: string;
193
+ detect?(input: StructuralQualityProviderInput): Promise<Detection>;
194
+ scan?(input: StructuralQualityProviderInput): Promise<SnapshotResult>;
195
+ observe?(input: StructuralQualityProviderInput): Promise<SnapshotResult>;
196
+ scopeBinding?(input: { projectPath: string }): Promise<ScopeBinding>;
197
+ };
198
+ ```
199
+
200
+ Providers declare `measurementModel` (such as `structural-root-causes-v1`) and
201
+ an optional `compatibilityKey` (such as `sentrux-structural-root-causes-v1`).
202
+ When baseline and evaluation share a compatibility key, non-breaking version
203
+ differences between provider releases compare cleanly. Sentrux compatibility
204
+ is explicit: the built-in adapter accepts only verified versions `0.5.5`,
205
+ `0.5.6`, and `0.5.7`; future or malformed versions fail closed until
206
+ explicitly verified.
207
+
208
+ Runtime hosts may inject a provider through `createForgeLoopContext`. Provider
209
+ IDs are lower-case stable names matching `^[a-z][a-z0-9-]{0,63}$`; the built-in
210
+ `sentrux` name is reserved. Provider output is untrusted until every field is
211
+ normalized, bounded, schema-validated, and semantically bound to the task.
212
+
213
+ ## 11. Sentrux MCP adapter and tool arguments
214
+
215
+ Sentrux is not a ForgeLoop npm dependency. ForgeLoop never installs, upgrades,
216
+ or selects an arbitrary Sentrux executable. The built-in adapter invokes the
217
+ trusted command name `sentrux --mcp` through a shell-free local MCP process, requires
218
+ verified versions `0.5.5`, `0.5.6`, and `0.5.7`, and strictly conforms to Sentrux tool argument schemas:
219
+
220
+ - `scan`: `arguments: { path: "<project-path>" }`
221
+ - `health`: `arguments: {}`
222
+
223
+ Sentrux-specific configuration (such as `.sentrux/rules.toml`) is owned
224
+ exclusively by the Sentrux provider adapter via `scopeBinding()`. The adapter
225
+ records its SHA-256 as `scope.architectureRulesFingerprint` for provenance, but
226
+ the rules file is a separate Architecture Rules Sensor: changing it does not
227
+ make unchanged Structural Quality measurements incomparable. Generic provider
228
+ configuration remains a Structural Quality scope input and still invalidates
229
+ incompatible observations. The core resolver never scans for a rules file and
230
+ custom providers do not inherit this binding unless they explicitly expose their
231
+ own `scopeBinding()`.
232
+
233
+ If Sentrux is absent, preserve the resulting `NOT_OBSERVED` or `BLOCKED` state
234
+ and follow the configured mode. Install or upgrade Sentrux only through the
235
+ user's normal, separately authorized process.
236
+
237
+ The repository includes a real-provider interoperability scenario covering the
238
+ public baseline/verify path and an intentional `A -> B -> C -> A` cycle:
239
+
240
+ ```bash
241
+ node --test tests/real-sentrux-structural-quality.test.js
242
+ ```
243
+
244
+ The scenario runs when the user-managed `sentrux` executable reports a verified
245
+ version; environments without that external executable leave the scenario
246
+ unobserved rather than substituting a fake provider.
247
+
248
+ ## 12. Sentrux Free versus optional diagnostics
249
+
250
+ The five scores, bottleneck, and the aggregate comparison are sufficient for a
251
+ structural-quality pass or fail. File-level diagnostics may be unavailable in
252
+ Sentrux Free. A missing diagnostics payload is therefore valid and remains
253
+ `null`; it does not weaken the score comparison and does not become a fake
254
+ diagnostic.
255
+
256
+ ## 13. Freshness and optional observe actions
257
+
258
+ Baseline and observed `PASS`/`FAIL` artifacts must bind a stable source
259
+ fingerprint. Unreadable files, unsafe symlinks, source drift during a scan,
260
+ changed provider scope, and stale task bindings fail closed. `quality-status`,
261
+ `next`, recovery, provenance, and completion reuse the same freshness
262
+ validator and never promote a stale pass.
263
+
264
+ In `observe` mode, `next` may expose baseline or verification as optional
265
+ actions. These actions are advisory and do not spawn a provider from a
266
+ read-only status or next-action query.
267
+
268
+ ## 14. Sentrux analytics are user choices
269
+
270
+ ForgeLoop does not change Sentrux's global analytics preference. If the
271
+ installed Sentrux version provides these commands, the user may inspect or
272
+ disable analytics independently:
273
+
274
+ ```bash
275
+ sentrux analytics status
276
+ sentrux analytics off
277
+ ```
278
+
279
+ Those commands are outside ForgeLoop evidence and should be run only with the
280
+ user's own authorization.
281
+
282
+ ## 15. CI example
283
+
284
+ CI can run the same project-local commands after initializing the task and
285
+ configuring the provider on the runner:
286
+
287
+ ```yaml
288
+ steps:
289
+ - run: forgeloop preflight --task $FORGELOOP_TASK --json
290
+ - run: forgeloop quality-baseline --task $FORGELOOP_TASK --json
291
+ - run: forgeloop advance --task $FORGELOOP_TASK --to EXECUTING --json
292
+ - run: forgeloop advance --task $FORGELOOP_TASK --to VERIFYING --json
293
+ - run: forgeloop quality-verify --task $FORGELOOP_TASK --json
294
+ ```
295
+
296
+ Provider installation, runner identity, and remote publication are separate
297
+ CI evidence. A green local or CI quality command does not imply a merge,
298
+ publication, or deployment.
299
+
300
+ ## 16. Artifacts, locking, and projection reconciliation
301
+
302
+ Quality artifacts are task-owned and have no mutable `latest.json`:
303
+
304
+ ```text
305
+ .forgeloop/task-state/<taskKey>/structural-quality/
306
+ baseline.json
307
+ evaluations/
308
+ cycle-<cycle>-attempt-<attempt>.json
309
+ ```
310
+
311
+ The baseline is immutable after `EXECUTING`. External provider scans execute
312
+ outside the task mutation lock to prevent starvation of concurrent operations.
313
+ Pre-scan and post-scan source material fingerprints ensure observations are
314
+ stable against mid-scan source drift (`E_STRUCTURAL_QUALITY_SOURCE_DRIFT`).
315
+ Provider-owned `.sentrux` configuration is excluded from source material and
316
+ is handled only by the Sentrux scope binding. Source symlinks are rejected by
317
+ the fail-closed fingerprint policy. Rules provenance is retained in the scope,
318
+ but is not folded into the Structural Quality comparison fingerprint.
319
+ If an evaluation artifact was committed but check projection was interrupted,
320
+ subsequent verification retries automatically reconcile and repair the canonical
321
+ receipt check without rescanning or incrementing attempt counts.
322
+
323
+ Portable bundles include the baseline and evaluations required for audit.
324
+ Bundle readers validate typed artifacts and fingerprints without rescanning
325
+ the project or requiring Sentrux.
326
+
327
+ ## 17. Error-code troubleshooting table
328
+
329
+ | Code | Meaning | First safe action |
330
+ | --- | --- | --- |
331
+ | `E_STRUCTURAL_QUALITY_CONFIGURATION_INVALID` | The structural-quality configuration is malformed or outside policy limits. | Correct `.forgeloop/config.json`, then rerun `preflight`. |
332
+ | `E_STRUCTURAL_QUALITY_PROVIDER_INVALID` | A provider contract or normalized observation is invalid. | Inspect provider integration and rerun with the same task; do not promote the observation. |
333
+ | `E_STRUCTURAL_QUALITY_PROVIDER_UNAVAILABLE` | The configured provider cannot be detected. | In observe mode continue with the limitation; in gate mode make the user-managed provider available. |
334
+ | `E_STRUCTURAL_QUALITY_PROVIDER_VERSION_UNSUPPORTED` | The provider is older than the supported contract. | Use a user-authorized supported provider version. |
335
+ | `E_STRUCTURAL_QUALITY_PROVIDER_PROTOCOL_INVALID` | MCP initialization, tool discovery, or response protocol is invalid. | Inspect the provider installation and keep the evidence blocked. |
336
+ | `E_STRUCTURAL_QUALITY_PROVIDER_TOOL_CONTRACT_INVALID` | The provider tool schemas do not expose required argument definitions. | Ensure provider exposes valid `scan` and `health` MCP tool argument schemas. |
337
+ | `E_STRUCTURAL_QUALITY_SCAN_FAILED` | The provider scan failed. | Diagnose the provider failure; never treat it as a pass. |
338
+ | `E_STRUCTURAL_QUALITY_TIMEOUT` | The bounded provider deadline expired. | Inspect provider health and rerun only after the cause is understood. |
339
+ | `E_STRUCTURAL_QUALITY_OUTPUT_LIMIT` | Combined provider output exceeded the safety limit. | Reduce provider verbosity or repair the provider; do not persist partial output. |
340
+ | `E_STRUCTURAL_QUALITY_BASELINE_MISSING` | A gate task has no valid baseline. | Capture it in `PLANNED` after a valid preflight checkpoint. |
341
+ | `E_STRUCTURAL_QUALITY_BASELINE_EXISTS` | A different baseline already exists. | Keep the immutable baseline, or use authorized `--replace` before execution. |
342
+ | `E_STRUCTURAL_QUALITY_BASELINE_PHASE_INVALID` | Baseline replacement was attempted after execution began. | Repair against the existing baseline in a new verification cycle. |
343
+ | `E_STRUCTURAL_QUALITY_BASELINE_BINDING_MISMATCH` | Baseline bindings no longer match the task inputs. | Inspect policy, route, provider scope, and source drift; do not bypass the binding. |
344
+ | `E_STRUCTURAL_QUALITY_EVALUATION_INCOMPARABLE` | Current and baseline observations cannot be compared. | Resolve provider/version/policy/provider-scope drift and verify again; architecture-rule changes alone are informational. |
345
+ | `E_STRUCTURAL_QUALITY_MEASUREMENT_MODEL_MISMATCH` | Measurement models differ between baseline and evaluation. | Ensure baseline and evaluation share a compatible measurement model. |
346
+ | `E_STRUCTURAL_QUALITY_EVIDENCE_STALE` | A quality check is from an old cycle or points to stale evidence. | Run the current-cycle verification and record its canonical check. |
347
+ | `E_STRUCTURAL_QUALITY_SOURCE_DRIFT` | Source material was mutated during provider observation. | Ensure worktree remains stable during quality scans and rerun verification. |
348
+ | `E_STRUCTURAL_QUALITY_OBSERVATION_EPOCH_STALE` | Task state epoch changed during observation. | Re-run quality verification under the active task epoch. |
349
+ | `E_STRUCTURAL_QUALITY_PROJECTION_INCOMPLETE` | Check projection was incomplete. | Re-run quality verification to reconcile the canonical check from the evaluation. |
350
+ | `E_STRUCTURAL_QUALITY_REGRESSION` | The configured aggregate, dimension, cycle, or minimum policy failed. | Record a diagnosis from the evaluation evidence and correct the scoped code. |