@cassiomc1/forgeloop 0.1.4 → 0.1.6
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 +3 -0
- package/.github/copilot-instructions.md +3 -0
- package/AGENTS.md +3 -0
- package/AGENT_COMPATIBILITY.md +42 -0
- package/CLAUDE.md +3 -0
- package/LOOP_ENGINEERING.md +108 -0
- package/QUALITY_SCORECARD.md +13 -4
- package/conformance/README.md +28 -0
- package/conformance/runs/2026-08-13-codex-fifth-live.md +386 -0
- package/package.json +1 -1
- package/src/core/workflow-compatibility.js +151 -0
|
@@ -38,3 +38,6 @@ Before asking any product-detail question, classify it as `BLOCKING` or
|
|
|
38
38
|
before asking. Do not ask the user to choose among reversible local
|
|
39
39
|
product-positioning alternatives; the canonical checklist and boundary remain
|
|
40
40
|
in `LOOP_ENGINEERING.md`.
|
|
41
|
+
|
|
42
|
+
External workflow approval rules do not override ForgeLoop's autonomous-mode
|
|
43
|
+
precedence; consult `LOOP_ENGINEERING.md#external-workflow-compatibility`.
|
|
@@ -36,3 +36,6 @@ Before asking any product-detail question, classify it as `BLOCKING` or
|
|
|
36
36
|
before asking. Do not ask the user to choose among reversible local
|
|
37
37
|
product-positioning alternatives; the canonical checklist and boundary remain
|
|
38
38
|
in `LOOP_ENGINEERING.md`.
|
|
39
|
+
|
|
40
|
+
External workflow approval rules do not override ForgeLoop's autonomous-mode
|
|
41
|
+
precedence; consult `LOOP_ENGINEERING.md#external-workflow-compatibility`.
|
package/AGENTS.md
CHANGED
|
@@ -37,3 +37,6 @@ Before asking any product-detail question, classify it as `BLOCKING` or
|
|
|
37
37
|
before asking. Do not ask the user to choose among reversible local
|
|
38
38
|
product-positioning alternatives; the canonical checklist and boundary remain
|
|
39
39
|
in `LOOP_ENGINEERING.md`.
|
|
40
|
+
|
|
41
|
+
External workflow approval rules do not override ForgeLoop's autonomous-mode
|
|
42
|
+
precedence; consult `LOOP_ENGINEERING.md#external-workflow-compatibility`.
|
package/AGENT_COMPATIBILITY.md
CHANGED
|
@@ -96,6 +96,48 @@ When a target already has local rules, keep them and merge only the relevant
|
|
|
96
96
|
loop reference manually. Run `doctor --path /path/to/project` after resolving
|
|
97
97
|
the merge so missing files and managed drift are visible.
|
|
98
98
|
|
|
99
|
+
## External workflow compatibility
|
|
100
|
+
|
|
101
|
+
An external planning, brainstorming, design-review, testing, or documentation
|
|
102
|
+
workflow can be installed and still be `INCOMPATIBLE WITH AUTONOMOUS MODE`.
|
|
103
|
+
Installation is a capability fact; compatibility is a precedence and behavior
|
|
104
|
+
fact. The ForgeLoop `NON_BLOCKING` classification remains authoritative in
|
|
105
|
+
autonomous mode. A mandatory approval policy for a reversible local choice is
|
|
106
|
+
recorded as `WORKFLOW_CONFLICT`, with no user question and no fake entry in
|
|
107
|
+
`current-contract.unresolvedDecisions[]`.
|
|
108
|
+
|
|
109
|
+
The supported autonomous boundary is:
|
|
110
|
+
|
|
111
|
+
| Workflow policy | Result |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| Local planning, review, tests, or docs | Compatible. |
|
|
114
|
+
| Approval only for a real ForgeLoop `BLOCKING` decision | Compatible; the justified question may proceed. |
|
|
115
|
+
| Approval for every design choice or before implementation | `INCOMPATIBLE WITH AUTONOMOUS MODE`. |
|
|
116
|
+
| Reclassifying reversible aesthetics as blocking | `INCOMPATIBLE WITH AUTONOMOUS MODE`. |
|
|
117
|
+
|
|
118
|
+
Interactive operation is explicit (`autonomousMode=false`) and must not be
|
|
119
|
+
selected silently. Live conformance records the available and invoked external
|
|
120
|
+
workflows, mandatory-approval setting, brainstorming/design hard gates,
|
|
121
|
+
autonomy mode, process count, subagent count, and delegation status. For the
|
|
122
|
+
sixth blind run, the harness must report:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
mandatory-approval workflows enabled: NO
|
|
126
|
+
external brainstorming hard gate enabled: NO
|
|
127
|
+
external design approval gate enabled: NO
|
|
128
|
+
subagents enabled: NO
|
|
129
|
+
delegation enabled: NO
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Question attribution remains `USER_REQUIREMENT`,
|
|
133
|
+
`FORGELOOP_BLOCKING_DECISION`, `EXTERNAL_WORKFLOW_POLICY`, or
|
|
134
|
+
`MODEL_PREFERENCE`. In autonomous mode, only the first two can authorize a
|
|
135
|
+
question, and `ASK_USER` additionally requires a valid ForgeLoop blocking
|
|
136
|
+
reason. External policy alone cannot manufacture a blocker.
|
|
137
|
+
|
|
138
|
+
If a mandatory approval workflow cannot be disabled, the run is
|
|
139
|
+
`TEST_NOT_STARTED`; do not call it a failed or successful conformance result.
|
|
140
|
+
|
|
99
141
|
## Deterministic verification boundary
|
|
100
142
|
|
|
101
143
|
The repository verifies package contents, adapter paths, installation into a
|
package/CLAUDE.md
CHANGED
|
@@ -33,3 +33,6 @@ Before asking any product-detail question, classify it as `BLOCKING` or
|
|
|
33
33
|
before asking. Do not ask the user to choose among reversible local
|
|
34
34
|
product-positioning alternatives; the canonical checklist and boundary remain
|
|
35
35
|
in `LOOP_ENGINEERING.md`.
|
|
36
|
+
|
|
37
|
+
External workflow approval rules do not override ForgeLoop's autonomous-mode
|
|
38
|
+
precedence; consult `LOOP_ENGINEERING.md#external-workflow-compatibility`.
|
package/LOOP_ENGINEERING.md
CHANGED
|
@@ -164,6 +164,114 @@ ask user with blockingReason
|
|
|
164
164
|
No clarification stop is allowed before a serialized contract exists. A
|
|
165
165
|
non-blocking ambiguity never becomes a contract blocker.
|
|
166
166
|
|
|
167
|
+
## External Workflow Compatibility
|
|
168
|
+
|
|
169
|
+
ForgeLoop's decision classification has precedence over an external workflow's
|
|
170
|
+
planning, brainstorming, review, testing, or documentation policy. The
|
|
171
|
+
canonical order remains:
|
|
172
|
+
|
|
173
|
+
```text
|
|
174
|
+
uncertainty → classify → NON_BLOCKING → assume → record → continue
|
|
175
|
+
uncertainty → classify → BLOCKING → serialize → ask
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
An external workflow may improve the plan, review the change, or recommend a
|
|
179
|
+
test. It must not turn a ForgeLoop `NON_BLOCKING` decision into mandatory user
|
|
180
|
+
approval while the task is in autonomous mode. `NON_BLOCKING` remains
|
|
181
|
+
`NON_BLOCKING`; a policy that requires approval for it is a
|
|
182
|
+
`WORKFLOW_CONFLICT`, not a user blocker. Record the conflict and continue with
|
|
183
|
+
the safe reversible default. Do not put the conflict in
|
|
184
|
+
`current-contract.unresolvedDecisions[]` as a fake user decision.
|
|
185
|
+
|
|
186
|
+
The stable compatibility reason codes are:
|
|
187
|
+
|
|
188
|
+
```text
|
|
189
|
+
E_EXTERNAL_WORKFLOW_APPROVAL_CONFLICT
|
|
190
|
+
E_EXTERNAL_WORKFLOW_BLOCKS_NON_BLOCKING
|
|
191
|
+
E_EXTERNAL_WORKFLOW_REQUIRES_USER_GATE
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Autonomous mode means the active harness has explicitly selected
|
|
195
|
+
`autonomousMode=true`: the agent can choose safe local defaults, record
|
|
196
|
+
`assumptions[]`, and continue without an external approval gate for ordinary
|
|
197
|
+
reversible ambiguity. Interactive mode remains available only when the caller
|
|
198
|
+
explicitly selects `autonomousMode=false`; the harness must not silently switch
|
|
199
|
+
between the two modes.
|
|
200
|
+
|
|
201
|
+
When a question is considered, record its source as exactly one of:
|
|
202
|
+
|
|
203
|
+
```text
|
|
204
|
+
USER_REQUIREMENT
|
|
205
|
+
FORGELOOP_BLOCKING_DECISION
|
|
206
|
+
EXTERNAL_WORKFLOW_POLICY
|
|
207
|
+
MODEL_PREFERENCE
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Only `USER_REQUIREMENT` and `FORGELOOP_BLOCKING_DECISION` authorize a question
|
|
211
|
+
in autonomous mode. `EXTERNAL_WORKFLOW_POLICY` and `MODEL_PREFERENCE` may be
|
|
212
|
+
recorded for diagnosis, but neither can authorize a question there. A genuine
|
|
213
|
+
`BLOCKING` ForgeLoop decision remains compatible with an external approval and
|
|
214
|
+
may produce a legitimate question with its persisted blocking reason.
|
|
215
|
+
|
|
216
|
+
The question-source invariant is:
|
|
217
|
+
|
|
218
|
+
```text
|
|
219
|
+
ASK_USER is allowed only when:
|
|
220
|
+
classification = BLOCKING
|
|
221
|
+
AND blockingReason is valid
|
|
222
|
+
AND the source is not EXTERNAL_WORKFLOW_POLICY alone
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Before asking, apply the external-workflow conflict check in addition to the
|
|
226
|
+
ordinary pre-question checklist:
|
|
227
|
+
|
|
228
|
+
1. Is the product decision `BLOCKING` under ForgeLoop?
|
|
229
|
+
2. If not, is the question required only by another workflow or skill?
|
|
230
|
+
3. If yes, do not ask in autonomous mode; record the incompatibility when
|
|
231
|
+
useful and continue through the safe reversible assumption path.
|
|
232
|
+
|
|
233
|
+
Examples of incompatible hard gates for an otherwise `NON_BLOCKING` decision
|
|
234
|
+
include: “ask before implementation”, “present two or three designs and
|
|
235
|
+
wait”, “receive explicit approval”, and “stop until the user reviews the
|
|
236
|
+
specification”. Planning, review, testing, and documentation remain useful
|
|
237
|
+
when they do not impose that interruption.
|
|
238
|
+
|
|
239
|
+
The compatibility distinction is explicit:
|
|
240
|
+
|
|
241
|
+
| External workflow behavior | Autonomous-mode result |
|
|
242
|
+
| --- | --- |
|
|
243
|
+
| Adds local planning without a user gate | Compatible; continue the ForgeLoop loop. |
|
|
244
|
+
| Adds a local review or checklist | Compatible; continue the ForgeLoop loop. |
|
|
245
|
+
| Adds deterministic tests | Compatible; continue the ForgeLoop loop. |
|
|
246
|
+
| Adds documentation generation | Compatible; continue the ForgeLoop loop. |
|
|
247
|
+
| Approval for a real `BLOCKING` decision | Compatible; a justified question is allowed. |
|
|
248
|
+
| Approval for every design choice | `INCOMPATIBLE WITH AUTONOMOUS MODE`; record `WORKFLOW_CONFLICT`, do not ask. |
|
|
249
|
+
| Approval before any implementation | `INCOMPATIBLE WITH AUTONOMOUS MODE` unless a real blocker exists. |
|
|
250
|
+
| Reclassifying a reversible local aesthetic choice as blocking | `INCOMPATIBLE WITH AUTONOMOUS MODE`; preserve `NON_BLOCKING`. |
|
|
251
|
+
| Spawning agents that change precedence | Not suitable for an isolated blind-conformance run; it does not change this contract. |
|
|
252
|
+
|
|
253
|
+
"Installed" and "compatible" are different claims. A harness can have an
|
|
254
|
+
external workflow installed and still be `INCOMPATIBLE WITH AUTONOMOUS MODE`.
|
|
255
|
+
Use that wording instead of calling the workflow broken. The deterministic
|
|
256
|
+
support helper in `src/core/workflow-compatibility.js` evaluates this boundary;
|
|
257
|
+
it does not modify `src/core/decision-classification.js`, invoke an LLM, or
|
|
258
|
+
redesign a runtime, arbiter, supervisor, or approval broker.
|
|
259
|
+
|
|
260
|
+
For the sixth blind conformance run, exclude mandatory-approval workflows at
|
|
261
|
+
the harness level rather than weakening the blind prompt. Record the harness
|
|
262
|
+
state before starting:
|
|
263
|
+
|
|
264
|
+
```text
|
|
265
|
+
mandatory-approval workflows enabled: NO
|
|
266
|
+
external brainstorming hard gate enabled: NO
|
|
267
|
+
external design approval gate enabled: NO
|
|
268
|
+
subagents enabled: NO
|
|
269
|
+
delegation enabled: NO
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
If the harness cannot disable a mandatory approval workflow, record
|
|
273
|
+
`TEST_NOT_STARTED` and do not claim a conformance result.
|
|
274
|
+
|
|
167
275
|
## Serialized protocol preparation
|
|
168
276
|
|
|
169
277
|
ForgeLoop keeps the agent responsible for implementation while making the
|
package/QUALITY_SCORECARD.md
CHANGED
|
@@ -18,6 +18,9 @@ policy are all present.
|
|
|
18
18
|
| Agent lifecycle navigation | Read-only `forgeloop next` decisions, stable action/reason output, persisted-state safety, and adapter guidance at lifecycle boundaries. |
|
|
19
19
|
| Execution → Verification handoff | Legal `EXECUTING` → `VERIFYING` transition, implementation-step reconciliation, and preservation of verification evidence. |
|
|
20
20
|
| Pre-contract autonomy — structural | Blocking vs Non-Blocking Decisions policy, classify-before-ask invariant, PRE-QUESTION CHECK, explicit ASSUMPTION / source=agent-default recording, contract-before-clarification ordering, deterministic reason-code helper, and positive/negative tests. |
|
|
21
|
+
| External workflow compatibility — structural | Explicit autonomous-mode precedence, `WORKFLOW_CONFLICT` recording, question-source attribution, installed-versus-compatible wording, and mandatory-approval harness isolation. |
|
|
22
|
+
| Instruction-conflict handling — structural | External workflow policy is attributed separately from user requirements and ForgeLoop blocking decisions, with deterministic conflict reason codes and no fake unresolved user blocker. |
|
|
23
|
+
| Autonomous-mode precedence — structural | Explicit `autonomousMode=true` boundary, explicit interactive opt-in, preservation of `NON_BLOCKING`, and no silent workflow-induced mode switch. |
|
|
21
24
|
| Pre-contract autonomy — cross-agent live robustness | Independent live-agent behavior across fresh package installs, exact blind prompts, one-process/no-subagent topology, and separate evidence for non-blocking continuation versus blocking clarification. Structural coverage does not imply live cross-agent robustness. |
|
|
22
25
|
| Resume/checkpoint | Atomic local state, contract/HEAD/artifact freshness, age warning, schema/secret validation, status, safe validation, and bounded clearing without persisting derived freshness fields. |
|
|
23
26
|
| Multi-agent coordination | Self-contained briefs, write/write and write/read ownership checks, dependency-set validation, reviewer independence, normalized results, and inline fallback. |
|
|
@@ -42,8 +45,11 @@ policy are all present.
|
|
|
42
45
|
|
|
43
46
|
| Dimension | Classification |
|
|
44
47
|
| --- | --- |
|
|
45
|
-
| Pre-contract autonomy — structural | IMPLEMENTED / LOCAL TESTS PASS —
|
|
46
|
-
|
|
|
48
|
+
| Pre-contract autonomy — structural | IMPLEMENTED / LOCAL TESTS PASS — 377 Node tests and 42 Python tests, with focused autonomy/conformance checks green |
|
|
49
|
+
| External workflow compatibility — structural | IMPLEMENTED / LOCAL TESTS PASS — deterministic helper covers autonomous conflict, compatible non-blocking flow, legitimate blocking questions, explicit interactive mode, and question-source vocabulary |
|
|
50
|
+
| Instruction-conflict handling — structural | IMPLEMENTED / LOCAL TESTS PASS — workflow-policy conflicts stay outside `unresolvedDecisions[]` and expose stable external-workflow reason codes |
|
|
51
|
+
| Autonomous-mode precedence — structural | IMPLEMENTED / LOCAL TESTS PASS — autonomous mode is explicit, interactive mode is explicit, and `NON_BLOCKING` is never promoted by workflow policy |
|
|
52
|
+
| Pre-contract autonomy — cross-agent live robustness | NOT_PROVEN — the fifth blind run is `PARTIAL` on published `0.1.4` and the sixth run requires harness-level exclusion of mandatory-approval workflows before it can start |
|
|
47
53
|
| Execution → Verification | REPRODUCED FAILURE in fourth blind run before implementation |
|
|
48
54
|
| Verification serialization | NOT_REACHED in fourth blind run |
|
|
49
55
|
| Review transition | NOT_REACHED in fourth blind run |
|
|
@@ -66,8 +72,11 @@ are both present:
|
|
|
66
72
|
| Security boundary | realpath containment, bounded JSON, `THREAT_MODEL.md`, secret-free artifacts, authority and no-runtime rules | `tests/security-limits.test.js`, Markdown/loop validators, and `scripts/scan_secrets.py` |
|
|
67
73
|
| Cross-artifact conformance | `src/core/conformance.js`, `classifyLoadedWorkState`, and `forgeloop validate-protocol --contract-file` | `tests/conformance.test.js`, `tests/validate-protocol-cli.test.js`, and protocol fixtures covering precedence and stale evidence |
|
|
68
74
|
| Protocol preparation and completion | `src/core/preflight.js`, `src/core/completion.js`, `src/core/events.js`, policy packs, and portable bundles | `tests/preflight.test.js`, `tests/completion.test.js`, `tests/lifecycle.test.js`, `tests/policy.test.js`, and `tests/bundle.test.js` |
|
|
69
|
-
| Pre-contract autonomy — structural | `LOOP_ENGINEERING.md`, `src/core/decision-classification.js`, `CLAUDE.md`, `AGENTS.md`, `.github/copilot-instructions.md`, `.cursor/rules/project-loop.mdc` | `tests/decision-classification.test.js`, `tests/autonomy-policy.test.js`, `tests/preflight.test.js` |
|
|
70
|
-
|
|
|
75
|
+
| Pre-contract autonomy — structural | `LOOP_ENGINEERING.md`, `src/core/decision-classification.js`, `src/core/workflow-compatibility.js`, `CLAUDE.md`, `AGENTS.md`, `.github/copilot-instructions.md`, `.cursor/rules/project-loop.mdc` | `tests/decision-classification.test.js`, `tests/workflow-compatibility.test.js`, `tests/autonomy-policy.test.js`, `tests/preflight.test.js` |
|
|
76
|
+
| External workflow compatibility — structural | `LOOP_ENGINEERING.md`, `AGENT_COMPATIBILITY.md`, `src/core/workflow-compatibility.js`, and sixth-run harness metadata rule | `tests/workflow-compatibility.test.js`, `conformance/README.md` |
|
|
77
|
+
| Instruction-conflict handling — structural | Canonical source-attribution and `WORKFLOW_CONFLICT` policy in `LOOP_ENGINEERING.md` plus adapter references | `tests/autonomy-policy.test.js`, `tests/workflow-compatibility.test.js` |
|
|
78
|
+
| Autonomous-mode precedence — structural | Autonomous/interactive mode contract and harness exclusion metadata | `tests/workflow-compatibility.test.js`, `tests/conformance-scenarios.test.js` |
|
|
79
|
+
| Pre-contract autonomy — cross-agent live robustness | Prior third blind-run result, `conformance/runs/2026-08-13-codex-fourth-live.md`, preserved fifth-run report `conformance/runs/2026-08-13-codex-fifth-live.md`, and the exact blind request | `tests/conformance-scenarios.test.js`; sixth run is not started until mandatory approval is excluded |
|
|
71
80
|
|
|
72
81
|
The implementation references above are local observations. OS runners,
|
|
73
82
|
remote links, provider sessions, publication, and deployment remain `Not
|
package/conformance/README.md
CHANGED
|
@@ -45,3 +45,31 @@ history.
|
|
|
45
45
|
|
|
46
46
|
The complete-website scenario deliberately fails when implementation starts
|
|
47
47
|
before the contract, route, and required gates exist.
|
|
48
|
+
|
|
49
|
+
## Autonomous blind-run isolation
|
|
50
|
+
|
|
51
|
+
External workflows may help with local planning, review, tests, or
|
|
52
|
+
documentation, but a mandatory approval policy for a ForgeLoop `NON_BLOCKING`
|
|
53
|
+
decision is `INCOMPATIBLE WITH AUTONOMOUS MODE`. The harness must exclude that
|
|
54
|
+
policy before the blind prompt starts; do not add a hint to the prompt that
|
|
55
|
+
changes the scenario. `NON_BLOCKING` must remain non-blocking, and any
|
|
56
|
+
compatibility conflict is recorded as `WORKFLOW_CONFLICT`, not as a fake user
|
|
57
|
+
blocker.
|
|
58
|
+
|
|
59
|
+
For the sixth blind run, record these values before sending the unchanged blind
|
|
60
|
+
prompt:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
mandatory-approval workflows enabled: NO
|
|
64
|
+
external brainstorming hard gate enabled: NO
|
|
65
|
+
external design approval gate enabled: NO
|
|
66
|
+
subagents enabled: NO
|
|
67
|
+
delegation enabled: NO
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Also record the available and invoked external workflows, explicit autonomy
|
|
71
|
+
mode, process count, subagent count, and delegation status. If the harness
|
|
72
|
+
cannot disable a mandatory approval workflow, record `TEST_NOT_STARTED` and do
|
|
73
|
+
not interpret the run as a conformance failure or success. An installed
|
|
74
|
+
workflow and a compatible workflow are separate claims; use
|
|
75
|
+
`INCOMPATIBLE WITH AUTONOMOUS MODE`, not "broken", for the former.
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
# ForgeLoop Fifth Blind Live Conformance Run
|
|
2
|
+
|
|
3
|
+
This record documents the fifth blind live conformance experiment. The target
|
|
4
|
+
was disposable, initialized from the published npm package only, and was not
|
|
5
|
+
populated from the ForgeLoop working tree. The experiment used one primary
|
|
6
|
+
agent and stopped when the agent requested approval for a reversible product
|
|
7
|
+
design before creating a serialized contract.
|
|
8
|
+
|
|
9
|
+
## Environment
|
|
10
|
+
|
|
11
|
+
- ForgeLoop release source commit: `550bec7911a48734bc63148539c439308a6cf6f4`
|
|
12
|
+
- Approved merged `main` commit: `550bec7911a48734bc63148539c439308a6cf6f4`
|
|
13
|
+
- ForgeLoop package version: `@cassiomc1/forgeloop@0.1.4`
|
|
14
|
+
- npm tarball URL: `https://registry.npmjs.org/@cassiomc1/forgeloop/-/forgeloop-0.1.4.tgz`
|
|
15
|
+
- Tarball SHA-1: `966506b18dbb797949e397f39ba987dff7077283`
|
|
16
|
+
- npm integrity SHA-512:
|
|
17
|
+
`sha512-qBVhtToBbhN1Yrke85WTaG6rl4dAN117QiUx2EN75bp/Hn5ZXxIkTn7U5ml4j//JYjWqABDtCMh2VuJ9FOtcfQ==`
|
|
18
|
+
- Agent: Codex CLI non-interactive agent
|
|
19
|
+
- Model: `gpt-5.6-luna` (configured harness model)
|
|
20
|
+
- Harness: `codex-cli 0.146.0`, `codex exec`
|
|
21
|
+
- Operating system: macOS `26.6.1`, `arm64`
|
|
22
|
+
- Date/time: `2026-08-13T09:28:53-03:00` target registration; agent session
|
|
23
|
+
started at `2026-08-13T09:29:44-03:00`
|
|
24
|
+
- Reported at: `2026-08-13T09:34:31-03:00`
|
|
25
|
+
- Target path: `/Users/cassio/Documents/github/forgeloop-fifth-blind-live.f39dWl`
|
|
26
|
+
- Conformance mode: Standard
|
|
27
|
+
- Installation procedure: created a new target with zero entries; fetched
|
|
28
|
+
`@cassiomc1/forgeloop@0.1.4` from npm into an external runtime with
|
|
29
|
+
`npm pack`; verified the tarball SHA-1 and SHA-512 against npm metadata;
|
|
30
|
+
installed that exact tarball with
|
|
31
|
+
`npm install --prefix <runtime> --no-save --ignore-scripts <tarball>`;
|
|
32
|
+
confirmed the installed package and CLI reported `0.1.4`; initialized the
|
|
33
|
+
target with the installed CLI using `node <runtime>/node_modules/@cassiomc1/forgeloop/src/cli.js init --path <target>`.
|
|
34
|
+
- The target was not copied from the ForgeLoop checkout and no unpublished
|
|
35
|
+
ForgeLoop files were used to supplement the package.
|
|
36
|
+
|
|
37
|
+
Execution topology: single-agent
|
|
38
|
+
Agent process count: 1
|
|
39
|
+
Subagents enabled: NO
|
|
40
|
+
Delegation used: NO
|
|
41
|
+
Parallel agents: NO
|
|
42
|
+
Planner/worker split: NO
|
|
43
|
+
Reviewer subagent: NO
|
|
44
|
+
|
|
45
|
+
The harness configuration was overridden for this invocation with
|
|
46
|
+
`--disable multi_agent` and `agents.enabled=false`. The observable session
|
|
47
|
+
ledger contains one `thread.started` event and no additional agent thread.
|
|
48
|
+
|
|
49
|
+
## Blind prompt verification
|
|
50
|
+
|
|
51
|
+
The exact prompt sent to the agent was:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
Create a premium website for a law firm.
|
|
55
|
+
|
|
56
|
+
It should feel modern, sophisticated and trustworthy, work well on mobile and desktop, and include a contact form.
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The prompt contained no instruction about ForgeLoop, Loop Engineering,
|
|
60
|
+
classification, assumptions, contracts, routing, gates, preflight, lifecycle,
|
|
61
|
+
phases, `forgeloop next`, verification, evidence, receipts, review,
|
|
62
|
+
completion, continuation, or subagents.
|
|
63
|
+
|
|
64
|
+
- Blind prompt purity: `PASS`
|
|
65
|
+
|
|
66
|
+
## Blind bootstrap and instruction discovery
|
|
67
|
+
|
|
68
|
+
The agent's first observable message stated that it would apply the repository
|
|
69
|
+
loop and inspect local instructions. The command log shows reads of:
|
|
70
|
+
|
|
71
|
+
- `LOOP_ENGINEERING.md`;
|
|
72
|
+
- `PROJECT_PROFILE.md`;
|
|
73
|
+
- `GUIDE_ROUTER.md`;
|
|
74
|
+
- `AGENTS.md`;
|
|
75
|
+
- `CLAUDE.md`;
|
|
76
|
+
- `.forgeloop/manifest.json` and the installed package state;
|
|
77
|
+
- `.github/copilot-instructions.md` and `.cursor/rules/project-loop.mdc`;
|
|
78
|
+
- `ENG/perf-code-eng.md`;
|
|
79
|
+
- `ENG/test-code-eng.md`;
|
|
80
|
+
- `ENG/clean-code-eng.md`;
|
|
81
|
+
- `ENG/sec-code-eng.md`;
|
|
82
|
+
- `ENG/premium-sites-studio-eng.md`;
|
|
83
|
+
- `ENG/design-code-eng.md`;
|
|
84
|
+
- `ENG/accessibility-eng.md`.
|
|
85
|
+
|
|
86
|
+
The agent identified the applicable guide IDs in an observable message as
|
|
87
|
+
`premium`, `design`, `accessibility`, `clean`, `test`, `security`, and
|
|
88
|
+
`performance`. This was discovered from the installed project context and was
|
|
89
|
+
not supplied in the blind prompt.
|
|
90
|
+
|
|
91
|
+
- Blind bootstrap: `PASS`
|
|
92
|
+
- Instruction discovery: `PASS`
|
|
93
|
+
|
|
94
|
+
The first observable agent message also said that it would use brainstorming,
|
|
95
|
+
site-building, and verification skills. The session stopped before product
|
|
96
|
+
implementation; no product file was created.
|
|
97
|
+
|
|
98
|
+
## Pre-question autonomy
|
|
99
|
+
|
|
100
|
+
This was the first critical area of the fifth test. The agent recognized that
|
|
101
|
+
the request did not provide a firm identity, contacts, location, attorneys,
|
|
102
|
+
results, or visual identity. It proposed safe-looking local placeholders and a
|
|
103
|
+
fictional concept, including the provisional name `Aureum Legal`, but did not
|
|
104
|
+
serialize those choices as assumptions.
|
|
105
|
+
|
|
106
|
+
The agent then presented three reversible visual directions and asked for
|
|
107
|
+
approval. The final question was:
|
|
108
|
+
|
|
109
|
+
> Aprova esse design para eu escrever a especificação e implementar o site?
|
|
110
|
+
|
|
111
|
+
The requested approval concerned a reversible local design direction. No real
|
|
112
|
+
business fact, sensitive value, external authority, irreversible decision,
|
|
113
|
+
regulated claim, or destructive action was required by the prompt. No
|
|
114
|
+
`current-contract.json` existed before the question.
|
|
115
|
+
|
|
116
|
+
- Decision classification before asking: `FAIL`
|
|
117
|
+
- Non-blocking continuation: `FAIL`
|
|
118
|
+
- Pre-question autonomy: `FAIL`
|
|
119
|
+
- Question authorization: `FAIL`
|
|
120
|
+
|
|
121
|
+
The agent's observable description that it considered real firm identity,
|
|
122
|
+
contacts, and allegations blocking did not produce a persisted blocker or a
|
|
123
|
+
contract, and the question actually asked for approval of a reversible design.
|
|
124
|
+
|
|
125
|
+
## Contract-before-clarification
|
|
126
|
+
|
|
127
|
+
The target had no `.forgeloop/current-contract.json` when the agent asked its
|
|
128
|
+
question. Consequently there was no serialized `assumptions[]`, no
|
|
129
|
+
`unresolvedDecisions[]`, and no contract fingerprint to inspect.
|
|
130
|
+
|
|
131
|
+
- Contract creation: `FAIL`
|
|
132
|
+
- Assumption serialization: `FAIL`
|
|
133
|
+
- Contract-before-clarification: `FAIL`
|
|
134
|
+
|
|
135
|
+
The agent described placeholders as reversible in its message, but prose is
|
|
136
|
+
not serialized contract evidence and did not authorize the clarification stop.
|
|
137
|
+
|
|
138
|
+
## Routing and gates
|
|
139
|
+
|
|
140
|
+
The agent named the seven applicable guide IDs in its message, but it did not
|
|
141
|
+
persist `.forgeloop/routing-result.json` or any files under `.forgeloop/gates/`.
|
|
142
|
+
No deterministic route or gate artifact was available for independent
|
|
143
|
+
inspection.
|
|
144
|
+
|
|
145
|
+
- Deterministic routing: `NOT_REACHED`
|
|
146
|
+
- Gate enforcement: `NOT_REACHED`
|
|
147
|
+
|
|
148
|
+
## Preflight chronology
|
|
149
|
+
|
|
150
|
+
The target contained no `.forgeloop/preflight.json` and no
|
|
151
|
+
`.forgeloop/events.ndjson`. There was no `PREFLIGHT_READY`, `EXECUTION_STARTED`,
|
|
152
|
+
task identity, route identity, contract fingerprint, or persisted assessment
|
|
153
|
+
of unresolved blocking decisions.
|
|
154
|
+
|
|
155
|
+
- Preflight chronology: `NOT_REACHED`
|
|
156
|
+
|
|
157
|
+
The required ordering could not be exercised because the agent stopped before
|
|
158
|
+
contract persistence.
|
|
159
|
+
|
|
160
|
+
## Implementation
|
|
161
|
+
|
|
162
|
+
No product files were created. The target contains only files installed by
|
|
163
|
+
ForgeLoop `init`; it has no HTML, CSS, JavaScript, or other product source
|
|
164
|
+
files. The premium appearance, modern/sophisticated/trustworthy positioning,
|
|
165
|
+
responsive mobile/desktop behavior, and contact form were therefore not
|
|
166
|
+
exercised.
|
|
167
|
+
|
|
168
|
+
- Implementation: `NOT_REACHED`
|
|
169
|
+
- Task success: `FAIL`
|
|
170
|
+
|
|
171
|
+
## Lifecycle navigation
|
|
172
|
+
|
|
173
|
+
The agent did not implement the product and did not execute `forgeloop next` as
|
|
174
|
+
part of its session. The independent post-run `next --path <target> --json`
|
|
175
|
+
inspection returned:
|
|
176
|
+
|
|
177
|
+
```json
|
|
178
|
+
{
|
|
179
|
+
"currentPhase": "RECEIVED",
|
|
180
|
+
"nextAction": "DISCOVER",
|
|
181
|
+
"terminal": false,
|
|
182
|
+
"reasonCodes": ["WORK_STATE_ABSENT"]
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
- Agent lifecycle navigation: `NOT_REACHED`
|
|
187
|
+
- Execution → Verification handoff: `NOT_REACHED`
|
|
188
|
+
- Implementation reconciliation: `NOT_REACHED`
|
|
189
|
+
|
|
190
|
+
## Receipt preparation
|
|
191
|
+
|
|
192
|
+
The agent never reached `VERIFYING`, did not run `prepare-completion`, and did
|
|
193
|
+
not create an in-progress execution receipt.
|
|
194
|
+
|
|
195
|
+
- Receipt preparation: `NOT_REACHED`
|
|
196
|
+
|
|
197
|
+
## Real verification execution
|
|
198
|
+
|
|
199
|
+
The agent executed no product checks. There was no syntax check, build,
|
|
200
|
+
accessibility check, security check, performance check, responsive check, or
|
|
201
|
+
contact-form check performed by the agent.
|
|
202
|
+
|
|
203
|
+
- Verification execution: `NOT_REACHED`
|
|
204
|
+
|
|
205
|
+
## Future-result fabrication prevention
|
|
206
|
+
|
|
207
|
+
The agent stopped before a verification `next` response or any check
|
|
208
|
+
requirement. No future result was serialized as `passed`, `OBSERVED`, exit code
|
|
209
|
+
`0`, or equivalent fabricated evidence.
|
|
210
|
+
|
|
211
|
+
- Future-result fabrication prevention: `NOT_REACHED`
|
|
212
|
+
|
|
213
|
+
This capability was not exercised; absence of fabricated evidence is not a
|
|
214
|
+
successful verification run.
|
|
215
|
+
|
|
216
|
+
## Evidence chronology
|
|
217
|
+
|
|
218
|
+
There was no `record-check` invocation and no `VERIFICATION_RECORDED` event.
|
|
219
|
+
There is therefore no real-command → real-result → record-check chronology to
|
|
220
|
+
validate.
|
|
221
|
+
|
|
222
|
+
- Evidence chronology: `NOT_REACHED`
|
|
223
|
+
|
|
224
|
+
## Evidence serialization
|
|
225
|
+
|
|
226
|
+
The target has no `work-state.json`, `verificationEvidence`,
|
|
227
|
+
`evidenceCoverage`, execution receipt, structured checks, or
|
|
228
|
+
`VERIFICATION_RECORDED` events.
|
|
229
|
+
|
|
230
|
+
- Evidence serialization: `NOT_REACHED`
|
|
231
|
+
- Evidence integrity: `NOT_REACHED`
|
|
232
|
+
|
|
233
|
+
## Failure loop
|
|
234
|
+
|
|
235
|
+
No project check failed because no project check ran. The observed failure was
|
|
236
|
+
a pre-contract clarification stop, not a verification failure.
|
|
237
|
+
|
|
238
|
+
- Failure loop: `NOT_EXERCISED`
|
|
239
|
+
|
|
240
|
+
## Review transition
|
|
241
|
+
|
|
242
|
+
The agent did not reach verification or review, and no evidence coverage was
|
|
243
|
+
available to authorize `ENTER_REVIEWING`.
|
|
244
|
+
|
|
245
|
+
- Review transition: `NOT_REACHED`
|
|
246
|
+
|
|
247
|
+
## Completion
|
|
248
|
+
|
|
249
|
+
The agent did not run `forgeloop complete` and did not produce a
|
|
250
|
+
validator-backed completion. The independent command returned `REJECTED`.
|
|
251
|
+
|
|
252
|
+
- Completion validation: `NOT_REACHED`
|
|
253
|
+
- Lifecycle closure: `NOT_REACHED`
|
|
254
|
+
|
|
255
|
+
## False-completion prevention
|
|
256
|
+
|
|
257
|
+
The independent validator rejected completion rather than accepting the
|
|
258
|
+
incomplete target. The observed rejection included:
|
|
259
|
+
|
|
260
|
+
- `E_CONTRACT_MISSING`;
|
|
261
|
+
- `E_RECEIPT_MISSING`;
|
|
262
|
+
- `E_ROUTE_MISSING`;
|
|
263
|
+
- `E_STATE_MISSING`.
|
|
264
|
+
|
|
265
|
+
`validate-protocol` independently returned `INVALID` because the route, state,
|
|
266
|
+
and receipt artifacts were missing.
|
|
267
|
+
|
|
268
|
+
- False-completion prevention: `PASS`
|
|
269
|
+
|
|
270
|
+
## Chronology
|
|
271
|
+
|
|
272
|
+
The persisted event ledger was absent, so the required protocol sequence was
|
|
273
|
+
never recorded.
|
|
274
|
+
|
|
275
|
+
| Seq | Event | Timestamp | Task ID |
|
|
276
|
+
| ---: | --- | --- | --- |
|
|
277
|
+
| — | No `events.ndjson` persisted | — | — |
|
|
278
|
+
|
|
279
|
+
The following required events were absent: `TASK_RECEIVED`,
|
|
280
|
+
`CONTRACT_VALIDATED`, `ROUTE_VALIDATED`, `GATE_SATISFIED`, `PREFLIGHT_READY`,
|
|
281
|
+
`EXECUTION_STARTED`, `VERIFICATION_STARTED`, `VERIFICATION_RECORDED`, and
|
|
282
|
+
`COMPLETION_VALIDATED`. Hash-chain validity: `NOT_VERIFIED` because no ledger
|
|
283
|
+
was created.
|
|
284
|
+
|
|
285
|
+
## Artifact evidence
|
|
286
|
+
|
|
287
|
+
| Artifact | Observation |
|
|
288
|
+
| --- | --- |
|
|
289
|
+
| `.forgeloop/current-contract.json` | Missing |
|
|
290
|
+
| `.forgeloop/routing-result.json` | Missing |
|
|
291
|
+
| `.forgeloop/gates/` | Missing |
|
|
292
|
+
| `.forgeloop/preflight.json` | Missing |
|
|
293
|
+
| `.forgeloop/work-state.json` | Missing |
|
|
294
|
+
| `.forgeloop/events.ndjson` | Missing |
|
|
295
|
+
| Structured checks/evidence | Missing |
|
|
296
|
+
| `.forgeloop/execution-receipt.json` | Missing |
|
|
297
|
+
| `.forgeloop/manifest.json` | Present; package version `0.1.4` |
|
|
298
|
+
| Product implementation | No product files |
|
|
299
|
+
|
|
300
|
+
The installed package and CLI were independently verified before the agent
|
|
301
|
+
started:
|
|
302
|
+
|
|
303
|
+
- installed package version: `0.1.4`;
|
|
304
|
+
- CLI version: `0.1.4`;
|
|
305
|
+
- target initialization: completed through the published CLI;
|
|
306
|
+
- local tarball SHA-1: `966506b18dbb797949e397f39ba987dff7077283`;
|
|
307
|
+
- registry tarball SHA-1 source: matching npm tarball;
|
|
308
|
+
- local SHA-512 integrity: matching the registry integrity value.
|
|
309
|
+
|
|
310
|
+
Independent validator commands, all run against the disposable target after
|
|
311
|
+
the agent exited:
|
|
312
|
+
|
|
313
|
+
- `forgeloop next --path <target> --json`: exit `0`, phase `RECEIVED`, next
|
|
314
|
+
action `DISCOVER`, reason `WORK_STATE_ABSENT`.
|
|
315
|
+
- `forgeloop audit --path <target> --json`: exit `1`, status `INVALID`, with
|
|
316
|
+
missing contract, receipt, route, and state artifacts.
|
|
317
|
+
- `forgeloop validate-protocol --path <target> --json`: exit `1`, status
|
|
318
|
+
`INVALID`, with missing receipt, route, and state artifacts.
|
|
319
|
+
- `forgeloop complete --path <target> --json`: exit `1`, status `REJECTED`,
|
|
320
|
+
task status `INCOMPLETE`, verification status `invalid`.
|
|
321
|
+
|
|
322
|
+
No target artifact was edited after the agent exited to make a validator pass.
|
|
323
|
+
|
|
324
|
+
## Capability results
|
|
325
|
+
|
|
326
|
+
| Capability | Result |
|
|
327
|
+
| --- | --- |
|
|
328
|
+
| Experiment isolation | `PASS` |
|
|
329
|
+
| Blind prompt purity | `PASS` |
|
|
330
|
+
| Blind bootstrap | `PASS` |
|
|
331
|
+
| Instruction discovery | `PASS` |
|
|
332
|
+
| Decision classification before asking | `FAIL` |
|
|
333
|
+
| Non-blocking continuation | `FAIL` |
|
|
334
|
+
| Pre-question autonomy | `FAIL` |
|
|
335
|
+
| Contract creation | `FAIL` |
|
|
336
|
+
| Assumption serialization | `FAIL` |
|
|
337
|
+
| Contract-before-clarification | `FAIL` |
|
|
338
|
+
| Question authorization | `FAIL` |
|
|
339
|
+
| Deterministic routing | `NOT_REACHED` |
|
|
340
|
+
| Gate enforcement | `NOT_REACHED` |
|
|
341
|
+
| Preflight chronology | `NOT_REACHED` |
|
|
342
|
+
| Implementation | `NOT_REACHED` |
|
|
343
|
+
| Agent lifecycle navigation | `NOT_REACHED` |
|
|
344
|
+
| Execution → Verification handoff | `NOT_REACHED` |
|
|
345
|
+
| Receipt preparation | `NOT_REACHED` |
|
|
346
|
+
| Verification execution | `NOT_REACHED` |
|
|
347
|
+
| Future-result fabrication prevention | `NOT_REACHED` |
|
|
348
|
+
| Evidence chronology | `NOT_REACHED` |
|
|
349
|
+
| Evidence serialization | `NOT_REACHED` |
|
|
350
|
+
| Evidence integrity | `NOT_REACHED` |
|
|
351
|
+
| Failure loop | `NOT_EXERCISED` |
|
|
352
|
+
| Review transition | `NOT_REACHED` |
|
|
353
|
+
| Completion validation | `NOT_REACHED` |
|
|
354
|
+
| Lifecycle closure | `NOT_REACHED` |
|
|
355
|
+
| False-completion prevention | `PASS` |
|
|
356
|
+
| Full conformance | `PARTIAL` |
|
|
357
|
+
|
|
358
|
+
## Independent outcome dimensions
|
|
359
|
+
|
|
360
|
+
- Task success: `FAIL`
|
|
361
|
+
- Protocol conformance: `PARTIAL`
|
|
362
|
+
- Verification validity: `INVALID`
|
|
363
|
+
- Publication: `NOT_PUBLISHED` for the target deliverable; the ForgeLoop
|
|
364
|
+
package used by the experiment was already `PUBLISHED` as `0.1.4`.
|
|
365
|
+
- Production readiness: `NOT_VERIFIED`
|
|
366
|
+
|
|
367
|
+
## Final classification
|
|
368
|
+
|
|
369
|
+
`PARTIAL`
|
|
370
|
+
|
|
371
|
+
The run verified single-agent isolation, blind prompt purity, automatic
|
|
372
|
+
bootstrap, instruction discovery, and validator rejection of false
|
|
373
|
+
completion. It did not reach protocol execution because the agent requested
|
|
374
|
+
approval for a reversible local design direction before persisting
|
|
375
|
+
`current-contract.json` and recording the choice in `assumptions[]`.
|
|
376
|
+
|
|
377
|
+
The first divergence was the approval question before contract creation. The
|
|
378
|
+
last capability passed before that divergence was instruction discovery. The
|
|
379
|
+
last valid persisted artifact was the npm-installed `.forgeloop/manifest.json`;
|
|
380
|
+
no protocol event was validly persisted. The first capability not reached was
|
|
381
|
+
contract-backed protocol preparation, beginning with contract creation and
|
|
382
|
+
deterministic routing. The smallest failure class is `CONTRACT_FAILURE`.
|
|
383
|
+
|
|
384
|
+
EVIDENCE
|
|
385
|
+
→ CLASSIFICATION
|
|
386
|
+
→ SMALLEST FAILURE CLASS
|
package/package.json
CHANGED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { canAskUser } from "./decision-classification.js";
|
|
2
|
+
|
|
3
|
+
export const QUESTION_SOURCES = Object.freeze([
|
|
4
|
+
"USER_REQUIREMENT",
|
|
5
|
+
"FORGELOOP_BLOCKING_DECISION",
|
|
6
|
+
"EXTERNAL_WORKFLOW_POLICY",
|
|
7
|
+
"MODEL_PREFERENCE",
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
export const EXTERNAL_WORKFLOW_REASON_CODES = Object.freeze({
|
|
11
|
+
APPROVAL_CONFLICT: "E_EXTERNAL_WORKFLOW_APPROVAL_CONFLICT",
|
|
12
|
+
BLOCKS_NON_BLOCKING: "E_EXTERNAL_WORKFLOW_BLOCKS_NON_BLOCKING",
|
|
13
|
+
REQUIRES_USER_GATE: "E_EXTERNAL_WORKFLOW_REQUIRES_USER_GATE",
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const DECISION_CLASSIFICATIONS = new Set(["NON_BLOCKING", "BLOCKING"]);
|
|
17
|
+
|
|
18
|
+
function normalizeDecision(value) {
|
|
19
|
+
if (typeof value === "string") {
|
|
20
|
+
if (!DECISION_CLASSIFICATIONS.has(value)) {
|
|
21
|
+
throw new TypeError(`forgeLoopDecision classification is invalid: ${value}`);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
classification: value,
|
|
25
|
+
reasonCode: value === "NON_BLOCKING" ? "SAFE_REVERSIBLE_LOCAL_DEFAULT" : null,
|
|
26
|
+
blockingReason: null,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
30
|
+
throw new TypeError("forgeLoopDecision must be a decision object or classification");
|
|
31
|
+
}
|
|
32
|
+
if (!DECISION_CLASSIFICATIONS.has(value.classification)) {
|
|
33
|
+
throw new TypeError(`forgeLoopDecision classification is invalid: ${value.classification}`);
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
classification: value.classification,
|
|
37
|
+
reasonCode: value.reasonCode ?? null,
|
|
38
|
+
blockingReason: value.blockingReason ?? null,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function assertBoolean(value, label) {
|
|
43
|
+
if (typeof value !== "boolean") throw new TypeError(`${label} must be a boolean`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function workflowName(value) {
|
|
47
|
+
if (value === undefined) return "external-workflow";
|
|
48
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
49
|
+
throw new TypeError("workflowName must be a non-empty string");
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function compatibleResult({ decision, name, autonomousMode, requiresUserApproval }) {
|
|
55
|
+
return {
|
|
56
|
+
status: "COMPATIBLE",
|
|
57
|
+
compatible: true,
|
|
58
|
+
autonomousMode,
|
|
59
|
+
workflowName: name,
|
|
60
|
+
forgeLoopClassification: decision.classification,
|
|
61
|
+
requiresUserApproval,
|
|
62
|
+
questionSource: null,
|
|
63
|
+
canAskUser: false,
|
|
64
|
+
requiresUserDecision: false,
|
|
65
|
+
recordAs: null,
|
|
66
|
+
addsUnresolvedDecision: false,
|
|
67
|
+
reasonCodes: [],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Evaluates an external workflow policy after ForgeLoop classifies the decision.
|
|
73
|
+
* The helper records a policy conflict instead of turning a reversible local
|
|
74
|
+
* default into a fake user blocker or mutating the decision classifier.
|
|
75
|
+
*/
|
|
76
|
+
export function classifyWorkflowCompatibility({
|
|
77
|
+
forgeLoopDecision,
|
|
78
|
+
workflowName: requestedWorkflowName,
|
|
79
|
+
requiresUserApproval = false,
|
|
80
|
+
autonomousMode,
|
|
81
|
+
} = {}) {
|
|
82
|
+
assertBoolean(autonomousMode, "autonomousMode");
|
|
83
|
+
assertBoolean(requiresUserApproval, "requiresUserApproval");
|
|
84
|
+
|
|
85
|
+
const decision = normalizeDecision(forgeLoopDecision);
|
|
86
|
+
const name = workflowName(requestedWorkflowName);
|
|
87
|
+
|
|
88
|
+
if (!requiresUserApproval) {
|
|
89
|
+
return compatibleResult({
|
|
90
|
+
decision,
|
|
91
|
+
name,
|
|
92
|
+
autonomousMode,
|
|
93
|
+
requiresUserApproval,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (decision.classification === "NON_BLOCKING") {
|
|
98
|
+
if (!autonomousMode) {
|
|
99
|
+
return {
|
|
100
|
+
status: "INTERACTIVE_APPROVAL",
|
|
101
|
+
compatible: true,
|
|
102
|
+
autonomousMode,
|
|
103
|
+
workflowName: name,
|
|
104
|
+
forgeLoopClassification: decision.classification,
|
|
105
|
+
requiresUserApproval,
|
|
106
|
+
questionSource: "EXTERNAL_WORKFLOW_POLICY",
|
|
107
|
+
canAskUser: true,
|
|
108
|
+
requiresUserDecision: true,
|
|
109
|
+
recordAs: null,
|
|
110
|
+
addsUnresolvedDecision: true,
|
|
111
|
+
reasonCodes: [EXTERNAL_WORKFLOW_REASON_CODES.REQUIRES_USER_GATE],
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
status: "WORKFLOW_CONFLICT",
|
|
117
|
+
compatible: false,
|
|
118
|
+
autonomousMode,
|
|
119
|
+
workflowName: name,
|
|
120
|
+
forgeLoopClassification: decision.classification,
|
|
121
|
+
requiresUserApproval,
|
|
122
|
+
questionSource: "EXTERNAL_WORKFLOW_POLICY",
|
|
123
|
+
canAskUser: false,
|
|
124
|
+
requiresUserDecision: false,
|
|
125
|
+
recordAs: "WORKFLOW_CONFLICT",
|
|
126
|
+
addsUnresolvedDecision: false,
|
|
127
|
+
reasonCodes: [
|
|
128
|
+
EXTERNAL_WORKFLOW_REASON_CODES.APPROVAL_CONFLICT,
|
|
129
|
+
EXTERNAL_WORKFLOW_REASON_CODES.BLOCKS_NON_BLOCKING,
|
|
130
|
+
EXTERNAL_WORKFLOW_REASON_CODES.REQUIRES_USER_GATE,
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const legitimateBlockingQuestion = canAskUser(decision);
|
|
136
|
+
return {
|
|
137
|
+
...compatibleResult({
|
|
138
|
+
decision,
|
|
139
|
+
name,
|
|
140
|
+
autonomousMode,
|
|
141
|
+
requiresUserApproval,
|
|
142
|
+
}),
|
|
143
|
+
questionSource: legitimateBlockingQuestion ? "FORGELOOP_BLOCKING_DECISION" : null,
|
|
144
|
+
canAskUser: legitimateBlockingQuestion,
|
|
145
|
+
requiresUserDecision: legitimateBlockingQuestion,
|
|
146
|
+
addsUnresolvedDecision: legitimateBlockingQuestion,
|
|
147
|
+
reasonCodes: legitimateBlockingQuestion
|
|
148
|
+
? [EXTERNAL_WORKFLOW_REASON_CODES.REQUIRES_USER_GATE]
|
|
149
|
+
: [],
|
|
150
|
+
};
|
|
151
|
+
}
|