@cassiomc1/forgeloop 0.1.12 → 0.1.14

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.
@@ -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.
@@ -68,6 +68,79 @@ 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
+
111
+ ### Verification command resolution modes and validator enforcement
112
+
113
+ Every verification command path is classified by resolution mode:
114
+
115
+ | Mode | Examples | May install software | Authority required |
116
+ | --- | --- | --- | --- |
117
+ | `LOCAL_EXECUTABLE` | `node scripts/test.js`, `python3 -m unittest`, `./bin/check` | No | No |
118
+ | `LOCAL_PACKAGE_BINARY` | `./node_modules/.bin/tool`, `npm test`, `pnpm test`, `yarn test` | No | No |
119
+ | `NON_INSTALLING_RESOLUTION` | `npx --no-install tool`, `npx --no tool` | No | No |
120
+ | `INSTALL_CAPABLE_RESOLUTION` | `npx tool`, `pnpm dlx tool`, `yarn dlx tool`, `bunx tool`, `uvx tool`, `pipx run tool` | Yes | Yes (`E_INSTALLATION_AUTHORITY_REQUIRED`) |
121
+ | `EXPLICIT_INSTALLATION` | `npm install tool`, `pnpm add tool`, `pip install tool`, `cargo install tool` | Yes | Yes (`E_INSTALLATION_AUTHORITY_REQUIRED`) |
122
+
123
+ **Validator-enforced rule**: Any verification command executed via an installation-capable or explicit-installation resolution mode without a valid canonical installation authority grant is rejected by `record-check`, `audit`, and `complete` with error code `E_INSTALLATION_AUTHORITY_REQUIRED`, `E_AUTHORITY_INVALID`, `E_AUTHORITY_SCOPE_MISMATCH`, or `E_AUTHORITY_UNTRUSTED_SOURCE` and cannot contribute to `VALID` completion.
124
+
125
+ Authority cannot be self-issued by the actor consuming it. Boolean fields inside verification evidence (such as `installationAuthorized: true`) are not sufficient proof of installation authority. Installation authority must be established via a canonical authority grant supplied by a host/operator trust boundary and referenced via `installationAuthorityRef`.
126
+
127
+ The runtime authority context has two modes:
128
+
129
+ - `NONE` is the default for the actor-facing standalone CLI. `FORGELOOP_AUTHORITY_FILE` and `FORGELOOP_AUTHORITY_DIR` may select candidate source metadata for compatibility and diagnostics, but they do not make a source trusted. An environment-selected source is rejected with `E_AUTHORITY_UNTRUSTED_SOURCE` when it is used for an installation-capable verification.
130
+ - `HOST_ATTESTED` is an internal integration context supplied by a host-owned wrapper, embedded API, or equivalent boundary. It may select a trusted authority file, directory, or in-memory provider only when the actor cannot replace that context at command invocation time. The CLI exposes no flag that promotes a source to `HOST_ATTESTED`.
131
+
132
+ External path is not equivalent to external authority ownership. The host-attested source must still resolve outside the actor-writable target, and a project-local `.forgeloop/authorities/` artifact remains an untrusted reference, cache, diagnostic, or mirror by default. A local claim such as `source: operator` is not proof of operator authority.
133
+
134
+ ForgeLoop validates authority semantics, while the host defines the trust boundary. If the host grants the actor write access to the configured attested source, the host boundary is compromised and ForgeLoop cannot distinguish operator authority from actor fabrication without a stronger external trust anchor.
135
+
136
+ ### Stale receipt recovery invariant
137
+
138
+ Every recovery action returned by `forgeloop next` must be executable from the state that produced it. When work state changes legitimately after preparing a completion receipt, `forgeloop prepare-completion` refreshes the receipt and re-binds it to current state and changed paths without requiring manual deletion of `.forgeloop/execution-receipt.json`.
139
+
140
+ ### Conformance profile escalation policy
141
+
142
+ A run started in Standard conformance must not be silently escalated to Strict after validator-backed completion. Strict validation is a separate conformance profile. If Strict revalidation is performed after Standard `COMPLETE`, it is treated as a distinct revalidation cycle and does not retroactively invalidate a valid Standard result.
143
+
71
144
  ## Blocking vs Non-Blocking Decisions
