@cassiomc1/forgeloop 0.1.12 → 0.1.13
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.
- package/.cursor/rules/project-loop.mdc +1 -1
- package/.github/copilot-instructions.md +1 -1
- package/AGENTS.md +1 -1
- package/CLAUDE.md +1 -1
- package/LOOP_ENGINEERING.md +40 -0
- package/LOOP_SYSTEM_DESIGN.md +9 -7
- package/PROTOCOL_INTEGRATION.md +28 -0
- package/README.md +32 -39
- package/THREAT_MODEL.md +2 -0
- package/package.json +1 -1
- package/src/commands/validate-protocol.js +11 -8
- package/src/core/conformance.js +47 -5
- package/src/core/native-adapters.js +4 -0
- package/src/core/verification-capability.js +47 -0
|
@@ -16,7 +16,7 @@ Do not treat ForgeLoop as vendor-specific, optional, or to follow only "in spiri
|
|
|
16
16
|
4. Respect higher-level and local instructions and the latest request.
|
|
17
17
|
5. Make the minimum change, run specific checks, and run proportional regression checks.
|
|
18
18
|
6. Diagnose failures before fixing them; do not repeat attempts without new evidence.
|
|
19
|
-
7. Request authority for unrelated actions, installations, and publications. For missing Qwen-MM-Plugins, follow `LOOP_ENGINEERING.md`.
|
|
19
|
+
7. Request authority for unrelated actions, installations, and publications. Do not install a missing verification tool merely to satisfy a check. For missing Qwen-MM-Plugins, follow `LOOP_ENGINEERING.md`.
|
|
20
20
|
8. After implementation begins, do not return a final result in `EXECUTING`: advance through `VERIFYING` → structured evidence → `REVIEWING` → execution receipt → validator-backed `COMPLETE`. If closure cannot be reached, report `BLOCKED` or `PARTIALLY VERIFIED`.
|
|
21
21
|
|
|
22
22
|
After implementation work for the current task is complete, run `forgeloop next` before returning a final result. Follow the returned lifecycle action until ForgeLoop reaches a terminal state or an explicit blocker.
|
|
@@ -13,7 +13,7 @@ Use these instructions across the repository while preserving local rules.
|
|
|
13
13
|
- Respect the latest request, scope, and higher-level instructions.
|
|
14
14
|
- Make the smallest coherent change; validate with specific and regression checks.
|
|
15
15
|
- Diagnose causes before fixing failures; do not make unverified attempts.
|
|
16
|
-
- Do not install software, publish, delete, or alter external state without authority. For missing Qwen-MM-Plugins, follow `LOOP_ENGINEERING.md`.
|
|
16
|
+
- Do not install software, publish, delete, or alter external state without authority. Do not install a missing verification tool merely to satisfy a check. For missing Qwen-MM-Plugins, follow `LOOP_ENGINEERING.md`.
|
|
17
17
|
- After implementation begins, do not return a final result in `EXECUTING`: advance through `VERIFYING` → structured evidence → `REVIEWING` → execution receipt → validator-backed `COMPLETE`. If closure cannot be reached, report `BLOCKED` or `PARTIALLY VERIFIED`.
|
|
18
18
|
|
|
19
19
|
After implementation work for the current task is complete, run `forgeloop next` before returning a final result. Follow the returned lifecycle action until ForgeLoop reaches a terminal state or an explicit blocker.
|
package/AGENTS.md
CHANGED
|
@@ -11,7 +11,7 @@ Do not treat ForgeLoop as vendor-specific, optional, or to follow only "in spiri
|
|
|
11
11
|
1. Use [`GUIDE_ROUTER.md`](./GUIDE_ROUTER.md) to select relevant guides and report activated guide IDs.
|
|
12
12
|
1. Make the smallest coherent change, run specific checks, and proportional regression checks.
|
|
13
13
|
1. Diagnose failures before fixing; do not repeat attempts without new evidence.
|
|
14
|
-
1. Do not install software, publish, delete, or migrate data without authority. For missing Qwen-MM-Plugins, follow `LOOP_ENGINEERING.md`.
|
|
14
|
+
1. Do not install software, publish, delete, or migrate data without authority. Do not install a missing verification tool merely to satisfy a check. For missing Qwen-MM-Plugins, follow `LOOP_ENGINEERING.md`.
|
|
15
15
|
1. Before implementation, create/validate `.forgeloop/current-contract.json`, persist routing, satisfy gates, and require `forgeloop preflight` to return `READY`.
|
|
16
16
|
1. Before claiming `COMPLETE`, require `forgeloop complete` to return `VALID`; otherwise report completion as not protocol-verified.
|
|
17
17
|
1. After implementation begins, do not return a final result in `EXECUTING`: advance through `VERIFYING` → structured evidence → `REVIEWING` → execution receipt → validator-backed `COMPLETE`. If closure cannot be reached, report `BLOCKED` or `PARTIALLY VERIFIED`.
|
package/CLAUDE.md
CHANGED
|
@@ -13,7 +13,7 @@ When working in this repository:
|
|
|
13
13
|
1. Consult [`GUIDE_ROUTER.md`](./GUIDE_ROUTER.md), select relevant guides, and announce their IDs.
|
|
14
14
|
1. Make small changes, run specific checks, and run proportional regression checks.
|
|
15
15
|
1. Investigate root causes before fixing failures; do not make unverified attempts.
|
|
16
|
-
1. Request authority for unrelated installations, publications, deletions, or migrations. For missing Qwen-MM-Plugins, follow `LOOP_ENGINEERING.md`.
|
|
16
|
+
1. Request authority for unrelated installations, publications, deletions, or migrations. Do not install a missing verification tool merely to satisfy a check. For missing Qwen-MM-Plugins, follow `LOOP_ENGINEERING.md`.
|
|
17
17
|
1. After implementation begins, do not return a final result in `EXECUTING`: advance through `VERIFYING` → structured evidence → `REVIEWING` → execution receipt → validator-backed `COMPLETE`. If closure cannot be reached, report `BLOCKED` or `PARTIALLY VERIFIED`.
|
|
18
18
|
1. After implementation work for the current task is complete, run `forgeloop next` before returning a final result. Follow the returned lifecycle action until ForgeLoop reaches a terminal state or an explicit blocker.
|
|
19
19
|
1. Report current evidence, limitations, and publication state without claiming checks that were not run.
|
package/LOOP_ENGINEERING.md
CHANGED
|
@@ -68,6 +68,46 @@ If the required CLI/API capability cannot be resolved:
|
|
|
68
68
|
Report the corresponding ForgeLoop dimension as `NOT_VERIFIED` with
|
|
69
69
|
`E_FORGELOOP_CLI_UNAVAILABLE`.
|
|
70
70
|
|
|
71
|
+
### Missing verification tool policy
|
|
72
|
+
|
|
73
|
+
A missing verification tool does not grant authority to install it.
|
|
74
|
+
|
|
75
|
+
When a verification command or checker is unavailable:
|
|
76
|
+
|
|
77
|
+
1. Try only already-installed or explicitly non-installing resolution paths.
|
|
78
|
+
2. Prefer an already available equivalent when it can verify the same requirement.
|
|
79
|
+
3. If no suitable local capability exists, request explicit installation authority
|
|
80
|
+
only when the missing verification is genuinely required.
|
|
81
|
+
4. If authority is unavailable or the check is non-critical, record the affected
|
|
82
|
+
verification dimension as `NOT_VERIFIED` with `E_VERIFICATION_TOOL_UNAVAILABLE`.
|
|
83
|
+
|
|
84
|
+
Do not retry a failed non-installing lookup with a command that implicitly
|
|
85
|
+
downloads or installs the missing package.
|
|
86
|
+
|
|
87
|
+
Examples of forbidden escalation without authority:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
npx --no-install TOOL → missing
|
|
91
|
+
npx TOOL → implicit install
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
command -v TOOL → missing
|
|
96
|
+
package-manager install TOOL
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
local executable missing
|
|
101
|
+
curl | sh
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Automatic installation is allowed only when an explicit ForgeLoop rule grants
|
|
105
|
+
that exact task-scoped installation authority and higher-priority platform/user
|
|
106
|
+
rules permit it.
|
|
107
|
+
|
|
108
|
+
A missing checker must never be converted into environmental mutation merely
|
|
109
|
+
to make verification pass.
|
|
110
|
+
|
|
71
111
|
## Blocking vs Non-Blocking Decisions
|
|
72
112
|
|
|
73
113
|
Classify every unresolved decision before deciding whether to ask the user.
|
package/LOOP_SYSTEM_DESIGN.md
CHANGED
|
@@ -10,11 +10,13 @@ The system should use every guide that materially helps the task without loading
|
|
|
10
10
|
|
|
11
11
|
## Primary decisions
|
|
12
12
|
|
|
13
|
-
- The
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
- The protocol is vendor-neutral, project-scoped, and capability-based,
|
|
14
|
+
supporting any AI agent, coding assistant, IDE runtime, or developer workflow.
|
|
15
|
+
- Common discovery surfaces (e.g. `AGENTS.md`, `CLAUDE.md`, `.cursor/rules/`,
|
|
16
|
+
`.github/copilot-instructions.md`) use project-local shims delegating to the
|
|
17
|
+
canonical protocol under `.forgeloop/kit/`, while other environments use the
|
|
18
|
+
shared `AGENTS.md` entry point or manual bootstrap.
|
|
19
|
+
- The portable instruction layer uses Markdown and each environment's native instruction mechanism; the optional local Node CLI validates and installs the kit without an agent runtime or third-party dependency.
|
|
18
20
|
- English is the only language used by repository content and guide metadata.
|
|
19
21
|
- The agent uses all applicable guides, not every file indiscriminately.
|
|
20
22
|
- Design, planning, test-first, and review process gates live in the canonical loop and scale with task risk instead of becoming unconditional boilerplate in every adapter or architecture note.
|
|
@@ -389,8 +391,8 @@ update practice.
|
|
|
389
391
|
## Acceptance criteria
|
|
390
392
|
|
|
391
393
|
- The repository and its maintained content are English-only.
|
|
392
|
-
-
|
|
393
|
-
|
|
394
|
+
- Common project instruction surfaces and generic bootstrap mechanisms have a
|
|
395
|
+
documented entry into one canonical loop.
|
|
394
396
|
- The router selects every relevant guide and excludes irrelevant guides in the six defined scenarios.
|
|
395
397
|
- The profile contains verifiable facts, sources, and real commands without secrets.
|
|
396
398
|
- The loop requires evidence before completion claims and exits safely when blocked.
|
package/PROTOCOL_INTEGRATION.md
CHANGED
|
@@ -140,6 +140,21 @@ If the required CLI or API capability cannot be resolved:
|
|
|
140
140
|
|
|
141
141
|
Report the corresponding ForgeLoop dimension as `NOT_VERIFIED` / `E_FORGELOOP_CLI_UNAVAILABLE`.
|
|
142
142
|
|
|
143
|
+
## Missing tool capability
|
|
144
|
+
|
|
145
|
+
A missing tool is a capability gap, not installation authority.
|
|
146
|
+
|
|
147
|
+
If an expected verifier, browser tool, linter, analyzer, or test dependency is
|
|
148
|
+
not already available:
|
|
149
|
+
|
|
150
|
+
- use a suitable existing local equivalent when possible;
|
|
151
|
+
- otherwise request authority if installation is necessary and allowed;
|
|
152
|
+
- otherwise report the affected verification dimension as not verified with
|
|
153
|
+
`E_VERIFICATION_TOOL_UNAVAILABLE`.
|
|
154
|
+
|
|
155
|
+
Never convert `PROTOCOL_LIMITED` into environmental mutation by implicitly
|
|
156
|
+
installing a package.
|
|
157
|
+
|
|
143
158
|
## Optional capability extensions
|
|
144
159
|
|
|
145
160
|
The installed loop directs the active actor to inspect native model and harness
|
|
@@ -150,6 +165,19 @@ through native mechanisms or upstream installers, then verify it before use.
|
|
|
150
165
|
API credentials, system packages, and unrelated environment changes remain
|
|
151
166
|
separately gated.
|
|
152
167
|
|
|
168
|
+
## Delegation scope
|
|
169
|
+
|
|
170
|
+
Delegation is optional.
|
|
171
|
+
|
|
172
|
+
A run that contains no delegation events, no delegated task references, and no
|
|
173
|
+
delegation artifacts is a valid single-actor run.
|
|
174
|
+
|
|
175
|
+
Missing delegation artifacts must not make such a run incomplete. For a purely
|
|
176
|
+
local single-actor lifecycle, the delegation dimension is `NOT_APPLICABLE`.
|
|
177
|
+
|
|
178
|
+
Once delegation is observed in canonical state, receipt, or event history, the
|
|
179
|
+
required delegation artifacts become mandatory.
|
|
180
|
+
|
|
153
181
|
## Instruction precedence
|
|
154
182
|
|
|
155
183
|
When multiple instruction layers exist, follow standard precedence:
|
package/README.md
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
|
-
# ForgeLoop —
|
|
1
|
+
# ForgeLoop — Verifiable Engineering Protocol
|
|
2
2
|
|
|
3
3
|
[](https://github.com/cassiomc1/forgeloop/actions/workflows/docs-quality.yml)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
It covers product strategy, code, testing, security, performance,
|
|
7
|
-
accessibility, design, and web games across web, mobile, and desktop projects.
|
|
5
|
+
ForgeLoop is a portable, verifiable engineering protocol for AI-assisted development and developer workflows.
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
`AGENTS.md`, `CLAUDE.md`, `.cursor/rules`, and
|
|
11
|
-
`.github/copilot-instructions.md`. The integration contract and capability levels are documented
|
|
12
|
-
in [`PROTOCOL_INTEGRATION.md`](./PROTOCOL_INTEGRATION.md). Adopt only the guides
|
|
13
|
-
relevant to the target project.
|
|
7
|
+
It is project-scoped, capability-based, and vendor-neutral. It turns intent into contract-driven execution with deterministic routing, resumable state, evidence-backed verification, recovery, and validator-backed completion.
|
|
14
8
|
|
|
15
|
-
ForgeLoop
|
|
16
|
-
and developer workflows. It turns intent into contract-driven execution with
|
|
17
|
-
deterministic routing, resumable state, evidence-backed verification, recovery, and
|
|
18
|
-
validator-backed completion.
|
|
9
|
+
ForgeLoop does not depend on a specific model, provider, agent product, IDE, or orchestration runtime.
|
|
19
10
|
|
|
20
|
-
The
|
|
21
|
-
|
|
22
|
-
discovery
|
|
23
|
-
|
|
11
|
+
The repository also provides an English-only collection of operational engineering guides covering product strategy, clean code, testing, security, performance, accessibility, visual design, and web games across web, mobile, and desktop projects.
|
|
12
|
+
|
|
13
|
+
Project-local discovery surfaces (`AGENTS.md`, `CLAUDE.md`, `.cursor/rules/project-loop.mdc`, `.github/copilot-instructions.md`) and manual bootstrap paths delegate to the same canonical protocol in `.forgeloop/kit/`. The capability levels and integration contract are documented in [`PROTOCOL_INTEGRATION.md`](./PROTOCOL_INTEGRATION.md). Adopt only the guides relevant to the target project.
|
|
14
|
+
|
|
15
|
+
The npm package also ships the local `forgeloop` CLI. In a target project it installs canonical documents under `.forgeloop/kit/`, keeps only small native discovery shims at the root, and stores mutable protocol artifacts under `.forgeloop/`.
|
|
24
16
|
|
|
25
17
|
## Catalog
|
|
26
18
|
|
|
@@ -88,13 +80,13 @@ Request → discovery → profile → routing → plan → execution
|
|
|
88
80
|
└ evidence-only rejection / next cycle
|
|
89
81
|
```
|
|
90
82
|
|
|
91
|
-
ForgeLoop is project-scoped, capability-based, and vendor-neutral.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
capability levels, degradation rules, and precedence
|
|
83
|
+
ForgeLoop is project-scoped, capability-based, and vendor-neutral.
|
|
84
|
+
|
|
85
|
+
Project-local discovery surfaces delegate to the same canonical ForgeLoop protocol. Execution environments that automatically discover one of those instruction surfaces can use it directly, while custom runtimes, automation systems, and developer workflows can use the manual bootstrap path.
|
|
86
|
+
|
|
87
|
+
Capabilities determine execution. Runtime names do not determine protocol applicability.
|
|
88
|
+
|
|
89
|
+
See [`PROTOCOL_INTEGRATION.md`](./PROTOCOL_INTEGRATION.md) for discovery, capability levels, degradation rules, and precedence.
|
|
98
90
|
|
|
99
91
|
### Migration recovery and release freeze
|
|
100
92
|
|
|
@@ -117,12 +109,11 @@ The regression suite injects failures at these boundaries and verifies that
|
|
|
117
109
|
owned cleanup. The frozen published installation under
|
|
118
110
|
[`tests/fixtures/legacy-0.1.6/`](./tests/fixtures/legacy-0.1.6/) is derived
|
|
119
111
|
from the real npm tarball, includes provenance and digests, and is copied into
|
|
120
|
-
The current published release is `@cassiomc1/forgeloop@0.1.
|
|
121
|
-
Earlier `0.1.8`, `0.1.9`, and `0.1.
|
|
122
|
-
their tags or `v0.1.10`. Version `0.1.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
divergence detection.
|
|
112
|
+
The current published release is `@cassiomc1/forgeloop@0.1.13`.
|
|
113
|
+
Earlier `0.1.8`, `0.1.9`, `0.1.10`, `0.1.11`, and `0.1.12` references are historical; never move
|
|
114
|
+
their tags or `v0.1.10`. Version `0.1.13` enforces the missing verification tool
|
|
115
|
+
policy, conditional single-actor delegation validation, and a universal
|
|
116
|
+
vendor-neutral engineering protocol positioning.
|
|
126
117
|
|
|
127
118
|
## How to prompt ForgeLoop
|
|
128
119
|
|
|
@@ -212,12 +203,12 @@ project without overwriting local instructions. When the package is available
|
|
|
212
203
|
in the npm registry, use the commands below; otherwise use the repository
|
|
213
204
|
checkout fallback.
|
|
214
205
|
|
|
215
|
-
The current published release is `@cassiomc1/forgeloop@0.1.
|
|
206
|
+
The current published release is `@cassiomc1/forgeloop@0.1.13`.
|
|
216
207
|
Pin this version when a reproducible blind run or release-identity check is
|
|
217
208
|
required:
|
|
218
209
|
|
|
219
210
|
```bash
|
|
220
|
-
npx @cassiomc1/forgeloop@0.1.
|
|
211
|
+
npx @cassiomc1/forgeloop@0.1.13 --version
|
|
221
212
|
npx @cassiomc1/forgeloop init
|
|
222
213
|
npx @cassiomc1/forgeloop doctor
|
|
223
214
|
npx @cassiomc1/forgeloop update
|
|
@@ -314,11 +305,13 @@ cross-artifact relationships plus the same derived freshness classification
|
|
|
314
305
|
used by `inspect` and `status`. Supply `--contract-file` to compare the saved
|
|
315
306
|
contract fingerprint with the current contract; omitting it leaves contract
|
|
316
307
|
freshness as `NOT_VERIFIED` and a complete artifact set requires revalidation.
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
`
|
|
321
|
-
|
|
308
|
+
Delegation artifacts are required only when delegation is present in the
|
|
309
|
+
canonical execution history or explicitly supplied as part of a delegated run.
|
|
310
|
+
For a purely local single-actor lifecycle, the delegation dimension is
|
|
311
|
+
`NOT_APPLICABLE` and does not require task briefs or delegated results. When
|
|
312
|
+
delegation is in scope, also supply the matching repeated
|
|
313
|
+
`--task-brief <path>` and `--delegated-result <path>` inputs; omitting them in a
|
|
314
|
+
delegated run reports `INCOMPLETE`.
|
|
322
315
|
It returns `VALID`, `INCOMPLETE`, `STALE`, `INCONSISTENT`, or `INVALID` with
|
|
323
316
|
exact invariant codes and derived stale reasons. The persisted
|
|
324
317
|
`.forgeloop/work-state.json` schema is unchanged: `status`, `stale`, and `fresh`
|
|
@@ -575,8 +568,8 @@ installed automatically.
|
|
|
575
568
|
|
|
576
569
|
## Optional multimodal capabilities
|
|
577
570
|
|
|
578
|
-
[Qwen-MM-Plugins](https://github.com/QwenLM/Qwen-MM-Plugins) can extend
|
|
579
|
-
|
|
571
|
+
[Qwen-MM-Plugins](https://github.com/QwenLM/Qwen-MM-Plugins) can extend an
|
|
572
|
+
execution environment with skills and optional MCP servers. Before using a
|
|
580
573
|
multimodal or media operation, the agent checks the model and harness for a
|
|
581
574
|
callable native capability. If the task requires a missing keyless capability,
|
|
582
575
|
the agent installs only the smallest matching `qwen-mm-plugins-<cap>` capability
|
package/THREAT_MODEL.md
CHANGED
|
@@ -33,6 +33,8 @@ remaining trust boundaries and their executable evidence.
|
|
|
33
33
|
| Runtime self-exemption | An execution environment discovers ForgeLoop but decides that the protocol does not apply because the environment is not named in documentation | Project adapter discovery and runtime interpretation | Universal applicability marker, capability-based integration, explicit unknown-runtime rule, no finite eligibility allowlist | A non-compliant runtime can ignore project instructions entirely | `tests/discovery-surfaces.test.js`, `tests/test_workflow_policy.py` |
|
|
34
34
|
| Blind oracle exposure | The system under test reads expected route/gate/evidence answers from the installed package and contaminates a blind conformance run | Published npm package and agent-readable target workspace | Exclude conformance oracles from npm package, tarball leak scan in `pack:check`, external harness-owned oracle | A misconfigured external harness may still copy oracle material into target | `tests/package.test.js`, `conformance/README.md` |
|
|
35
35
|
| Lifecycle simulation after CLI resolution failure | A runtime manually writes protocol-owned JSON and falsely claims conformance when the CLI is unresolved | Lifecycle-owned protocol state and CLI availability | CLI-owned artifact policy, universal adapter prohibition, validator-backed completion, append-only ledger hash chain | A privileged local process can tamper with local files; ForgeLoop detects consistency, not remote attestation | `tests/discovery-surfaces.test.js`, `tests/lifecycle.test.js`, `LOOP_ENGINEERING.md` |
|
|
36
|
+
| Unauthorized verification dependency installation | The active actor mutates the environment by downloading or installing a missing checker merely to satisfy verification | Verification capability discovery and installation authority | Missing verification tool policy, non-installing resolution first, explicit installation authority, equivalent-check fallback, NOT_VERIFIED degradation | A privileged external process may still install tools outside ForgeLoop's control | `tests/verification-capability.test.js`, `tests/discovery-surfaces.test.js`, `LOOP_ENGINEERING.md` |
|
|
37
|
+
| False delegation requirement | A valid single-actor run is incorrectly reported as incomplete because a validator demands artifacts for delegation that never occurred | Validator delegation scope resolution | Canonical delegationIsInScope predicate, conditional delegation validation in validateTaskArtifactSet and validate-protocol | Malformed or externally injected artifacts may require INCONSISTENT classification | `tests/conformance.test.js`, `tests/validate-protocol-cli.test.js` |
|
|
36
38
|
|
|
37
39
|
## Boundary rules
|
|
38
40
|
|
package/package.json
CHANGED
|
@@ -97,14 +97,6 @@ export async function runValidateProtocol({
|
|
|
97
97
|
const stateClassification = state && readErrors.length === 0 && !stateValidationError
|
|
98
98
|
? await classifyLoadedWorkState({ target, state, contractFile })
|
|
99
99
|
: null;
|
|
100
|
-
const result = validateTaskArtifactSet({
|
|
101
|
-
route,
|
|
102
|
-
state,
|
|
103
|
-
stateClassification,
|
|
104
|
-
receipt,
|
|
105
|
-
taskBriefs,
|
|
106
|
-
delegatedResults,
|
|
107
|
-
});
|
|
108
100
|
let readyConsistencyErrors = [];
|
|
109
101
|
try {
|
|
110
102
|
const persistedPreflight = await readJsonArtifact(target, ARTIFACT_PATHS.preflight, "preflight", packageRoot);
|
|
@@ -119,9 +111,11 @@ export async function runValidateProtocol({
|
|
|
119
111
|
} catch {
|
|
120
112
|
// A missing or invalid preflight is already outside the optional protocol set.
|
|
121
113
|
}
|
|
114
|
+
let ledgerEvents = [];
|
|
122
115
|
let ledgerErrors = [];
|
|
123
116
|
if (state && !stateValidationError) {
|
|
124
117
|
const ledger = await validateEventLedger(target, packageRoot);
|
|
118
|
+
ledgerEvents = ledger.events ?? [];
|
|
125
119
|
ledgerErrors = [
|
|
126
120
|
...ledger.errors.map((error) => ({ ...error, artifacts: [ARTIFACT_PATHS.events] })),
|
|
127
121
|
...validateStateLedgerCoherence(state, ledger.events).map((error) => ({
|
|
@@ -130,6 +124,15 @@ export async function runValidateProtocol({
|
|
|
130
124
|
})),
|
|
131
125
|
];
|
|
132
126
|
}
|
|
127
|
+
const result = validateTaskArtifactSet({
|
|
128
|
+
route,
|
|
129
|
+
state,
|
|
130
|
+
stateClassification,
|
|
131
|
+
receipt,
|
|
132
|
+
taskBriefs,
|
|
133
|
+
delegatedResults,
|
|
134
|
+
events: ledgerEvents,
|
|
135
|
+
});
|
|
133
136
|
if (readErrors.length > 0 || schemaErrors.length > 0 || readyConsistencyErrors.length > 0 || ledgerErrors.length > 0) {
|
|
134
137
|
return {
|
|
135
138
|
...result,
|
package/src/core/conformance.js
CHANGED
|
@@ -23,6 +23,24 @@ function sortErrors(errors) {
|
|
|
23
23
|
|| left.message.localeCompare(right.message));
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
export function delegationIsInScope({
|
|
27
|
+
state = null,
|
|
28
|
+
receipt = null,
|
|
29
|
+
events = [],
|
|
30
|
+
taskBriefs = [],
|
|
31
|
+
delegatedResults = [],
|
|
32
|
+
} = {}) {
|
|
33
|
+
if (taskBriefs && taskBriefs.length > 0) return true;
|
|
34
|
+
if (delegatedResults && delegatedResults.length > 0) return true;
|
|
35
|
+
if (state?.delegatedTasks && state.delegatedTasks.length > 0) return true;
|
|
36
|
+
if (state?.delegatedTaskIds && state.delegatedTaskIds.length > 0) return true;
|
|
37
|
+
if (receipt?.delegatedTasks && receipt.delegatedTasks.length > 0) return true;
|
|
38
|
+
if (Array.isArray(events) && events.some((event) => typeof event?.type === "string" && event.type.toLowerCase().includes("delegat"))) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
26
44
|
export function validateTaskArtifactSet({
|
|
27
45
|
route = null,
|
|
28
46
|
state = null,
|
|
@@ -30,6 +48,7 @@ export function validateTaskArtifactSet({
|
|
|
30
48
|
receipt = null,
|
|
31
49
|
taskBriefs = [],
|
|
32
50
|
delegatedResults = [],
|
|
51
|
+
events = [],
|
|
33
52
|
} = {}) {
|
|
34
53
|
const errors = [];
|
|
35
54
|
const incomplete = [];
|
|
@@ -62,6 +81,7 @@ export function validateTaskArtifactSet({
|
|
|
62
81
|
errors.push(error("STATE_RECEIPT_GUIDES_MISMATCH", "execution-receipt.selectedGuides must equal work-state.selectedGuides", ["state", "receipt"]));
|
|
63
82
|
}
|
|
64
83
|
|
|
84
|
+
const delegationActive = delegationIsInScope({ state, receipt, events, taskBriefs, delegatedResults });
|
|
65
85
|
const briefIds = new Set();
|
|
66
86
|
for (const brief of taskBriefs) {
|
|
67
87
|
if (!brief?.taskId) continue;
|
|
@@ -86,13 +106,18 @@ export function validateTaskArtifactSet({
|
|
|
86
106
|
}
|
|
87
107
|
}
|
|
88
108
|
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
|
|
109
|
+
if (delegationActive) {
|
|
110
|
+
if (taskBriefs.length > 0) {
|
|
111
|
+
for (const taskId of [...briefIds].sort()) {
|
|
112
|
+
if (!delegatedIds.has(taskId)) incomplete.push(`missing delegated result: ${taskId}`);
|
|
113
|
+
}
|
|
114
|
+
} else if (delegatedResults.length > 0) {
|
|
115
|
+
incomplete.push("task briefs are required when delegated results are supplied");
|
|
116
|
+
} else {
|
|
117
|
+
incomplete.push("task briefs and delegated results were not supplied for delegated task");
|
|
92
118
|
}
|
|
93
|
-
} else if (delegatedResults.length === 0) {
|
|
94
|
-
incomplete.push("task briefs and delegated results were not supplied");
|
|
95
119
|
}
|
|
120
|
+
|
|
96
121
|
if (!route || !state || !receipt) incomplete.push("route, state, and receipt are all required for a complete artifact set");
|
|
97
122
|
|
|
98
123
|
const sortedErrors = sortErrors(errors);
|
|
@@ -117,6 +142,22 @@ export function validateTaskArtifactSet({
|
|
|
117
142
|
}
|
|
118
143
|
: null;
|
|
119
144
|
|
|
145
|
+
const delegation = delegationActive
|
|
146
|
+
? {
|
|
147
|
+
status: sortedErrors.some((e) => e.code.includes("DELEGAT") || e.code.includes("TASK"))
|
|
148
|
+
? "INCONSISTENT"
|
|
149
|
+
: incomplete.some((i) => i.includes("delegat") || i.includes("brief"))
|
|
150
|
+
? "INCOMPLETE"
|
|
151
|
+
: "VALID",
|
|
152
|
+
required: true,
|
|
153
|
+
errors: sortedErrors.filter((e) => e.code.includes("DELEGAT") || e.code.includes("TASK")),
|
|
154
|
+
}
|
|
155
|
+
: {
|
|
156
|
+
status: "NOT_APPLICABLE",
|
|
157
|
+
required: false,
|
|
158
|
+
errors: [],
|
|
159
|
+
};
|
|
160
|
+
|
|
120
161
|
const evidenceKind = status === "VALID"
|
|
121
162
|
? "OBSERVED"
|
|
122
163
|
: status === "INCOMPLETE"
|
|
@@ -131,6 +172,7 @@ export function validateTaskArtifactSet({
|
|
|
131
172
|
errors: sortedErrors,
|
|
132
173
|
incomplete: [...new Set(incomplete)].sort(),
|
|
133
174
|
stale,
|
|
175
|
+
delegation,
|
|
134
176
|
evidence: [createEvidence({
|
|
135
177
|
kind: evidenceKind,
|
|
136
178
|
source: "ForgeLoop protocol conformance",
|
|
@@ -43,6 +43,10 @@ route, required gates, and READY preflight.
|
|
|
43
43
|
Use the project-local ForgeLoop CLI for lifecycle-owned protocol state.
|
|
44
44
|
Never manually synthesize lifecycle chronology or assign ForgeLoop COMPLETE.
|
|
45
45
|
|
|
46
|
+
Do not install a missing verification tool merely to satisfy a check.
|
|
47
|
+
Use an existing equivalent, obtain explicit authority, or report the
|
|
48
|
+
verification dimension as NOT_VERIFIED.
|
|
49
|
+
|
|
46
50
|
Before claiming ForgeLoop-verified completion, require
|
|
47
51
|
\`forgeloop complete\` to return \`VALID\`.
|
|
48
52
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export const E_VERIFICATION_TOOL_UNAVAILABLE = "E_VERIFICATION_TOOL_UNAVAILABLE";
|
|
2
|
+
export const E_INSTALLATION_AUTHORITY_REQUIRED = "E_INSTALLATION_AUTHORITY_REQUIRED";
|
|
3
|
+
|
|
4
|
+
export function classifyVerificationCapability({
|
|
5
|
+
available = false,
|
|
6
|
+
equivalentAvailable = false,
|
|
7
|
+
installationAuthorized = false,
|
|
8
|
+
installationRequired = false,
|
|
9
|
+
} = {}) {
|
|
10
|
+
if (available) {
|
|
11
|
+
return {
|
|
12
|
+
action: "USE_AVAILABLE",
|
|
13
|
+
reasonCode: null,
|
|
14
|
+
message: "Verification tool is locally available.",
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (equivalentAvailable) {
|
|
19
|
+
return {
|
|
20
|
+
action: "USE_EQUIVALENT",
|
|
21
|
+
reasonCode: null,
|
|
22
|
+
message: "An existing local equivalent verifier is available.",
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (installationAuthorized) {
|
|
27
|
+
return {
|
|
28
|
+
action: "INSTALL_AUTHORIZED",
|
|
29
|
+
reasonCode: null,
|
|
30
|
+
message: "Installation is explicitly authorized for this verification requirement.",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (installationRequired) {
|
|
35
|
+
return {
|
|
36
|
+
action: "REQUEST_AUTHORITY",
|
|
37
|
+
reasonCode: E_INSTALLATION_AUTHORITY_REQUIRED,
|
|
38
|
+
message: "Verification tool is required but installation authority has not been granted.",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
action: "RECORD_NOT_VERIFIED",
|
|
44
|
+
reasonCode: E_VERIFICATION_TOOL_UNAVAILABLE,
|
|
45
|
+
message: "Verification tool is absent and installation was not authorized.",
|
|
46
|
+
};
|
|
47
|
+
}
|