@cassiomc1/forgeloop 0.1.11 → 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 +16 -18
- package/.github/copilot-instructions.md +16 -19
- package/AGENTS.md +18 -24
- package/AGENT_COMPATIBILITY.md +4 -211
- package/CLAUDE.md +16 -18
- package/LOOP_ENGINEERING.md +104 -0
- package/LOOP_SYSTEM_DESIGN.md +13 -11
- package/PROTOCOL_INTEGRATION.md +199 -0
- package/QUALITY_SCORECARD.md +1 -1
- package/README.md +125 -174
- package/TERMINOLOGY.md +2 -0
- package/THREAT_MODEL.md +5 -0
- package/package.json +5 -4
- package/src/commands/validate-protocol.js +11 -8
- package/src/core/conformance.js +47 -5
- package/src/core/discovery-surfaces.js +22 -0
- package/src/core/inspect.js +23 -12
- package/src/core/native-adapters.js +34 -2
- package/src/core/templates.js +1 -0
- package/src/core/verification-capability.js +47 -0
- package/conformance/README.md +0 -153
- package/conformance/backend-auth/EXPECTED_ROUTE.json +0 -7
- package/conformance/backend-auth/REQUEST.md +0 -4
- package/conformance/backend-auth/REQUIRED_EVIDENCE.json +0 -3
- package/conformance/backend-auth/REQUIRED_GATES.json +0 -3
- package/conformance/blind-premium-website/EXPECTED_ROUTE.json +0 -7
- package/conformance/blind-premium-website/REQUEST.md +0 -6
- package/conformance/blind-premium-website/REQUIRED_EVIDENCE.json +0 -14
- package/conformance/blind-premium-website/REQUIRED_GATES.json +0 -3
- package/conformance/complete-website/EXPECTED_ROUTE.json +0 -7
- package/conformance/complete-website/REQUEST.md +0 -6
- package/conformance/complete-website/REQUIRED_EVIDENCE.json +0 -3
- package/conformance/complete-website/REQUIRED_GATES.json +0 -3
- package/conformance/docs-only/EXPECTED_ROUTE.json +0 -7
- package/conformance/docs-only/REQUEST.md +0 -4
- package/conformance/docs-only/REQUIRED_EVIDENCE.json +0 -3
- package/conformance/docs-only/REQUIRED_GATES.json +0 -3
- package/conformance/runs/2026-08-11-codex-first-live.md +0 -98
- package/conformance/runs/2026-08-11-codex-second-live.md +0 -87
- package/conformance/runs/2026-08-13-codex-fifth-live.md +0 -386
- package/conformance/runs/2026-08-13-codex-fourth-live.md +0 -309
- package/conformance/runs/2026-08-13-codex-sixth-live.md +0 -412
- package/conformance/simple-bug/EXPECTED_ROUTE.json +0 -7
- package/conformance/simple-bug/REQUEST.md +0 -4
- package/conformance/simple-bug/REQUIRED_EVIDENCE.json +0 -3
- package/conformance/simple-bug/REQUIRED_GATES.json +0 -3
- package/src/core/agent-support.js +0 -89
|
@@ -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",
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const DISCOVERY_SURFACES = Object.freeze([
|
|
2
|
+
Object.freeze({
|
|
3
|
+
id: "agents-md",
|
|
4
|
+
path: "AGENTS.md",
|
|
5
|
+
kind: "project-instructions",
|
|
6
|
+
}),
|
|
7
|
+
Object.freeze({
|
|
8
|
+
id: "claude-md",
|
|
9
|
+
path: "CLAUDE.md",
|
|
10
|
+
kind: "project-instructions",
|
|
11
|
+
}),
|
|
12
|
+
Object.freeze({
|
|
13
|
+
id: "cursor-rule",
|
|
14
|
+
path: ".cursor/rules/project-loop.mdc",
|
|
15
|
+
kind: "project-instructions",
|
|
16
|
+
}),
|
|
17
|
+
Object.freeze({
|
|
18
|
+
id: "github-repository-instructions",
|
|
19
|
+
path: ".github/copilot-instructions.md",
|
|
20
|
+
kind: "project-instructions",
|
|
21
|
+
}),
|
|
22
|
+
]);
|
package/src/core/inspect.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { fileExists, ensureWithin, readBytes } from "./filesystem.js";
|
|
2
|
-
import {
|
|
2
|
+
import { DISCOVERY_SURFACES } from "./discovery-surfaces.js";
|
|
3
3
|
import { readManifest } from "./manifest.js";
|
|
4
4
|
import { PROTOCOL_VERSION } from "./protocol.js";
|
|
5
5
|
import { inspectSchemaHealth } from "./schema-validation.js";
|
|
@@ -42,15 +42,14 @@ export async function inspectTarget({ target, packageRoot, contractFile = null }
|
|
|
42
42
|
? `${FORGELOOP_KIT_DIR}/schemas`
|
|
43
43
|
: "schemas";
|
|
44
44
|
const doctor = await runDoctor({ target, packageRoot });
|
|
45
|
-
const
|
|
46
|
-
id:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
available: (await Promise.all(
|
|
51
|
-
record.instructionFiles.map(async (relativePath) => fileExists(ensureWithin(target, relativePath))),
|
|
52
|
-
)).some(Boolean),
|
|
45
|
+
const surfaces = await Promise.all(DISCOVERY_SURFACES.map(async (surface) => ({
|
|
46
|
+
id: surface.id,
|
|
47
|
+
path: surface.path,
|
|
48
|
+
kind: surface.kind,
|
|
49
|
+
available: await fileExists(ensureWithin(target, surface.path)),
|
|
53
50
|
})));
|
|
51
|
+
const availableSurfaces = surfaces.filter((surface) => surface.available);
|
|
52
|
+
const protocolActivated = availableSurfaces.length > 0;
|
|
54
53
|
|
|
55
54
|
const findings = [...doctor.findings];
|
|
56
55
|
for (const schema of schemaHealth.schemas) {
|
|
@@ -100,9 +99,20 @@ export async function inspectTarget({ target, packageRoot, contractFile = null }
|
|
|
100
99
|
error: manifestError,
|
|
101
100
|
},
|
|
102
101
|
profile,
|
|
102
|
+
integration: {
|
|
103
|
+
protocolActivated,
|
|
104
|
+
protocolMarker: "FORGELOOP_PROJECT_PROTOCOL=REQUIRED",
|
|
105
|
+
discovery: {
|
|
106
|
+
status: protocolActivated ? "INSTRUCTION_DISCOVERED" : "INSTRUCTION_ABSENT",
|
|
107
|
+
surfaces,
|
|
108
|
+
},
|
|
109
|
+
capability: {
|
|
110
|
+
status: "NOT_VERIFIED",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
103
113
|
adapters: {
|
|
104
|
-
detected:
|
|
105
|
-
|
|
114
|
+
detected: availableSurfaces.map((s) => s.path),
|
|
115
|
+
surfaces,
|
|
106
116
|
},
|
|
107
117
|
protocol: {
|
|
108
118
|
version: PROTOCOL_VERSION,
|
|
@@ -112,7 +122,8 @@ export async function inspectTarget({ target, packageRoot, contractFile = null }
|
|
|
112
122
|
},
|
|
113
123
|
state: { ...state, path: WORK_STATE_PATH, present: statePresent },
|
|
114
124
|
compatibility: {
|
|
115
|
-
|
|
125
|
+
deprecated: true,
|
|
126
|
+
agents: [],
|
|
116
127
|
},
|
|
117
128
|
findings,
|
|
118
129
|
evidence,
|
|
@@ -15,13 +15,44 @@ export function nativeShimReferences(relativePath) {
|
|
|
15
15
|
const prefix = nativeShimPrefix(relativePath);
|
|
16
16
|
return [
|
|
17
17
|
`${prefix}/LOOP_ENGINEERING.md`,
|
|
18
|
-
`${prefix}/
|
|
18
|
+
`${prefix}/PROTOCOL_INTEGRATION.md`,
|
|
19
19
|
];
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export function nativeShim(relativePath) {
|
|
23
23
|
const kitPrefix = nativeShimPrefix(relativePath);
|
|
24
|
-
return
|
|
24
|
+
return `<!-- FORGELOOP_PROJECT_PROTOCOL=REQUIRED -->
|
|
25
|
+
# ForgeLoop Project Protocol
|
|
26
|
+
|
|
27
|
+
This project is ForgeLoop-enabled.
|
|
28
|
+
|
|
29
|
+
If your execution environment loaded this file, ForgeLoop applies to work
|
|
30
|
+
performed in this project regardless of model, provider, product, IDE,
|
|
31
|
+
agent name, runtime name, or orchestration environment.
|
|
32
|
+
|
|
33
|
+
Do not treat ForgeLoop as vendor-specific, harness-specific, optional,
|
|
34
|
+
advisory, or something to follow only "in spirit".
|
|
35
|
+
|
|
36
|
+
Read and follow:
|
|
37
|
+
- ${kitPrefix}/LOOP_ENGINEERING.md
|
|
38
|
+
- ${kitPrefix}/PROTOCOL_INTEGRATION.md
|
|
39
|
+
|
|
40
|
+
Before changing product or executable files, establish the ForgeLoop contract,
|
|
41
|
+
route, required gates, and READY preflight.
|
|
42
|
+
|
|
43
|
+
Use the project-local ForgeLoop CLI for lifecycle-owned protocol state.
|
|
44
|
+
Never manually synthesize lifecycle chronology or assign ForgeLoop COMPLETE.
|
|
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
|
+
|
|
50
|
+
Before claiming ForgeLoop-verified completion, require
|
|
51
|
+
\`forgeloop complete\` to return \`VALID\`.
|
|
52
|
+
|
|
53
|
+
If a required capability is unavailable, report that ForgeLoop dimension as
|
|
54
|
+
not verified rather than simulating it.
|
|
55
|
+
`;
|
|
25
56
|
}
|
|
26
57
|
|
|
27
58
|
export function resolveNativeReference(relativePath, reference) {
|
|
@@ -45,6 +76,7 @@ export function inspectNativeAdapter(relativePath, bytes) {
|
|
|
45
76
|
missingReferences,
|
|
46
77
|
resolvedReferences,
|
|
47
78
|
hasForgeLoopMarker: /forgeloop/i.test(text),
|
|
79
|
+
hasProtocolMarker: text.includes("FORGELOOP_PROJECT_PROTOCOL=REQUIRED"),
|
|
48
80
|
};
|
|
49
81
|
}
|
|
50
82
|
|
package/src/core/templates.js
CHANGED
|
@@ -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
|
+
}
|
package/conformance/README.md
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
# ForgeLoop conformance scenarios
|
|
2
|
-
|
|
3
|
-
These scenarios are adapter-facing contracts. They describe requests and the
|
|
4
|
-
artifacts a live agent must produce; they do not invoke a model runtime and are
|
|
5
|
-
not part of the deterministic `npm test` execution path.
|
|
6
|
-
|
|
7
|
-
The current published baseline for new runs is
|
|
8
|
-
`@cassiomc1/forgeloop@0.1.10`. Pin that version when preparing a reproducible
|
|
9
|
-
blind run; historical reports retain the exact package version they used.
|
|
10
|
-
|
|
11
|
-
The frozen baseline was verified on 2026-08-13 with this identity:
|
|
12
|
-
|
|
13
|
-
```text
|
|
14
|
-
package: @cassiomc1/forgeloop@0.1.10
|
|
15
|
-
npm gitHead: 10246cf92016c92c91c6d99c2e8c7df7d99fa68a
|
|
16
|
-
release commit: 10246cf92016c92c91c6d99c2e8c7df7d99fa68a
|
|
17
|
-
GitHub tag: v0.1.10 -> 10246cf92016c92c91c6d99c2e8c7df7d99fa68a
|
|
18
|
-
tarball URL: https://registry.npmjs.org/@cassiomc1/forgeloop/-/forgeloop-0.1.10.tgz
|
|
19
|
-
tarball SHA-1: 175a83ebd00e6b0ec4f0b7bf2ed8924198d6df3c
|
|
20
|
-
npm SHA-512 integrity: sha512-+aMssrl9Wh69at9B1oKJQJEpgHpbKlb7sT1pLAWh+v/IouxXZkVqz5w34iR54pfqykjhl5Nrpd+g3XbQtzYdbA==
|
|
21
|
-
release identity: RELEASE_IDENTITY_VALID
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
The repository may contain documentation or executable commits after this
|
|
25
|
-
frozen package. Those commits do not change the package used by the blind run.
|
|
26
|
-
Version `0.1.10` includes the completion-validation and cleanup TOCTOU fixes;
|
|
27
|
-
repeat the complete identity check before starting a reproducible run.
|
|
28
|
-
|
|
29
|
-
The repository candidate is `0.1.11` and is not published. It makes repeated
|
|
30
|
-
verification recoverable through normal CLI transitions, evaluates evidence
|
|
31
|
-
readiness consistently, rejects future lifecycle claims and contradictory
|
|
32
|
-
compound evidence, and detects divergence between new work-state cycles and
|
|
33
|
-
their event ledger. Continue pinning `0.1.10` until `0.1.11` is published and
|
|
34
|
-
its release identity is verified.
|
|
35
|
-
|
|
36
|
-
Run a scenario in a disposable target using the Standard profile first:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
npx @cassiomc1/forgeloop preflight --json
|
|
40
|
-
npx @cassiomc1/forgeloop next --json
|
|
41
|
-
npx @cassiomc1/forgeloop audit --json
|
|
42
|
-
npx @cassiomc1/forgeloop complete --json
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
The expected post-implementation path is:
|
|
46
|
-
|
|
47
|
-
```text
|
|
48
|
-
implementation
|
|
49
|
-
→ forgeloop next
|
|
50
|
-
→ advance --to VERIFYING
|
|
51
|
-
→ forgeloop next
|
|
52
|
-
→ prepare-completion
|
|
53
|
-
→ forgeloop next
|
|
54
|
-
→ checks + record-check
|
|
55
|
-
→ forgeloop next
|
|
56
|
-
→ advance --to REVIEWING
|
|
57
|
-
→ forgeloop next
|
|
58
|
-
→ complete
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Use the Strict profile only as a separate experiment:
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
# .forgeloop/kit/PROJECT_PROFILE.md must be verified before this profile starts.
|
|
65
|
-
npx @cassiomc1/forgeloop preflight --strict --json
|
|
66
|
-
npx @cassiomc1/forgeloop audit --strict --json
|
|
67
|
-
npx @cassiomc1/forgeloop complete --strict --json
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Do not mix Standard and Strict criteria in one conformance result. Live-run
|
|
71
|
-
diagnostic records belong under [`conformance/runs/`](./runs/); they must not
|
|
72
|
-
contain secrets, credentials, hidden reasoning, or unnecessary conversation
|
|
73
|
-
history.
|
|
74
|
-
|
|
75
|
-
## Release identity evidence
|
|
76
|
-
|
|
77
|
-
Every live-run report records the exact published package used by the target.
|
|
78
|
-
Include all of these fields before sending the blind prompt:
|
|
79
|
-
|
|
80
|
-
```text
|
|
81
|
-
package: @cassiomc1/forgeloop@X.Y.Z
|
|
82
|
-
npm gitHead: <40-character commit SHA>
|
|
83
|
-
release commit: <40-character commit SHA>
|
|
84
|
-
GitHub tag: vX.Y.Z -> <40-character commit SHA>
|
|
85
|
-
tarball URL: https://registry.npmjs.org/...
|
|
86
|
-
tarball SHA-1: <40-character hex digest>
|
|
87
|
-
npm SHA-512 integrity: sha512-<base64 digest>
|
|
88
|
-
release identity: RELEASE_IDENTITY_VALID
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Run the repository's read-only verifier against the exact release commit:
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
RELEASE_COMMIT="$(git rev-list -n1 vX.Y.Z)"
|
|
95
|
-
npm run release:identity -- --version X.Y.Z --release-commit "$RELEASE_COMMIT"
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
Do not interpret a local package version, a green build, or a tarball URL by
|
|
99
|
-
itself as publication proof. If the verifier cannot establish every identity
|
|
100
|
-
field, record `RELEASE_IDENTITY_NOT_VERIFIED` or
|
|
101
|
-
`RELEASE_IDENTITY_INVALID` and do not start the blind run.
|
|
102
|
-
|
|
103
|
-
The complete-website scenario deliberately fails when implementation starts
|
|
104
|
-
before the contract, route, and required gates exist.
|
|
105
|
-
|
|
106
|
-
## Migration compatibility evidence
|
|
107
|
-
|
|
108
|
-
The real published `0.1.6` fixture at
|
|
109
|
-
[`tests/fixtures/legacy-0.1.6/`](../tests/fixtures/legacy-0.1.6/) is frozen
|
|
110
|
-
with package, tarball, SHA-1, SHA-512, `gitHead`, and extraction-date metadata.
|
|
111
|
-
The migration tests run from those local bytes and cover interruptions after
|
|
112
|
-
hidden writes, after hidden verification, after the manifest authority switch,
|
|
113
|
-
and during legacy cleanup. An interrupted target must be diagnosed as
|
|
114
|
-
`E_MIGRATION_INCOMPLETE`; a later `update` may retry only hash-owned cleanup.
|
|
115
|
-
User-modified, unmanaged, and `preserve=true` files remain untouched even when
|
|
116
|
-
that leaves a root residual. ForgeLoop revalidates the recorded ownership hash
|
|
117
|
-
immediately before deleting each managed legacy file. This narrows the race
|
|
118
|
-
window but does not provide OS-level filesystem locking against a separately
|
|
119
|
-
privileged concurrent process.
|
|
120
|
-
|
|
121
|
-
## Autonomous blind-run isolation
|
|
122
|
-
|
|
123
|
-
External workflows may help with local planning, review, tests, or
|
|
124
|
-
documentation, but a mandatory approval policy for a ForgeLoop `NON_BLOCKING`
|
|
125
|
-
decision is `INCOMPATIBLE WITH AUTONOMOUS MODE`. The harness must exclude that
|
|
126
|
-
policy before the blind prompt starts; do not add a hint to the prompt that
|
|
127
|
-
changes the scenario. `NON_BLOCKING` must remain non-blocking, and any
|
|
128
|
-
compatibility conflict is recorded as `WORKFLOW_CONFLICT`, not as a fake user
|
|
129
|
-
blocker.
|
|
130
|
-
|
|
131
|
-
For the sixth blind run, record these values before sending the unchanged blind
|
|
132
|
-
prompt:
|
|
133
|
-
|
|
134
|
-
```text
|
|
135
|
-
mandatory-approval workflows enabled: NO
|
|
136
|
-
external brainstorming hard gate enabled: NO
|
|
137
|
-
external design approval gate enabled: NO
|
|
138
|
-
subagents enabled: NO
|
|
139
|
-
delegation enabled: NO
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Also record the available and invoked external workflows, explicit autonomy
|
|
143
|
-
mode, process count, subagent count, and delegation status. If the harness
|
|
144
|
-
cannot disable a mandatory approval workflow, record `TEST_NOT_STARTED` and do
|
|
145
|
-
not interpret the run as a conformance failure or success. An installed
|
|
146
|
-
workflow and a compatible workflow are separate claims; use
|
|
147
|
-
`INCOMPATIBLE WITH AUTONOMOUS MODE`, not "broken", for the former.
|
|
148
|
-
|
|
149
|
-
Every live-run report must classify how it ended with exactly one
|
|
150
|
-
`terminationSource`: `AGENT`, `OPERATOR`, `HARNESS`, `TIMEOUT`, or `BLOCKER`.
|
|
151
|
-
An operator-terminated run is recorded as `RUN_STATUS: OPERATOR_INTERRUPTED`,
|
|
152
|
-
`CONFORMANCE: PARTIAL`, with post-termination capabilities marked
|
|
153
|
-
`NOT_REACHED` and the smallest failure class `OPERATOR_INTERRUPTION`.
|