72
145
 
73
146
  Classify every unresolved decision before deciding whether to ask the user.
@@ -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 package supports Codex, Claude Code, Cursor, GitHub Copilot, Antigravity,
14
- OpenCode, Hermes, Pi, Command Code, and Freebuff.
15
- - Codex, Claude Code, Cursor, and GitHub Copilot use native entry files; the
16
- other six agents consume the shared `AGENTS.md` entry point.
17
- - The portable instruction layer uses Markdown and each agent's native instruction mechanism; the optional local Node CLI validates and installs the kit without an agent runtime or third-party dependency.
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
- - All ten supported agents have a documented entry into one canonical loop,
393
- with native adapters distinguished from shared `AGENTS.md` compatibility.
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.
@@ -140,6 +140,92 @@ 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
+ Every verification command is classified by resolution mode (`LOCAL_EXECUTABLE`,
156
+ `LOCAL_PACKAGE_BINARY`, `NON_INSTALLING_RESOLUTION`, `INSTALL_CAPABLE_RESOLUTION`,
157
+ `EXPLICIT_INSTALLATION`). Any command that uses an install-capable or installation
158
+ path without a valid canonical authority reference is rejected by `record-check`,
159
+ `audit`, and `complete` with `E_INSTALLATION_AUTHORITY_REQUIRED`, `E_AUTHORITY_INVALID`,
160
+ `E_AUTHORITY_SCOPE_MISMATCH`, or `E_AUTHORITY_UNTRUSTED_SOURCE`.
161
+
162
+ ```text
163
+ capability ≠ authority
164
+ evidence ≠ authority grant
165
+ actor claim ≠ operator grant
166
+ ```
167
+
168
+ Authority cannot be self-issued by the actor consuming it. Boolean fields inside
169
+ verification evidence are not sufficient proof of installation authority.
170
+
171
+ ### Authority provenance
172
+
173
+ Authority provenance is external to actor-authored project state. An external
174
+ path is not equivalent to external authority ownership:
175
+
176
+ ```text
177
+ outside target
178
+
179
+ outside actor control
180
+ ```
181
+
182
+ The standalone CLI uses `trustMode: NONE`. `FORGELOOP_AUTHORITY_FILE` and
183
+ `FORGELOOP_AUTHORITY_DIR` select candidate authority sources, but they do not
184
+ make a source trusted in actor-facing execution. Environment-selected sources
185
+ are rejected with `E_AUTHORITY_UNTRUSTED_SOURCE` for install-capable checks.
186
+
187
+ Trusted authority requires an explicit `HOST_ATTESTED` runtime context supplied
188
+ through an integration boundary the active actor cannot replace at command
189
+ invocation time. Configuration is not trust:
190
+
191
+ ```text
192
+ environment-selected source
193
+
194
+ host-attested source
195
+
196
+ configuration
197
+
198
+ trust
199
+ ```
200
+
201
+ The host-attested source must still resolve outside the actor-writable target. A
202
+ project-local authority reference may identify a grant, but it does not create
203
+ the root of trust.
204
+
205
+ ```text
206
+ actor-authored evidence
207
+
208
+ trusted authority
209
+
210
+ project-local file
211
+
212
+ host grant
213
+
214
+ declared provenance
215
+
216
+ verified provenance
217
+ ```
218
+
219
+ A local artifact claiming `source: operator` is not sufficient proof of operator
220
+ authority. The actor-facing CLI must not expose an equivalent of
221
+ `--authority-source-attested-by-host` or `--trusted-authority-file` that
222
+ self-promotes a source. If the host exposes the attested source as writable to
223
+ the actor, the host boundary has been compromised and ForgeLoop cannot provide
224
+ cryptographic attestation by itself.
225
+
226
+ Never convert `PROTOCOL_LIMITED` into environmental mutation by implicitly
227
+ installing a package.
228
+
143
229
  ## Optional capability extensions
144
230
 
145
231
  The installed loop directs the active actor to inspect native model and harness
@@ -150,6 +236,19 @@ through native mechanisms or upstream installers, then verify it before use.
150
236
  API credentials, system packages, and unrelated environment changes remain
151
237
  separately gated.
152
238
 
