@warpgogol/forge 3.0.0 → 4.1.1
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/AGENTS.md +18 -3
- package/bin/cli.ts +15 -8
- package/os/adr/adr.module.ts +24 -23
- package/os/adr/index.ts +1 -1
- package/os/audit/audit.module.ts +13 -8
- package/os/audit/index.ts +1 -1
- package/os/compass/compass.module.ts +22 -19
- package/os/core/core.module.ts +842 -864
- package/os/core/handlers/package-health.ts +21 -0
- package/os/core/index.ts +1 -1
- package/os/exploration/exploration.module.ts +19 -16
- package/os/exploration/index.ts +2 -2
- package/os/mission/index.ts +1 -1
- package/os/mission/mission.module.ts +13 -8
- package/os/naming/index.ts +1 -1
- package/os/naming/naming-convention.ts +1 -0
- package/os/naming/naming.module.ts +13 -7
- package/os/notes/index.ts +2 -2
- package/os/notes/notes.module.ts +20 -17
- package/os/plan/index.ts +1 -1
- package/os/plan/plan.module.ts +13 -8
- package/os/plugin/plugin.module.ts +10 -8
- package/os/program/program.module.ts +22 -20
- package/os/rfc/handlers/implement-stamp.ts +17 -1
- package/os/rfc/index.ts +1 -1
- package/os/rfc/rfc-0000-template.md +3 -2
- package/os/rfc/rfc.module.ts +54 -84
- package/os/rfc/types.ts +1 -0
- package/os/session/handlers/metrics-aggregate.ts +208 -0
- package/os/session/handlers/metrics-rfc.ts +339 -0
- package/os/session/handlers/metrics-session.ts +209 -0
- package/os/session/handlers/save.ts +19 -0
- package/os/session/index.ts +16 -1
- package/os/session/session.module.ts +133 -107
- package/os/session/types.ts +99 -0
- package/os/spec/spec.module.ts +28 -29
- package/os/werkstatt/werkstatt.module.ts +12 -9
- package/os/workflow/index.ts +1 -1
- package/os/workflow/workflow.module.ts +18 -12
- package/package.json +3 -1
- package/src/forge-module.ts +24 -10
- package/src/index.ts +12 -12
- package/src/onboarding/scaffold.ts +6 -4
- package/src/tests/metrics-rfc-1053.test.ts +355 -0
- package/src/types/werkstatt-engine-shims.d.ts +126 -48
- package/src/types/werkstatt-shared-shims.d.ts +6 -0
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
</MODULE_CONTRACT>
|
|
9
9
|
<CHANGE_SUMMARY>
|
|
10
10
|
<item>Initial: forge.package.health validator — engines, CI workflow, extract config, devDeps completeness.</item>
|
|
11
|
+
<item>PKG-HEALTH-05: reject versionBump: major in extract.config.yaml — prevents double-bump major version inflation.</item>
|
|
11
12
|
</CHANGE_SUMMARY>
|
|
12
13
|
*/
|
|
13
14
|
|
|
@@ -156,6 +157,26 @@ export async function runPackageHealth(
|
|
|
156
157
|
file: pkgDir,
|
|
157
158
|
fixHint: "Create extract.config.yaml with git remote and extraction settings.",
|
|
158
159
|
});
|
|
160
|
+
} else {
|
|
161
|
+
// CHECK 3b: versionBump must not be major (prevent accidental major version inflation)
|
|
162
|
+
try {
|
|
163
|
+
const configRaw = fs.readFileSync(extractConfigPath, "utf8");
|
|
164
|
+
const versionBumpMatch = configRaw.match(/^versionBump:\s*(\S+)/m);
|
|
165
|
+
if (versionBumpMatch && versionBumpMatch[1] === "major") {
|
|
166
|
+
violations.push({
|
|
167
|
+
ruleId: "PKG-HEALTH-05",
|
|
168
|
+
packageName,
|
|
169
|
+
severity: "error",
|
|
170
|
+
message:
|
|
171
|
+
"extract.config.yaml has versionBump: major — this causes double-bump when the monorepo version was already bumped manually. Use versionBump: patch instead.",
|
|
172
|
+
file: extractConfigPath,
|
|
173
|
+
fixHint:
|
|
174
|
+
"Change versionBump to patch (or minor). Manually bump the monorepo package.json version to the target instead.",
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
} catch {
|
|
178
|
+
// Read error — skip this check
|
|
179
|
+
}
|
|
159
180
|
}
|
|
160
181
|
|
|
161
182
|
// CHECK 4: devDependencies completeness — tools used in scripts must be declared
|
package/os/core/index.ts
CHANGED
|
@@ -12,16 +12,17 @@
|
|
|
12
12
|
|
|
13
13
|
import type { ForgeModule } from "../../src/forge-module.ts";
|
|
14
14
|
|
|
15
|
-
export
|
|
15
|
+
export async function createForgeExplorationModule(): Promise<ForgeModule> {
|
|
16
|
+
const { runExplorationList } = await import("./handlers/list.ts");
|
|
17
|
+
const { runExplorationShow } = await import("./handlers/show.ts");
|
|
18
|
+
const { runExplorationArchive } = await import("./handlers/archive.ts");
|
|
19
|
+
return {
|
|
16
20
|
name: "forge-exploration",
|
|
17
21
|
version: "0.1.0",
|
|
18
22
|
runtime: "autonomous",
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const { runExplorationArchive } = await import("./handlers/archive.ts");
|
|
23
|
-
|
|
24
|
-
registry.registerCommand({
|
|
23
|
+
declarations: [],
|
|
24
|
+
commands: [
|
|
25
|
+
{
|
|
25
26
|
name: "exploration.list",
|
|
26
27
|
description:
|
|
27
28
|
"List all exploration notes in docs/explorations/. Returns id, title, status, and createdAt for each note. " +
|
|
@@ -39,9 +40,8 @@ export const forgeExplorationModule: ForgeModule = {
|
|
|
39
40
|
},
|
|
40
41
|
},
|
|
41
42
|
execute: runExplorationList,
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
registry.registerCommand({
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
45
|
name: "exploration.show",
|
|
46
46
|
description:
|
|
47
47
|
"Show the full content of a single exploration note. Use --id <slug> to specify the note slug " +
|
|
@@ -60,9 +60,8 @@ export const forgeExplorationModule: ForgeModule = {
|
|
|
60
60
|
},
|
|
61
61
|
},
|
|
62
62
|
execute: runExplorationShow,
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
registry.registerCommand({
|
|
63
|
+
},
|
|
64
|
+
{
|
|
66
65
|
name: "exploration.archive",
|
|
67
66
|
description:
|
|
68
67
|
"Archive an exploration note by setting its status to 'archived'. Use --id <slug> to specify the note. " +
|
|
@@ -86,6 +85,10 @@ export const forgeExplorationModule: ForgeModule = {
|
|
|
86
85
|
},
|
|
87
86
|
},
|
|
88
87
|
execute: runExplorationArchive,
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
pipelines: [
|
|
91
|
+
|
|
92
|
+
]};
|
|
93
|
+
}
|
|
94
|
+
;
|
package/os/exploration/index.ts
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
</non-goals>
|
|
7
7
|
</MODULE_CONTRACT>
|
|
8
8
|
<CHANGE_SUMMARY>
|
|
9
|
-
<item>RFC-0710: expose
|
|
9
|
+
<item>RFC-0710: expose createForgeExplorationModule and exploration types from the exploration domain.</item>
|
|
10
10
|
</CHANGE_SUMMARY>
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
export {
|
|
13
|
+
export { createForgeExplorationModule } from "./exploration.module.ts";
|
|
14
14
|
export { runExplorationList } from "./handlers/list.ts";
|
|
15
15
|
export { runExplorationShow } from "./handlers/show.ts";
|
|
16
16
|
export { runExplorationArchive } from "./handlers/archive.ts";
|
package/os/mission/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { createForgeMissionModule } from "./mission.module.ts";
|
|
@@ -13,14 +13,15 @@
|
|
|
13
13
|
|
|
14
14
|
import type { ForgeModule } from "../../src/forge-module.ts";
|
|
15
15
|
|
|
16
|
-
export
|
|
16
|
+
export async function createForgeMissionModule(): Promise<ForgeModule> {
|
|
17
|
+
const { runMissionArchive } = await import("./handlers/archive.ts");
|
|
18
|
+
return {
|
|
17
19
|
name: "forge-mission",
|
|
18
20
|
version: "0.1.0",
|
|
19
21
|
runtime: "autonomous",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
registry.registerCommand({
|
|
22
|
+
declarations: [],
|
|
23
|
+
commands: [
|
|
24
|
+
{
|
|
24
25
|
name: "mission.archive",
|
|
25
26
|
description:
|
|
26
27
|
"Move terminal-state mission directories (state: closed or aborted in " +
|
|
@@ -50,6 +51,10 @@ export const forgeMissionModule: ForgeModule = {
|
|
|
50
51
|
},
|
|
51
52
|
},
|
|
52
53
|
execute: runMissionArchive,
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
pipelines: [
|
|
57
|
+
|
|
58
|
+
]};
|
|
59
|
+
}
|
|
60
|
+
;
|
package/os/naming/index.ts
CHANGED
|
@@ -102,6 +102,7 @@ const NAMING_CONVENTION_EXEMPT_DIRS = new Set([
|
|
|
102
102
|
"docs/performance", // Tool-generated screenshots and Lighthouse reports with timestamps
|
|
103
103
|
"docs/specs", // Imported specification documents with their own naming convention
|
|
104
104
|
"docs/rfcs/archive", // Archived RFCs — historical artifacts, cannot be renamed
|
|
105
|
+
"docs/metrics", // RFC-1053: generated metrics files with RFC/session IDs in filenames
|
|
105
106
|
]);
|
|
106
107
|
|
|
107
108
|
/**
|
|
@@ -12,13 +12,15 @@
|
|
|
12
12
|
|
|
13
13
|
import type { ForgeModule } from "../../src/forge-module.ts";
|
|
14
14
|
|
|
15
|
-
export
|
|
15
|
+
export async function createForgeNamingModule(): Promise<ForgeModule> {
|
|
16
|
+
const { runNamingConventionLint } = await import("./naming-convention.ts");
|
|
17
|
+
return {
|
|
16
18
|
name: "forge-naming",
|
|
17
19
|
version: "0.1.0",
|
|
18
20
|
runtime: "autonomous",
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
declarations: [],
|
|
22
|
+
commands: [
|
|
23
|
+
{
|
|
22
24
|
name: "naming.convention.lint",
|
|
23
25
|
contract: "naming",
|
|
24
26
|
rules: [],
|
|
@@ -34,6 +36,10 @@ export const forgeNamingModule: ForgeModule = {
|
|
|
34
36
|
},
|
|
35
37
|
reads: ["packages/**/*.{ts,tsx}", "apps/**/*.{ts,tsx}", "services/**/*.{ts,tsx}"],
|
|
36
38
|
execute: runNamingConventionLint,
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
pipelines: [
|
|
42
|
+
|
|
43
|
+
]};
|
|
44
|
+
}
|
|
45
|
+
;
|
package/os/notes/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
2
|
<MODULE_CONTRACT>
|
|
3
|
-
<purpose>Re-export
|
|
3
|
+
<purpose>Re-export createForgeNotesModule and note validator handlers.</purpose>
|
|
4
4
|
</MODULE_CONTRACT>
|
|
5
5
|
<CHANGE_SUMMARY>
|
|
6
6
|
<item>RFC-0808: initial notes module index.</item>
|
|
7
7
|
</CHANGE_SUMMARY>
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
export {
|
|
10
|
+
export { createForgeNotesModule } from "./notes.module.ts";
|
package/os/notes/notes.module.ts
CHANGED
|
@@ -17,12 +17,8 @@ import type {
|
|
|
17
17
|
ForgeRuntimeContext,
|
|
18
18
|
} from "../../src/types.ts";
|
|
19
19
|
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
version: "0.1.0",
|
|
23
|
-
runtime: "autonomous",
|
|
24
|
-
async register(registry) {
|
|
25
|
-
const { runNoteLinkValidate } = await import("../../src/validators/note-link-validate.ts");
|
|
20
|
+
export async function createForgeNotesModule(): Promise<ForgeModule> {
|
|
21
|
+
const { runNoteLinkValidate } = await import("../../src/validators/note-link-validate.ts");
|
|
26
22
|
const { runNoteFrontmatterValidate } =
|
|
27
23
|
await import("../../src/validators/note-frontmatter-validate.ts");
|
|
28
24
|
const { runNoteOrphanDetect } = await import("../../src/validators/note-orphan-detect.ts");
|
|
@@ -47,8 +43,13 @@ export const forgeNotesModule: ForgeModule = {
|
|
|
47
43
|
): Promise<ForgeCommandResult> => {
|
|
48
44
|
return runNoteOrphanDetect(input, context);
|
|
49
45
|
};
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
return {
|
|
47
|
+
name: "forge-notes",
|
|
48
|
+
version: "0.1.0",
|
|
49
|
+
runtime: "autonomous",
|
|
50
|
+
declarations: [],
|
|
51
|
+
commands: [
|
|
52
|
+
{
|
|
52
53
|
name: "note.link.validate",
|
|
53
54
|
contract: "note",
|
|
54
55
|
rules: [],
|
|
@@ -69,9 +70,8 @@ export const forgeNotesModule: ForgeModule = {
|
|
|
69
70
|
reads: ["vault/**/*.md"],
|
|
70
71
|
cacheable: false,
|
|
71
72
|
execute: noteLinkValidateWrapper,
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
registry.registerCommand({
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
75
|
name: "note.frontmatter.validate",
|
|
76
76
|
contract: "note",
|
|
77
77
|
rules: [],
|
|
@@ -92,9 +92,8 @@ export const forgeNotesModule: ForgeModule = {
|
|
|
92
92
|
reads: ["vault/**/*.md"],
|
|
93
93
|
cacheable: false,
|
|
94
94
|
execute: noteFrontmatterValidateWrapper,
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
registry.registerCommand({
|
|
95
|
+
},
|
|
96
|
+
{
|
|
98
97
|
name: "note.orphan.detect",
|
|
99
98
|
description:
|
|
100
99
|
"Detect orphan notes in a markdown note vault — notes with zero inbound wikilinks. Always exits zero (warnings, not errors).",
|
|
@@ -109,6 +108,10 @@ export const forgeNotesModule: ForgeModule = {
|
|
|
109
108
|
reads: ["vault/**/*.md"],
|
|
110
109
|
cacheable: false,
|
|
111
110
|
execute: noteOrphanDetectWrapper,
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
pipelines: [
|
|
114
|
+
|
|
115
|
+
]};
|
|
116
|
+
}
|
|
117
|
+
;
|
package/os/plan/index.ts
CHANGED
package/os/plan/plan.module.ts
CHANGED
|
@@ -12,14 +12,15 @@
|
|
|
12
12
|
|
|
13
13
|
import type { ForgeModule } from "../../src/forge-module.ts";
|
|
14
14
|
|
|
15
|
-
export
|
|
15
|
+
export async function createForgePlanModule(): Promise<ForgeModule> {
|
|
16
|
+
const { runPlanArchive } = await import("./handlers/archive.ts");
|
|
17
|
+
return {
|
|
16
18
|
name: "forge-plan",
|
|
17
19
|
version: "0.1.0",
|
|
18
20
|
runtime: "autonomous",
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
registry.registerCommand({
|
|
21
|
+
declarations: [],
|
|
22
|
+
commands: [
|
|
23
|
+
{
|
|
23
24
|
name: "plan.archive",
|
|
24
25
|
description:
|
|
25
26
|
"Move plan files whose parent RFC has terminal status " +
|
|
@@ -44,6 +45,10 @@ export const forgePlanModule: ForgeModule = {
|
|
|
44
45
|
},
|
|
45
46
|
},
|
|
46
47
|
execute: runPlanArchive,
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
pipelines: [
|
|
51
|
+
|
|
52
|
+
]};
|
|
53
|
+
}
|
|
54
|
+
;
|
|
@@ -233,8 +233,9 @@ export const forgePluginModule: ForgeModule = {
|
|
|
233
233
|
name: "forge-plugin",
|
|
234
234
|
version: "0.1.0",
|
|
235
235
|
runtime: "autonomous",
|
|
236
|
-
|
|
237
|
-
|
|
236
|
+
declarations: [],
|
|
237
|
+
commands: [
|
|
238
|
+
{
|
|
238
239
|
name: "forge.plugin.validate",
|
|
239
240
|
contract: "forge",
|
|
240
241
|
rules: [],
|
|
@@ -246,9 +247,8 @@ export const forgePluginModule: ForgeModule = {
|
|
|
246
247
|
reads: ["forge.yaml", "**/forge.plugin.yaml"],
|
|
247
248
|
cacheable: false,
|
|
248
249
|
execute: runPluginValidate,
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
registry.registerCommand({
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
252
|
name: "forge.plugin.discover",
|
|
253
253
|
description:
|
|
254
254
|
"Enumerate all project-declared skill packs with valid forge.plugin.yaml manifests (RFC-0941). Returns pack id, version, prefix, and directory.",
|
|
@@ -258,6 +258,8 @@ export const forgePluginModule: ForgeModule = {
|
|
|
258
258
|
reads: ["forge.yaml", "**/forge.plugin.yaml"],
|
|
259
259
|
cacheable: false,
|
|
260
260
|
execute: runPluginDiscover,
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
|
|
261
|
+
}
|
|
262
|
+
],
|
|
263
|
+
pipelines: [
|
|
264
|
+
|
|
265
|
+
]};
|
|
@@ -13,18 +13,19 @@ kernel registry (RFC-0856).</purpose>
|
|
|
13
13
|
|
|
14
14
|
import type { ForgeModule } from "../../src/forge-module.ts";
|
|
15
15
|
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
version: "0.1.0",
|
|
19
|
-
runtime: "autonomous",
|
|
20
|
-
|
|
21
|
-
async register(registry) {
|
|
22
|
-
const { runValidate } = await import("./handlers/validate.ts");
|
|
16
|
+
export async function createForgeProgramModule(): Promise<ForgeModule> {
|
|
17
|
+
const { runValidate } = await import("./handlers/validate.ts");
|
|
23
18
|
const { runSeal } = await import("./handlers/seal.ts");
|
|
24
19
|
const { runLease } = await import("./handlers/lease.ts");
|
|
25
20
|
const { runComplete } = await import("./handlers/complete.ts");
|
|
21
|
+
return {
|
|
22
|
+
name: "forge-program",
|
|
23
|
+
version: "0.1.0",
|
|
24
|
+
runtime: "autonomous",
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
declarations: [],
|
|
27
|
+
commands: [
|
|
28
|
+
{
|
|
28
29
|
name: "program.packet.validate",
|
|
29
30
|
contract: "program",
|
|
30
31
|
rules: [],
|
|
@@ -57,9 +58,8 @@ export const forgeProgramModule: ForgeModule = {
|
|
|
57
58
|
reads: ["docs/plans/**/program.yaml", "docs/plans/**/*.md"],
|
|
58
59
|
cacheable: false,
|
|
59
60
|
execute: runValidate,
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
registry.registerCommand({
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
63
|
name: "program.packet.seal",
|
|
64
64
|
description:
|
|
65
65
|
"Steward finalizes a packet against the predecessor's completion commit, " +
|
|
@@ -99,9 +99,8 @@ export const forgeProgramModule: ForgeModule = {
|
|
|
99
99
|
reads: ["docs/plans/**/program.yaml", "docs/plans/**/*.md"],
|
|
100
100
|
cacheable: false,
|
|
101
101
|
execute: runSeal,
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
registry.registerCommand({
|
|
102
|
+
},
|
|
103
|
+
{
|
|
105
104
|
name: "program.packet.lease",
|
|
106
105
|
description:
|
|
107
106
|
"Manage the exclusive local executor lease for a sealed packet. " +
|
|
@@ -152,9 +151,8 @@ export const forgeProgramModule: ForgeModule = {
|
|
|
152
151
|
reads: ["docs/plans/**/program.yaml", "docs/plans/**/*.md"],
|
|
153
152
|
cacheable: false,
|
|
154
153
|
execute: runLease,
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
registry.registerCommand({
|
|
154
|
+
},
|
|
155
|
+
{
|
|
158
156
|
name: "program.packet.complete",
|
|
159
157
|
description:
|
|
160
158
|
"Steward validates the implementation range, writes the completion report, " +
|
|
@@ -210,6 +208,10 @@ export const forgeProgramModule: ForgeModule = {
|
|
|
210
208
|
reads: ["docs/plans/**/program.yaml", "docs/plans/**/*.md"],
|
|
211
209
|
cacheable: false,
|
|
212
210
|
execute: runComplete,
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
211
|
+
}
|
|
212
|
+
],
|
|
213
|
+
pipelines: [
|
|
214
|
+
|
|
215
|
+
]};
|
|
216
|
+
}
|
|
217
|
+
;
|
|
@@ -12,10 +12,12 @@ verification evidence, and atomically mutates RFC frontmatter.
|
|
|
12
12
|
</non-goals>
|
|
13
13
|
</MODULE_CONTRACT>
|
|
14
14
|
<CHANGE_SUMMARY>
|
|
15
|
-
<item>RFC-0476: initial
|
|
15
|
+
<item>RFC-0476: initial rfc.implement.stamp handler with acceptance criteria evaluation, evidence checks, and atomic status transition.</item>
|
|
16
|
+
<item>RFC-0268: acceptance probe evidence check before stamping.</item>
|
|
16
17
|
<item>RFC-0756: auto-detect implementation commit when --implementation-commit is omitted.</item>
|
|
17
18
|
<item>RFC-0795: add RFC-IMP-07 dependsOn dependency gate — blocks stamping when any dependsOn entry is not implemented.</item>
|
|
18
19
|
<item>RFC-0997: add RFC-IMP-08 minimum-one-probe gate — blocks stamping for post-cutoff architecture/contract/command RFCs with no acceptance probes.</item>
|
|
20
|
+
<item>RFC-1053: integrate generateRfcMetrics after successful stamp (non-fatal, guarded by !isDryRun).</item>
|
|
19
21
|
</CHANGE_SUMMARY>
|
|
20
22
|
*/
|
|
21
23
|
|
|
@@ -25,6 +27,7 @@ import { join, dirname } from "node:path";
|
|
|
25
27
|
|
|
26
28
|
import { writeFileAtomic } from "../../../src/utils/fs-atomic.ts";
|
|
27
29
|
import { parse as yamlParse } from "yaml";
|
|
30
|
+
import { generateRfcMetrics } from "../../session/handlers/metrics-rfc.ts";
|
|
28
31
|
|
|
29
32
|
import {
|
|
30
33
|
listRfcFiles,
|
|
@@ -466,6 +469,18 @@ export async function runRfcImplementStamp(
|
|
|
466
469
|
// Write the mutated RFC file atomically
|
|
467
470
|
await writeFileAtomic(rfcFilePath, mutatedSource);
|
|
468
471
|
|
|
472
|
+
// ── RFC-1053: Generate per-RFC metrics (non-fatal, guarded by !isDryRun) ─
|
|
473
|
+
let metricsPath: string | undefined;
|
|
474
|
+
if (!isDryRun) {
|
|
475
|
+
try {
|
|
476
|
+
metricsPath = await generateRfcMetrics(workspaceRoot, targetId, logger);
|
|
477
|
+
} catch (metricsErr) {
|
|
478
|
+
logger.warn(
|
|
479
|
+
`[metrics] Failed to generate metrics for ${targetId}: ${(metricsErr as Error).message}`,
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
469
484
|
// ── Re-emit evidence if probes exist (to update with new status) ─────────
|
|
470
485
|
if (hasProbes && requiresEvidence && evidenceRelPath) {
|
|
471
486
|
// Evidence already exists and passed — no need to re-emit on stamp
|
|
@@ -493,6 +508,7 @@ export async function runRfcImplementStamp(
|
|
|
493
508
|
stampedAt,
|
|
494
509
|
criteriaChecked: criteriaEval.totalChecked,
|
|
495
510
|
...(evidenceRelPath ? { evidencePath: evidenceRelPath } : {}),
|
|
511
|
+
...(metricsPath ? { metricsPath } : {}),
|
|
496
512
|
},
|
|
497
513
|
violations: [],
|
|
498
514
|
},
|
package/os/rfc/index.ts
CHANGED
|
@@ -218,8 +218,9 @@ interface ExampleResult {
|
|
|
218
218
|
|
|
219
219
|
- [ ] AC-1: WHEN `<command> --json` is invoked, THE command SHALL return a JSON object matching the documented output schema (evidence: probe:AC-1 or test: <path>)
|
|
220
220
|
- [ ] AC-2: THE `<command>` SHALL be registered in the kernel module with the correct name and scope (evidence: file: <module-path>)
|
|
221
|
-
- [ ] AC-3: IF `<command>` receives invalid input, THEN THE command SHALL report a blocking error
|
|
222
|
-
- [ ] AC-4:
|
|
221
|
+
- [ ] AC-3: IF `<command>` receives invalid input, THEN THE command SHALL report a blocking error (evidence: test: <path/to/test>)
|
|
222
|
+
- [ ] AC-4: IF `<command>` receives invalid input, THEN THE command SHALL exit non-zero (evidence: test: <path/to/test>)
|
|
223
|
+
- [ ] AC-5: THE relevant `AGENTS.md` SHALL reference this RFC where agent behavior rules changed (evidence: file: <path:line>)
|
|
223
224
|
|
|
224
225
|
## Implementation notes for agents
|
|
225
226
|
|