@warpgogol/forge 4.0.0 → 4.1.2
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 +20 -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
|
@@ -7,123 +7,149 @@
|
|
|
7
7
|
</MODULE_CONTRACT>
|
|
8
8
|
<CHANGE_SUMMARY>
|
|
9
9
|
<item>RFC-0537: initial forgeSessionModule registering session.save, session.archive, session.validate, session.list commands.</item>
|
|
10
|
+
<item>RFC-1053: register metrics.aggregate command for skill effectiveness metrics aggregation.</item>
|
|
10
11
|
</CHANGE_SUMMARY>
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
import type { ForgeModule } from "../../src/forge-module.ts";
|
|
14
15
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
16
|
+
export async function createForgeSessionModule(): Promise<ForgeModule> {
|
|
17
|
+
const { runSessionSave } = await import("./handlers/save.ts");
|
|
18
|
+
const { runSessionArchive } = await import("./handlers/archive.ts");
|
|
19
|
+
const { runSessionValidate } = await import("./handlers/validate.ts");
|
|
20
|
+
const { runSessionList } = await import("./handlers/list.ts");
|
|
21
|
+
const { runMetricsAggregate } = await import("./handlers/metrics-aggregate.ts");
|
|
22
|
+
return {
|
|
23
|
+
name: "forge-session",
|
|
24
|
+
version: "0.1.0",
|
|
25
|
+
runtime: "autonomous",
|
|
26
|
+
declarations: [],
|
|
27
|
+
commands: [
|
|
28
|
+
{
|
|
29
|
+
name: "session.save",
|
|
30
|
+
description:
|
|
31
|
+
"Convert raw ATIF files from docs/sessions/.raw/ to structured markdown " +
|
|
32
|
+
"in docs/sessions/ with auto-extracted metadata. Idempotent — same raw " +
|
|
33
|
+
"file always produces the same output filename. Deletes raw file after " +
|
|
34
|
+
"conversion unless --keep-raw. Use --raw-file to process a specific file.",
|
|
35
|
+
scope: "workspace",
|
|
36
|
+
mutatesState: true,
|
|
37
|
+
writes: ["docs/sessions/*.md"],
|
|
38
|
+
reads: ["docs/sessions/.raw/*"],
|
|
39
|
+
cacheable: false,
|
|
40
|
+
flags: {
|
|
41
|
+
"raw-file": {
|
|
42
|
+
kind: "string",
|
|
43
|
+
description: "Process a specific raw file instead of scanning .raw/.",
|
|
44
|
+
},
|
|
45
|
+
"keep-raw": {
|
|
46
|
+
kind: "boolean",
|
|
47
|
+
description: "Do not delete raw file after conversion.",
|
|
48
|
+
},
|
|
49
|
+
"dry-run": {
|
|
50
|
+
kind: "boolean",
|
|
51
|
+
description: "Preview without writing files.",
|
|
52
|
+
},
|
|
49
53
|
},
|
|
54
|
+
execute: runSessionSave,
|
|
50
55
|
},
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
"
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
kind: "boolean",
|
|
75
|
-
description: "Preview what would be moved without touching the filesystem.",
|
|
56
|
+
{
|
|
57
|
+
name: "session.archive",
|
|
58
|
+
description:
|
|
59
|
+
"Move session files older than --max-age-days (default 7) from " +
|
|
60
|
+
"docs/sessions/ to docs/sessions/archive/. Bidirectional: files in " +
|
|
61
|
+
"archive/ younger than threshold are moved back to docs/sessions/. " +
|
|
62
|
+
"Use --dry-run to preview. Age is computed from frontmatter date, " +
|
|
63
|
+
"not filesystem mtime. Prefer the docs.archive umbrella command " +
|
|
64
|
+
"unless you need to archive only sessions.",
|
|
65
|
+
scope: "workspace",
|
|
66
|
+
mutatesState: true,
|
|
67
|
+
writes: ["docs/sessions/*.md", "docs/sessions/archive/**"],
|
|
68
|
+
reads: ["docs/sessions/**/*.md"],
|
|
69
|
+
cacheable: false,
|
|
70
|
+
flags: {
|
|
71
|
+
"max-age-days": {
|
|
72
|
+
kind: "string",
|
|
73
|
+
description: "Age threshold in days (default 7).",
|
|
74
|
+
},
|
|
75
|
+
"dry-run": {
|
|
76
|
+
kind: "boolean",
|
|
77
|
+
description: "Preview what would be moved without touching the filesystem.",
|
|
78
|
+
},
|
|
76
79
|
},
|
|
80
|
+
execute: runSessionArchive,
|
|
77
81
|
},
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
scope: "workspace",
|
|
92
|
-
flags: {
|
|
93
|
-
id: { kind: "string", description: "Target a single session by id." },
|
|
94
|
-
},
|
|
95
|
-
reads: ["docs/sessions/**/*.md", "docs/rfcs/**/*.md"],
|
|
96
|
-
execute: runSessionValidate,
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
registry.registerCommand({
|
|
100
|
-
name: "session.list",
|
|
101
|
-
description:
|
|
102
|
-
"List all sessions. Filter with --date-from, --date-to, --rfc, --type flags. " +
|
|
103
|
-
"Use --json for machine-readable output. Parses frontmatter on the fly. " +
|
|
104
|
-
"Includes archived sessions (marked with archived: true).",
|
|
105
|
-
scope: "workspace",
|
|
106
|
-
flags: {
|
|
107
|
-
"date-from": {
|
|
108
|
-
kind: "string",
|
|
109
|
-
description: "Filter sessions from this date (YYYY-MM-DD, inclusive).",
|
|
110
|
-
},
|
|
111
|
-
"date-to": {
|
|
112
|
-
kind: "string",
|
|
113
|
-
description: "Filter sessions up to this date (YYYY-MM-DD, inclusive).",
|
|
82
|
+
{
|
|
83
|
+
name: "session.validate",
|
|
84
|
+
contract: "session",
|
|
85
|
+
rules: [],
|
|
86
|
+
description:
|
|
87
|
+
"Validate session frontmatter schema (SES-01), id-filename match (SES-02), " +
|
|
88
|
+
"RFC-id existence (SES-03), raw file hygiene (SES-04), and non-markdown " +
|
|
89
|
+
"file detection (SES-05). Pass --id to validate a single file, " +
|
|
90
|
+
"or run without arguments for all. On-demand only — not integrated into " +
|
|
91
|
+
"build.check.",
|
|
92
|
+
scope: "workspace",
|
|
93
|
+
flags: {
|
|
94
|
+
id: { kind: "string", description: "Target a single session by id." },
|
|
114
95
|
},
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
96
|
+
reads: ["docs/sessions/**/*.md", "docs/rfcs/**/*.md"],
|
|
97
|
+
execute: runSessionValidate,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "session.list",
|
|
101
|
+
description:
|
|
102
|
+
"List all sessions. Filter with --date-from, --date-to, --rfc, --type flags. " +
|
|
103
|
+
"Use --json for machine-readable output. Parses frontmatter on the fly. " +
|
|
104
|
+
"Includes archived sessions (marked with archived: true).",
|
|
105
|
+
scope: "workspace",
|
|
106
|
+
flags: {
|
|
107
|
+
"date-from": {
|
|
108
|
+
kind: "string",
|
|
109
|
+
description: "Filter sessions from this date (YYYY-MM-DD, inclusive).",
|
|
110
|
+
},
|
|
111
|
+
"date-to": {
|
|
112
|
+
kind: "string",
|
|
113
|
+
description: "Filter sessions up to this date (YYYY-MM-DD, inclusive).",
|
|
114
|
+
},
|
|
115
|
+
rfc: {
|
|
116
|
+
kind: "string",
|
|
117
|
+
description: "Filter by related RFC id (e.g. RFC-0537).",
|
|
118
|
+
},
|
|
119
|
+
type: {
|
|
120
|
+
kind: "string",
|
|
121
|
+
description:
|
|
122
|
+
"Filter by session type (mission, grilling, implementation, review, fix, freeform).",
|
|
123
|
+
},
|
|
118
124
|
},
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
125
|
+
reads: ["docs/sessions/**/*.md"],
|
|
126
|
+
execute: runSessionList,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "metrics.aggregate",
|
|
130
|
+
description:
|
|
131
|
+
"Query and aggregate skill effectiveness metrics from docs/metrics/ files. " +
|
|
132
|
+
"Returns per-skill statistics (invocations, avgFindings, avgFixIterations, avgDurationMs). " +
|
|
133
|
+
"Use --skill to filter by skill name, --since/--until for date range.",
|
|
134
|
+
scope: "workspace",
|
|
135
|
+
flags: {
|
|
136
|
+
skill: {
|
|
137
|
+
kind: "string",
|
|
138
|
+
description: "Filter by skill name (e.g. fo-review).",
|
|
139
|
+
},
|
|
140
|
+
since: {
|
|
141
|
+
kind: "string",
|
|
142
|
+
description: "Only include metrics generated since this date (YYYY-MM-DD).",
|
|
143
|
+
},
|
|
144
|
+
until: {
|
|
145
|
+
kind: "string",
|
|
146
|
+
description: "Only include metrics generated until this date (YYYY-MM-DD).",
|
|
147
|
+
},
|
|
123
148
|
},
|
|
149
|
+
reads: ["docs/metrics/**/*.yaml"],
|
|
150
|
+
execute: runMetricsAggregate,
|
|
124
151
|
},
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
};
|
|
152
|
+
],
|
|
153
|
+
pipelines: [],
|
|
154
|
+
};
|
|
155
|
+
}
|
package/os/session/types.ts
CHANGED
|
@@ -12,12 +12,14 @@ validation rule identifiers.
|
|
|
12
12
|
<CHANGE_SUMMARY>
|
|
13
13
|
<item>RFC-0537: initial session domain types, constants, and SES rule identifiers.</item>
|
|
14
14
|
<item>RFC-0884: add checkpoint interfaces, extend SessionFrontmatter with optional checkpoint fields, add SES-06 rule.</item>
|
|
15
|
+
<item>RFC-1053: add metrics type interfaces (RfcMetrics, SessionMetrics, MetricsAggregateResult) and METRICS_DIR constant.</item>
|
|
15
16
|
</CHANGE_SUMMARY>
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
19
|
export const SESSION_DIR = "docs/sessions";
|
|
19
20
|
export const SESSION_RAW_SUBDIR = ".raw";
|
|
20
21
|
export const SESSION_ARCHIVE_SUBDIR = "archive";
|
|
22
|
+
export const METRICS_DIR = "docs/metrics";
|
|
21
23
|
export const SESSION_ID_PATTERN = /^\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}-[0-9a-f]{6}$/;
|
|
22
24
|
export const SESSION_FILE_PATTERN = /^\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}-[0-9a-f]{6}\.md$/;
|
|
23
25
|
|
|
@@ -133,6 +135,7 @@ export interface SessionSaveResult {
|
|
|
133
135
|
files: string[];
|
|
134
136
|
commands: string[];
|
|
135
137
|
};
|
|
138
|
+
metricsPath?: string;
|
|
136
139
|
dryRun: boolean;
|
|
137
140
|
}
|
|
138
141
|
|
|
@@ -201,3 +204,99 @@ export interface SessionListResult {
|
|
|
201
204
|
sessions: SessionListEntry[];
|
|
202
205
|
count: number;
|
|
203
206
|
}
|
|
207
|
+
|
|
208
|
+
// ── RFC-1053: Skill effectiveness metrics ──
|
|
209
|
+
|
|
210
|
+
export interface RfcPipelineStep {
|
|
211
|
+
step: string;
|
|
212
|
+
skill: string | null;
|
|
213
|
+
commitSha: string | null;
|
|
214
|
+
timestamp: string | null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface ReviewMetrics {
|
|
218
|
+
findingsCount: number;
|
|
219
|
+
findingsByAxis: Record<string, number>;
|
|
220
|
+
verdict: string | null;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export interface FixMetrics {
|
|
224
|
+
fixesApplied: number;
|
|
225
|
+
commitSha: string | null;
|
|
226
|
+
iterations: number;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export interface VerificationMetrics {
|
|
230
|
+
probesTotal: number;
|
|
231
|
+
probesPassed: number;
|
|
232
|
+
evidencePath: string | null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface ResultMetrics {
|
|
236
|
+
acceptanceCriteriaTotal: number;
|
|
237
|
+
acceptanceCriteriaMet: number;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export interface RfcTimings {
|
|
241
|
+
firstCommitAt: string | null;
|
|
242
|
+
lastCommitAt: string | null;
|
|
243
|
+
totalDurationMs: number | null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export interface RfcMetrics {
|
|
247
|
+
rfcId: string;
|
|
248
|
+
generatedAt: string;
|
|
249
|
+
pipeline: RfcPipelineStep[];
|
|
250
|
+
review: ReviewMetrics | null;
|
|
251
|
+
fix: FixMetrics | null;
|
|
252
|
+
verification: VerificationMetrics | null;
|
|
253
|
+
result: ResultMetrics;
|
|
254
|
+
timings: RfcTimings;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export interface SessionDocumentRef {
|
|
258
|
+
rfcId: string;
|
|
259
|
+
status: string;
|
|
260
|
+
metricsFile: string | null;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface SessionSkillInvocation {
|
|
264
|
+
skill: string;
|
|
265
|
+
approximateDurationMs: number | null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface InsightSummary {
|
|
269
|
+
total: number;
|
|
270
|
+
byCategory: Record<string, number>;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface SessionMetrics {
|
|
274
|
+
sessionId: string;
|
|
275
|
+
generatedAt: string;
|
|
276
|
+
date: string;
|
|
277
|
+
durationMs: number;
|
|
278
|
+
approximateDurations: true;
|
|
279
|
+
documents: SessionDocumentRef[];
|
|
280
|
+
skills: SessionSkillInvocation[];
|
|
281
|
+
insights: InsightSummary | null;
|
|
282
|
+
commits: string[];
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export interface SkillAggregate {
|
|
286
|
+
skill: string;
|
|
287
|
+
invocations: number;
|
|
288
|
+
avgFindings: number | null;
|
|
289
|
+
avgFixIterations: number | null;
|
|
290
|
+
avgDurationMs: number | null;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export interface MetricsAggregateResult {
|
|
294
|
+
command: "metrics.aggregate";
|
|
295
|
+
status: "ok";
|
|
296
|
+
skill: string | "all";
|
|
297
|
+
since: string | null;
|
|
298
|
+
until: string | null;
|
|
299
|
+
perSkill: SkillAggregate[];
|
|
300
|
+
totalRfcs: number;
|
|
301
|
+
totalSessions: number;
|
|
302
|
+
}
|
package/os/spec/spec.module.ts
CHANGED
|
@@ -14,20 +14,21 @@
|
|
|
14
14
|
|
|
15
15
|
import type { ForgeModule } from "../../src/forge-module.ts";
|
|
16
16
|
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
version: "0.2.0",
|
|
20
|
-
runtime: "autonomous",
|
|
21
|
-
async register(registry) {
|
|
22
|
-
const { runSpecValidate } = await import("./spec-validate.ts");
|
|
17
|
+
export async function createForgeSpecModule(): Promise<ForgeModule> {
|
|
18
|
+
const { runSpecValidate } = await import("./spec-validate.ts");
|
|
23
19
|
const { runSpecStatus } = await import("./spec-status.ts");
|
|
24
20
|
const { runSpecMaterialize } = await import("./spec-materialize.ts");
|
|
25
21
|
const { runSpecLiveMerge } = await import("./live-spec-merge.ts");
|
|
26
22
|
const { runSpecLiveList } = await import("./live-spec-list.ts");
|
|
27
23
|
const { runSpecLiveShow } = await import("./live-spec-show.ts");
|
|
28
24
|
const { runSpecLiveValidate } = await import("./live-spec-validate.ts");
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
return {
|
|
26
|
+
name: "forge-spec",
|
|
27
|
+
version: "0.2.0",
|
|
28
|
+
runtime: "autonomous",
|
|
29
|
+
declarations: [],
|
|
30
|
+
commands: [
|
|
31
|
+
{
|
|
31
32
|
name: "spec.validate",
|
|
32
33
|
contract: "spec",
|
|
33
34
|
rules: [],
|
|
@@ -45,9 +46,8 @@ export const forgeSpecModule: ForgeModule = {
|
|
|
45
46
|
},
|
|
46
47
|
reads: ["docs/specs/**/*"],
|
|
47
48
|
execute: runSpecValidate,
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
registry.registerCommand({
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
51
|
name: "spec.status",
|
|
52
52
|
description:
|
|
53
53
|
"Show roadmap progress for vendored specs. " +
|
|
@@ -61,9 +61,8 @@ export const forgeSpecModule: ForgeModule = {
|
|
|
61
61
|
},
|
|
62
62
|
reads: ["docs/specs/**/*", "docs/rfcs/**/*.md"],
|
|
63
63
|
execute: runSpecStatus,
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
registry.registerCommand({
|
|
64
|
+
},
|
|
65
|
+
{
|
|
67
66
|
name: "spec.materialize",
|
|
68
67
|
description:
|
|
69
68
|
"Scaffold RFC files for the next N front nodes of a spec roadmap. " +
|
|
@@ -78,9 +77,8 @@ export const forgeSpecModule: ForgeModule = {
|
|
|
78
77
|
nodes: { kind: "string", description: "Comma-separated explicit node ids to materialize." },
|
|
79
78
|
},
|
|
80
79
|
execute: runSpecMaterialize,
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
registry.registerCommand({
|
|
80
|
+
},
|
|
81
|
+
{
|
|
84
82
|
name: "spec.live.merge",
|
|
85
83
|
description:
|
|
86
84
|
"Merge deltas from an implemented RFC's ## Design section into a living feature spec " +
|
|
@@ -98,9 +96,8 @@ export const forgeSpecModule: ForgeModule = {
|
|
|
98
96
|
"dry-run": { kind: "boolean", description: "Preview deltas without writing files." },
|
|
99
97
|
},
|
|
100
98
|
execute: runSpecLiveMerge,
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
registry.registerCommand({
|
|
99
|
+
},
|
|
100
|
+
{
|
|
104
101
|
name: "spec.live.list",
|
|
105
102
|
description:
|
|
106
103
|
"List all living feature specs in docs/specs/live/. " +
|
|
@@ -108,9 +105,8 @@ export const forgeSpecModule: ForgeModule = {
|
|
|
108
105
|
scope: "workspace",
|
|
109
106
|
reads: ["docs/specs/live/*.md"],
|
|
110
107
|
execute: runSpecLiveList,
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
registry.registerCommand({
|
|
108
|
+
},
|
|
109
|
+
{
|
|
114
110
|
name: "spec.live.show",
|
|
115
111
|
description:
|
|
116
112
|
"Show a single living feature spec by domain. " +
|
|
@@ -121,9 +117,8 @@ export const forgeSpecModule: ForgeModule = {
|
|
|
121
117
|
domain: { kind: "string", required: true, description: "Domain name (filename without .md)." },
|
|
122
118
|
},
|
|
123
119
|
execute: runSpecLiveShow,
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
registry.registerCommand({
|
|
120
|
+
},
|
|
121
|
+
{
|
|
127
122
|
name: "spec.live.validate",
|
|
128
123
|
contract: "spec",
|
|
129
124
|
rules: [],
|
|
@@ -135,6 +130,10 @@ export const forgeSpecModule: ForgeModule = {
|
|
|
135
130
|
scope: "workspace",
|
|
136
131
|
reads: ["docs/specs/live/*.md", "docs/rfcs/**/*.md"],
|
|
137
132
|
execute: runSpecLiveValidate,
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
pipelines: [
|
|
136
|
+
|
|
137
|
+
]};
|
|
138
|
+
}
|
|
139
|
+
;
|
|
@@ -20,8 +20,9 @@ export const forgeWerkstattModule: ForgeModule = {
|
|
|
20
20
|
name: "forge-werkstatt",
|
|
21
21
|
version: "0.1.0",
|
|
22
22
|
runtime: "werkstatt-adapter",
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
declarations: [],
|
|
24
|
+
commands: [
|
|
25
|
+
{
|
|
25
26
|
name: "werkstatt.lock.status",
|
|
26
27
|
description: "Report all Werkstatt locks, their age, owner, and staleness (RFC-0362).",
|
|
27
28
|
scope: "workspace",
|
|
@@ -29,8 +30,8 @@ export const forgeWerkstattModule: ForgeModule = {
|
|
|
29
30
|
flags: {},
|
|
30
31
|
reads: [".werkstatt/locks/**"],
|
|
31
32
|
execute: runWerkstattLockStatus,
|
|
32
|
-
}
|
|
33
|
-
|
|
33
|
+
},
|
|
34
|
+
{
|
|
34
35
|
name: "werkstatt.lock.recover",
|
|
35
36
|
description:
|
|
36
37
|
"Classify and clean stale locks and staging artifacts (RFC-0362). Flags: --scope, --purge.",
|
|
@@ -48,8 +49,8 @@ export const forgeWerkstattModule: ForgeModule = {
|
|
|
48
49
|
reads: [".werkstatt/locks/**"],
|
|
49
50
|
cacheable: false,
|
|
50
51
|
execute: runWerkstattLockRecover,
|
|
51
|
-
}
|
|
52
|
-
|
|
52
|
+
},
|
|
53
|
+
{
|
|
53
54
|
name: "werkstatt.operation.validate",
|
|
54
55
|
contract: "werkstatt",
|
|
55
56
|
rules: [],
|
|
@@ -60,6 +61,8 @@ export const forgeWerkstattModule: ForgeModule = {
|
|
|
60
61
|
flags: {},
|
|
61
62
|
reads: ["packages/os/site-kernel-handoff/src/**/*.ts"],
|
|
62
63
|
execute: runWerkstattOperationValidate,
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
pipelines: [
|
|
67
|
+
|
|
68
|
+
]};
|
package/os/workflow/index.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
</CHANGE_SUMMARY>
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
export {
|
|
17
|
+
export { createForgeWorkflowModule } from "./workflow.module.ts";
|
|
18
18
|
export { runWorkflowLint, runWorkflowList, runWorkflowAmendList } from "./handlers.ts";
|
|
19
19
|
export type {
|
|
20
20
|
WorkflowPhase,
|
|
@@ -13,14 +13,16 @@
|
|
|
13
13
|
|
|
14
14
|
import type { ForgeModule } from "../../src/forge-module.ts";
|
|
15
15
|
|
|
16
|
-
export
|
|
16
|
+
export async function createForgeWorkflowModule(): Promise<ForgeModule> {
|
|
17
|
+
const { runWorkflowLint, runWorkflowList, runWorkflowAmendList } =
|
|
18
|
+
await import("./handlers.ts");
|
|
19
|
+
return {
|
|
17
20
|
name: "workflow",
|
|
18
21
|
version: "0.1.0",
|
|
19
22
|
runtime: "autonomous",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
registry.registerCommand({
|
|
23
|
+
declarations: [],
|
|
24
|
+
commands: [
|
|
25
|
+
{
|
|
24
26
|
name: "workflow.lint",
|
|
25
27
|
contract: "workflow",
|
|
26
28
|
rules: [],
|
|
@@ -32,8 +34,8 @@ export const forgeWorkflowModule: ForgeModule = {
|
|
|
32
34
|
supportsAllSites: true,
|
|
33
35
|
reads: [".agents/workflows/**/*.md", ".windsurf/workflows/**/*.md"],
|
|
34
36
|
execute: runWorkflowLint,
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
+
},
|
|
38
|
+
{
|
|
37
39
|
name: "workflow.list",
|
|
38
40
|
description:
|
|
39
41
|
"List .agents/workflows entries with phase, IO summary, and next workflow (RFC-0075).",
|
|
@@ -42,8 +44,8 @@ export const forgeWorkflowModule: ForgeModule = {
|
|
|
42
44
|
supportsAllSites: true,
|
|
43
45
|
reads: [".agents/workflows/**/*.md", ".windsurf/workflows/**/*.md"],
|
|
44
46
|
execute: runWorkflowList,
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
+
},
|
|
48
|
+
{
|
|
47
49
|
name: "workflow-amend.list",
|
|
48
50
|
description:
|
|
49
51
|
"List .agents/workflows-amend entries with phase, IO summary, and next workflow (RFC-0136).",
|
|
@@ -52,6 +54,10 @@ export const forgeWorkflowModule: ForgeModule = {
|
|
|
52
54
|
supportsAllSites: true,
|
|
53
55
|
reads: [".agents/workflows-amend/**/*.md"],
|
|
54
56
|
execute: runWorkflowAmendList,
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
pipelines: [
|
|
60
|
+
|
|
61
|
+
]};
|
|
62
|
+
}
|
|
63
|
+
;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warpgogol/forge",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -164,6 +164,7 @@
|
|
|
164
164
|
"lint": "pnpm exec eslint \"src/**/*.ts\" \"os/**/*.ts\"",
|
|
165
165
|
"typecheck": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
166
166
|
"test": "vitest run --passWithNoTests",
|
|
167
|
+
"test:coverage": "vitest run --coverage --passWithNoTests",
|
|
167
168
|
"test:watch": "vitest",
|
|
168
169
|
"test:tarball:node24": "node test-fixtures/node24-consumer/smoke.mjs"
|
|
169
170
|
},
|
|
@@ -182,6 +183,7 @@
|
|
|
182
183
|
"fast-check": "^4.9.0",
|
|
183
184
|
"typescript": "^6.0.3",
|
|
184
185
|
"typescript-eslint": "8.68.0",
|
|
186
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
185
187
|
"vitest": "^4.1.11"
|
|
186
188
|
},
|
|
187
189
|
"engines": {
|