239
+ ## Delegation scope
240
+
241
+ Delegation is optional.
242
+
243
+ A run that contains no delegation events, no delegated task references, and no
244
+ delegation artifacts is a valid single-actor run.
245
+
246
+ Missing delegation artifacts must not make such a run incomplete. For a purely
247
+ local single-actor lifecycle, the delegation dimension is `NOT_APPLICABLE`.
248
+
249
+ Once delegation is observed in canonical state, receipt, or event history, the
250
+ required delegation artifacts become mandatory.
251
+
153
252
  ## Instruction precedence
154
253
 
155
254
  When multiple instruction layers exist, follow standard precedence:
package/README.md CHANGED
@@ -1,26 +1,18 @@
1
- # ForgeLoop — Instruction Guides for AI Agents
1
+ # ForgeLoop — Verifiable Engineering Protocol
2
2
 
3
3
  [![Docs quality](https://github.com/cassiomc1/forgeloop/actions/workflows/docs-quality.yml/badge.svg?branch=main)](https://github.com/cassiomc1/forgeloop/actions/workflows/docs-quality.yml)
4
4
 
5
- An English-only collection of operational guides for AI agents and developers.
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
- The files are Markdown and can be used as references, as a foundation for
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 is a portable, verifiable engineering protocol for AI coding environments
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 npm package also ships the local `forgeloop` CLI. In a target project it
21
- installs canonical documents under `.forgeloop/kit/`, keeps only small native
22
- discovery shims at the root, and stores mutable protocol artifacts under
23
- `.forgeloop/`.
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. Thin
92
- native adapters support common discovery surfaces including Codex, Claude Code,
93
- Cursor, and GitHub Copilot, while Antigravity, OpenCode, Hermes, Pi, Command Code,
94
- Freebuff, custom agents, and developer workflows discover the shared `AGENTS.md`
95
- entry point or manual bootstrap. All environments delegate to the same canonical
96
- protocol; see [`PROTOCOL_INTEGRATION.md`](./PROTOCOL_INTEGRATION.md) for
97
- capability levels, degradation rules, and precedence notes.
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,12 @@ 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.11`.
121
- Earlier `0.1.8`, `0.1.9`, and `0.1.10` references are historical; never move
122
- their tags or `v0.1.10`. Version `0.1.11` adds canonical evidence readiness,
123
- requirement-specific terminal result recording, legal repeated verification
124
- cycles, future-result and compound-evidence safeguards, and lifecycle-ledger
125
- divergence detection.
112
+ The latest verified published npm release is `@cassiomc1/forgeloop@0.1.14`.
113
+ The repository release is `0.1.14`.
114
+ Earlier `0.1.8`, `0.1.9`, `0.1.10`, `0.1.11`, `0.1.12`, and `0.1.13` references are historical; never move
115
+ their tags or `v0.1.10`. Release `0.1.14` enforces verification installation
116
+ authority, provides recoverable stale receipt lifecycle in `prepare-completion`,
117
+ and validates single-actor protocol runs.
126
118
 
127
119
  ## How to prompt ForgeLoop
128
120
 
@@ -212,12 +204,13 @@ project without overwriting local instructions. When the package is available
212
204
  in the npm registry, use the commands below; otherwise use the repository
213
205
  checkout fallback.
214
206
 
215
- The current published release is `@cassiomc1/forgeloop@0.1.11`.
216
- Pin this version when a reproducible blind run or release-identity check is
217
- required:
207
+ The current repository package is `@cassiomc1/forgeloop@0.1.14`.
208
+ The latest verified published npm release is `@cassiomc1/forgeloop@0.1.14`.
209
+ For reproducible published-package runs or release-identity checks,
210
+ pin the published version:
218
211
 
219
212
  ```bash
220
- npx @cassiomc1/forgeloop@0.1.11 --version
213
+ npx @cassiomc1/forgeloop@0.1.14 --version
221
214
  npx @cassiomc1/forgeloop init
222
215
  npx @cassiomc1/forgeloop doctor
223
216
  npx @cassiomc1/forgeloop update
@@ -314,11 +307,13 @@ cross-artifact relationships plus the same derived freshness classification
314
307
  used by `inspect` and `status`. Supply `--contract-file` to compare the saved
315
308
  contract fingerprint with the current contract; omitting it leaves contract
316
309
  freshness as `NOT_VERIFIED` and a complete artifact set requires revalidation.
317
- When delegation is in scope, also supply the matching repeated
318
- `--task-brief <path>` and `--delegated-result <path>` inputs. Without those
319
- inputs it reports `INCOMPLETE` with
320
- `task briefs and delegated results were not supplied`; that classification is
321
- separate from a local `complete --json` result of `VALID`.
310
+ Delegation artifacts are required only when delegation is present in the
311
+ canonical execution history or explicitly supplied as part of a delegated run.
312
+ For a purely local single-actor lifecycle, the delegation dimension is
313
+ `NOT_APPLICABLE` and does not require task briefs or delegated results. When
314
+ delegation is in scope, also supply the matching repeated
315
+ `--task-brief <path>` and `--delegated-result <path>` inputs; omitting them in a
316
+ delegated run reports `INCOMPLETE`.
322
317
  It returns `VALID`, `INCOMPLETE`, `STALE`, `INCONSISTENT`, or `INVALID` with
323
318
  exact invariant codes and derived stale reasons. The persisted
324
319
  `.forgeloop/work-state.json` schema is unchanged: `status`, `stale`, and `fresh`
@@ -379,12 +374,17 @@ target project. Its main threat boundaries are:
379
374
  | Data exposure | Receipts and checkpoints reject secret-like keys and values; examples use placeholders, and the repository secret scanner runs in CI. |
380
375
  | Unsafe update overwrite | `update` preserves locally modified files and the target's `.forgeloop/kit/PROJECT_PROFILE.md`; adoption and writes remain bounded to the selected target. |
381
376
  | Dependency supply chain | Runtime code uses Node built-ins only; the package does not install agents, providers, plugins, or remote services. |
377
+ | Installation authority provenance | Standalone CLI uses `trustMode: NONE`: environment-selected `FORGELOOP_AUTHORITY_FILE`/`FORGELOOP_AUTHORITY_DIR` sources are untrusted candidates; only an internal `HOST_ATTESTED` context may select a trusted source outside the actor-writable target. Project-local authority claims remain untrusted. |
382
378
  | Stale replay | Work state records contract and repository fingerprints; drift requires revalidation and never reruns destructive or publication actions automatically. |
383
379
  | Unverified publication | Receipts carry explicit publication booleans; local success never implies a push, pull request, merge, release, or deployment. |
384
380
 
385
381
  The full boundary inventory, residual limitations, and executable evidence are
386
382
  in [`THREAT_MODEL.md`](./THREAT_MODEL.md).
387
383
 
384
+ An external path is not equivalent to external authority ownership. Actor-controlled
385
+ environment configuration is not sufficient proof of host/operator authority;
386
+ trusted authority requires a host-attested integration boundary.
387
+
388
388
  The CLI cannot protect a target from a separately privileged or hostile process
389
389
  that changes the filesystem after validation. Consumers must still review
390
390
  permissions, package provenance, and external actions before granting authority.
@@ -575,8 +575,8 @@ installed automatically.
575
575
 
576
576
  ## Optional multimodal capabilities
577
577
 
578
- [Qwen-MM-Plugins](https://github.com/QwenLM/Qwen-MM-Plugins) can extend a
579
- supported agent harness with skills and optional MCP servers. Before using a
578
+ [Qwen-MM-Plugins](https://github.com/QwenLM/Qwen-MM-Plugins) can extend an
579
+ execution environment with skills and optional MCP servers. Before using a
580
580
  multimodal or media operation, the agent checks the model and harness for a
581
581
  callable native capability. If the task requires a missing keyless capability,
582
582
  the agent installs only the smallest matching `qwen-mm-plugins-<cap>` capability
package/THREAT_MODEL.md CHANGED
@@ -33,6 +33,12 @@ 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` |
38
+ | Self-asserted authority bypass | The active actor supplies `installationAuthorized=true` inside its own verification evidence and thereby grants itself authority | Authority provenance and verification evidence | Boolean claims are ignored; scoped authority references, task/type/tool validation, and validator revalidation in `record-check`/`audit`/`complete` require a trusted source | A host-controlled source is still a semantic trust boundary and is not cryptographic attestation | `tests/verification-capability.test.js`, `tests/authority.test.js`, `tests/stale-receipt-recovery.test.js` |
39
+ | Forged local authority artifact | The active actor creates `.forgeloop/authorities/auth-modlens.json`, claims `source=operator`, and uses the reference to authorize its own installation-capable check | Host/operator authority source versus actor-writable project state | Resolve grants only from an explicit `HOST_ATTESTED` runtime context with an external source outside the target; reject project-local grants with `E_AUTHORITY_UNTRUSTED_SOURCE`; revalidate in `record-check`/`audit`/`complete` | If the host exposes the attested source as writable to the actor, ForgeLoop cannot distinguish genuine grants from actor fabrication without a stronger trust anchor | Local fake rejection, host-attested external acceptance, inside-target rejection, post-record removal and revocation tests |
40
+ | Environment-injected trust root | The active actor creates an authority file outside the project target and sets `FORGELOOP_AUTHORITY_FILE` or `FORGELOOP_AUTHORITY_DIR` when invoking ForgeLoop | Actor-controlled process environment versus host-attested runtime authority | Standalone CLI uses `trustMode: NONE`; environment-selected sources are metadata/candidates only and fail with `E_AUTHORITY_UNTRUSTED_SOURCE`; trusted authority requires an internal `HOST_ATTESTED` context not exposed as a self-assertable CLI option | If the host integration allows the actor to mutate or replace the attested source/context, the host trust boundary is compromised | Environment-injection rejection, standalone audit/complete rejection, host-attested positive path |
41
+ | Stale receipt recovery dead-end | Work state changes after preparing a receipt, leaving a mismatch that cannot be refreshed because the old receipt is rejected during re-preparation | Preparation lifecycle and recovery action resolution | Recoverable stale receipt binding in `prepareCompletion`, executable `PREPARE_COMPLETION` return from `next`, atomic refresh of stateFingerprint and changedPaths | Manual file corruption outside CLI commands requires manual diagnostic recovery | `tests/stale-receipt-recovery.test.js`, `tests/next-executability.test.js` |
36
42
 
37
43
  ## Boundary rules
38
44
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cassiomc1/forgeloop",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "description": "Portable, verifiable engineering protocol for AI coding environments and developer workflows",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "forgeloop://schemas/authority.schema.json",
4
+ "title": "ForgeLoop installation authority grant",
5
+ "type": "object",
6
+ "required": [
7
+ "schemaVersion",
8
+ "protocolVersion",
9
+ "authorityId",
10
+ "taskId",
11
+ "type",
12
+ "status",
13
+ "scope",
14
+ "source"
15
+ ],
16
+ "properties": {
17
+ "schemaVersion": { "const": 1 },
18
+ "protocolVersion": { "const": 1 },
19
+ "authorityId": { "type": "string", "minLength": 1 },
20
+ "taskId": { "type": "string", "minLength": 1 },
21
+ "type": { "enum": ["SOFTWARE_INSTALLATION"] },
22
+ "status": { "enum": ["AUTHORIZED", "REVOKED", "EXPIRED"] },
23
+ "scope": {
24
+ "type": "object",
25
+ "required": ["tool"],
26
+ "properties": {
27
+ "tool": { "type": "string", "minLength": 1 }
28
+ },
29
+ "additionalProperties": false
30
+ },
31
+ "source": { "enum": ["operator", "host", "project-policy"] }
32
+ },
33
+ "additionalProperties": false
34
+ }
@@ -8,6 +8,8 @@ export function formatInspectResult(report) {
8
8
  `Manifest: ${report.manifest.status}`,
9
9
  `Profile: ${report.profile.mode ?? "unknown"}/${report.profile.status ?? "unknown"}`,
10
10
  `Protocol: v${report.protocol.version}`,
11
+ `Authority source: ${report.authority.sourceType ?? "none configured"} / ${report.authority.trusted ? "TRUSTED" : report.authority.trustMode === "NONE" ? "UNATTESTED" : "UNTRUSTED"}`,
12
+ `Authority trust: ${report.authority.trustMode}`,
11
13
  `State: ${report.state.status}`,
12
14
  `Adapters: ${report.adapters.detected.length} detected`,
13
15
  `Findings: ${report.findings.length}`,
@@ -2,8 +2,8 @@ import { prepareCompletion as prepareCompletionArtifacts } from "../core/complet
2
2
 
3
3
  export { prepareCompletionArtifacts as prepareCompletion };
4
4
 
5
- export async function runPrepareCompletion({ target, packageRoot }) {
6
- return prepareCompletionArtifacts({ target, packageRoot });
5
+ export async function runPrepareCompletion({ target, packageRoot, authorityContext, runtimeContext }) {
6
+ return prepareCompletionArtifacts({ target, packageRoot, authorityContext, runtimeContext });
7
7
  }
8
8
 
9
9
  export function formatPrepareCompletionResult(result) {
@@ -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/audit.js CHANGED
@@ -34,8 +34,8 @@ async function compareChangedPaths(target, packageRoot) {
34
34
  };
35
35
  }
36
36
 
37
- export async function evaluateAudit({ target, packageRoot, strict = false } = {}) {
38
- const completion = await evaluateCompletion({ target, packageRoot, strict });
37
+ export async function evaluateAudit({ target, packageRoot, strict = false, authorityContext, runtimeContext } = {}) {
38
+ const completion = await evaluateCompletion({ target, packageRoot, strict, authorityContext, runtimeContext });
39
39
  let manifest = null;
40
40
  let manifestError = null;
41
41
  try {
@@ -1,4 +1,5 @@
1
1
  import { PROTOCOL_VERSION } from "./protocol.js";
2
+ import { validateVerificationAuthority } from "./verification-capability.js";
2
3
 
3
4
  export const CHECK_SCHEMA_VERSION = 1;
4
5
  export const CHECK_STATUSES = Object.freeze(["passed", "failed", "blocked", "not-run"]);
@@ -45,7 +46,7 @@ function assertCompoundStatus(value, label) {
45
46
  }
46
47
  }
47
48
 
48
- export function createCheck(input = {}) {
49
+ export function createCheck(input = {}, options = {}) {
49
50
  const check = {
50
51
  schemaVersion: CHECK_SCHEMA_VERSION,
51
52
  protocolVersion: PROTOCOL_VERSION,
@@ -61,10 +62,10 @@ export function createCheck(input = {}) {
61
62
  ...(input.viewport !== undefined ? { viewport: structuredClone(input.viewport) } : {}),
62
63
  ...(input.details !== undefined ? { details: structuredClone(input.details) } : {}),
63
64
  };
64
- return assertCheck(check);
65
+ return assertCheck(check, "check", options);
65
66
  }
66
67
 
67
- export function assertCheck(value, label = "check") {
68
+ export function assertCheck(value, label = "check", options = {}) {
68
69
  if (!value || typeof value !== "object" || Array.isArray(value)) {
69
70
  throw checkError("E_CHECK_INVALID", `${label} must be an object`);
70
71
  }
@@ -97,15 +98,21 @@ export function assertCheck(value, label = "check") {
97
98
  if (value.status === "not-run" && value.evidenceKind !== "NOT_VERIFIED") {
98
99
  throw contradiction(`${label} not-run must use NOT_VERIFIED evidence`);
99
100
  }
101
+ if (value.status === "passed") {
102
+ const auth = validateVerificationAuthority(value, options);
103
+ if (!auth.valid) {
104
+ throw checkError(auth.error.code, auth.error.message);
105
+ }
106
+ }
100
107
  assertCompoundStatus(value, label);
101
108
  return value;
102
109
  }
103
110
 
104
- export function assertCheckList(value, label = "checks") {
111
+ export function assertCheckList(value, label = "checks", options = {}) {
105
112
  if (!Array.isArray(value)) throw checkError("E_CHECK_INVALID", `${label} must be an array`);
106
113
  const ids = new Set();
107
114
  value.forEach((item, index) => {
108
- assertCheck(item, `${label}[${index}]`);
115
+ assertCheck(item, `${label}[${index}]`, options);
109
116
  if (ids.has(item.id)) throw checkError("E_CHECK_INVALID", `${label} contains duplicate id ${item.id}`);
110
117
  ids.add(item.id);
111
118
  });