@warpgogol/forge 5.2.0 → 5.2.4
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 +4 -1
- package/dist/os/adr/adr.module.js +1 -1
- package/dist/os/adr/adr.module.js.map +1 -1
- package/dist/os/compass/compass.module.js +2 -2
- package/dist/os/compass/compass.module.js.map +1 -1
- package/dist/os/compass/handlers/compass-audit-handler.d.ts +3 -0
- package/dist/os/compass/handlers/compass-audit-handler.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-audit-handler.js +87 -8
- package/dist/os/compass/handlers/compass-audit-handler.js.map +1 -1
- package/dist/os/core/core.module.d.ts.map +1 -1
- package/dist/os/core/core.module.js +15 -1
- package/dist/os/core/core.module.js.map +1 -1
- package/dist/os/mission/handlers/archive.d.ts.map +1 -1
- package/dist/os/mission/handlers/archive.js +22 -6
- package/dist/os/mission/handlers/archive.js.map +1 -1
- package/dist/os/program/lease.js +1 -1
- package/dist/os/program/lease.js.map +1 -1
- package/dist/os/queue/queue.module.js +1 -1
- package/dist/os/queue/queue.module.js.map +1 -1
- package/dist/os/rfc/handlers/list-create.d.ts.map +1 -1
- package/dist/os/rfc/handlers/list-create.js +79 -32
- package/dist/os/rfc/handlers/list-create.js.map +1 -1
- package/dist/os/rfc/rfc.module.js +1 -1
- package/dist/os/rfc/rfc.module.js.map +1 -1
- package/dist/os/spec/spec.module.d.ts.map +1 -1
- package/dist/os/spec/spec.module.js +2 -0
- package/dist/os/spec/spec.module.js.map +1 -1
- package/dist/src/config/forge-config.d.ts +9 -0
- package/dist/src/config/forge-config.d.ts.map +1 -1
- package/dist/src/config/forge-config.js +7 -0
- package/dist/src/config/forge-config.js.map +1 -1
- package/dist/src/knowledge/index.d.ts +1 -0
- package/dist/src/knowledge/index.d.ts.map +1 -1
- package/dist/src/knowledge/index.js +1 -0
- package/dist/src/knowledge/index.js.map +1 -1
- package/dist/src/knowledge/sync.d.ts +24 -0
- package/dist/src/knowledge/sync.d.ts.map +1 -0
- package/dist/src/knowledge/sync.js +127 -0
- package/dist/src/knowledge/sync.js.map +1 -0
- package/dist/src/onboarding/agents-generate.d.ts +2 -0
- package/dist/src/onboarding/agents-generate.d.ts.map +1 -1
- package/dist/src/onboarding/agents-generate.js +14 -18
- package/dist/src/onboarding/agents-generate.js.map +1 -1
- package/dist/src/onboarding/doctor.d.ts +6 -0
- package/dist/src/onboarding/doctor.d.ts.map +1 -1
- package/dist/src/onboarding/doctor.js +124 -14
- package/dist/src/onboarding/doctor.js.map +1 -1
- package/dist/src/onboarding/init.d.ts.map +1 -1
- package/dist/src/onboarding/init.js +15 -8
- package/dist/src/onboarding/init.js.map +1 -1
- package/dist/src/onboarding/memory-compact.d.ts +22 -0
- package/dist/src/onboarding/memory-compact.d.ts.map +1 -0
- package/dist/src/onboarding/memory-compact.js +147 -0
- package/dist/src/onboarding/memory-compact.js.map +1 -0
- package/dist/src/onboarding/memory-scaffold.d.ts +1 -0
- package/dist/src/onboarding/memory-scaffold.d.ts.map +1 -1
- package/dist/src/onboarding/memory-scaffold.js +1 -1
- package/dist/src/onboarding/memory-scaffold.js.map +1 -1
- package/dist/src/onboarding/nested-agents-generate.d.ts.map +1 -1
- package/dist/src/onboarding/nested-agents-generate.js +1 -1
- package/dist/src/onboarding/nested-agents-generate.js.map +1 -1
- package/dist/src/onboarding/upgrade.d.ts.map +1 -1
- package/dist/src/onboarding/upgrade.js +42 -13
- package/dist/src/onboarding/upgrade.js.map +1 -1
- package/dist/src/onboarding/workspace-discovery.d.ts +1 -1
- package/dist/src/onboarding/workspace-discovery.d.ts.map +1 -1
- package/dist/src/onboarding/workspace-discovery.js +14 -2
- package/dist/src/onboarding/workspace-discovery.js.map +1 -1
- package/dist/src/types.d.ts +1 -2
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +1 -0
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/fs-atomic.js +1 -1
- package/dist/src/utils/fs-atomic.js.map +1 -1
- package/docs/reference/forge-yaml.md +12 -0
- package/os/adr/adr.module.ts +1 -1
- package/os/compass/compass.module.ts +2 -2
- package/os/compass/handlers/compass-audit-handler.ts +116 -8
- package/os/compass/handlers/tests/compass-audit-plan.test.ts +98 -0
- package/os/compass/handlers/tests/compass-audit-record.test.ts +105 -0
- package/os/compass/handlers/tests/compass-audit-validate.test.ts +133 -0
- package/os/compass/handlers/tests/compass-ledger-scope.test.ts +124 -0
- package/os/core/core.module.ts +16 -1
- package/os/mission/handlers/archive.test.ts +49 -0
- package/os/mission/handlers/archive.ts +21 -6
- package/os/program/lease.ts +1 -1
- package/os/queue/queue.module.ts +1 -1
- package/os/rfc/handlers/list-create.ts +83 -35
- package/os/rfc/handlers/validate-rules.test.ts +50 -0
- package/os/rfc/rfc-create-concurrent.test.ts +118 -0
- package/os/rfc/rfc-create-hint.test.ts +90 -0
- package/os/rfc/rfc-read-only-no-side-effects.test.ts +83 -0
- package/os/rfc/rfc.module.ts +1 -1
- package/os/spec/spec.module.ts +2 -0
- package/package.json +1 -1
- package/profiles/forge-shell.yaml +3 -0
- package/profiles/godot-game.yaml +3 -0
- package/profiles/phaser-game.yaml +3 -0
- package/profiles/site-workshop.yaml +567 -564
- package/src/config/forge-config.ts +11 -0
- package/src/knowledge/__tests__/sync.test.ts +227 -0
- package/src/knowledge/index.ts +7 -0
- package/src/knowledge/sync.ts +161 -0
- package/src/onboarding/agents-generate.ts +18 -18
- package/src/onboarding/doctor.ts +141 -15
- package/src/onboarding/init.ts +15 -8
- package/src/onboarding/memory-compact.ts +188 -0
- package/src/onboarding/memory-scaffold.ts +1 -1
- package/src/onboarding/nested-agents-generate.ts +5 -1
- package/src/onboarding/upgrade.ts +47 -16
- package/src/onboarding/workspace-discovery.ts +15 -1
- package/src/tests/agents-generate.test.ts +26 -3
- package/src/tests/doctor-dist-freshness.test.ts +110 -0
- package/src/tests/doctor-fix.test.ts +145 -0
- package/src/tests/doctor-nested-agents.test.ts +108 -0
- package/src/tests/memory-compact.test.ts +143 -0
- package/src/tests/upgrade.test.ts +53 -0
- package/src/tests/workspace-discovery.test.ts +28 -0
- package/src/types.ts +2 -2
- package/src/utils/fs-atomic.ts +1 -1
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>
|
|
4
|
+
RFC-1139 AC-1: the next-steps hint printed by rfc.create must be an
|
|
5
|
+
executable command — correct binary (werkstatt, not forge), correct
|
|
6
|
+
subcommand (run), and correct flags (--id, not --file).
|
|
7
|
+
</purpose>
|
|
8
|
+
</MODULE_CONTRACT>
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, expect, it, beforeEach, afterEach } from "vitest";
|
|
12
|
+
import * as fs from "node:fs/promises";
|
|
13
|
+
import * as os from "node:os";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import { runRfcCreate } from "./handlers/list-create.ts";
|
|
16
|
+
import type { ForgeCommandInput, ForgeRuntimeContext } from "../../src/types.ts";
|
|
17
|
+
|
|
18
|
+
const RFC_DIR = "docs/rfcs";
|
|
19
|
+
|
|
20
|
+
const TEMPLATE = `---
|
|
21
|
+
id: RFC-0000
|
|
22
|
+
title: "Template"
|
|
23
|
+
status: draft
|
|
24
|
+
kind: command
|
|
25
|
+
scope: workspace
|
|
26
|
+
createdAt: YYYY-MM-DD
|
|
27
|
+
updatedAt: YYYY-MM-DD
|
|
28
|
+
satisfies: []
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
# RFC-0000: Template
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
function makeContext(root: string): ForgeRuntimeContext {
|
|
35
|
+
return {
|
|
36
|
+
workspaceRoot: root,
|
|
37
|
+
logger: {
|
|
38
|
+
info() {},
|
|
39
|
+
warn() {},
|
|
40
|
+
error() {},
|
|
41
|
+
success() {},
|
|
42
|
+
section() {},
|
|
43
|
+
getEvents: () => [],
|
|
44
|
+
},
|
|
45
|
+
outputFormat: "json",
|
|
46
|
+
dryRun: false,
|
|
47
|
+
} as unknown as ForgeRuntimeContext;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function makeInput(flags: Record<string, unknown>): ForgeCommandInput {
|
|
51
|
+
return { argv: [], flags } as unknown as ForgeCommandInput;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
describe("rfc.create — RFC-1139 next-steps hint accuracy", () => {
|
|
55
|
+
let root: string;
|
|
56
|
+
let rfcDir: string;
|
|
57
|
+
|
|
58
|
+
beforeEach(async () => {
|
|
59
|
+
root = await fs.mkdtemp(path.join(os.tmpdir(), "rfc-hint-"));
|
|
60
|
+
rfcDir = path.join(root, RFC_DIR);
|
|
61
|
+
await fs.mkdir(rfcDir, { recursive: true });
|
|
62
|
+
await fs.writeFile(path.join(rfcDir, "rfc-0000-template.md"), TEMPLATE, "utf8");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
afterEach(async () => {
|
|
66
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("AC-1: next-steps hint is an executable werkstatt command with --id", async () => {
|
|
70
|
+
const result = await runRfcCreate(
|
|
71
|
+
makeInput({ title: "Hint Test", kind: "command", scope: "workspace" }),
|
|
72
|
+
makeContext(root),
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const steps = result.nextSteps ?? [];
|
|
76
|
+
expect(steps.length).toBeGreaterThan(0);
|
|
77
|
+
|
|
78
|
+
for (const step of steps) {
|
|
79
|
+
const match = step.action.match(/pnpm exec (\S+) run ([\w.]+)/);
|
|
80
|
+
expect(match, `hint "${step.action}" must contain a runnable command`).not.toBeNull();
|
|
81
|
+
const [, binary, command] = match!;
|
|
82
|
+
// forge has no `run` subcommand — werkstatt does
|
|
83
|
+
expect(binary).toBe("werkstatt");
|
|
84
|
+
expect(command).toBe("rfc.validate");
|
|
85
|
+
// rfc.validate takes --id, not --file
|
|
86
|
+
expect(step.action).toContain("--id RFC-");
|
|
87
|
+
expect(step.action).not.toContain("--file");
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>
|
|
4
|
+
RFC-1139 AC-4: read-only commands must not write to the working tree —
|
|
5
|
+
no ambient regeneration of tracked generated files as a side effect.
|
|
6
|
+
Guards against future read-path writers.
|
|
7
|
+
</purpose>
|
|
8
|
+
</MODULE_CONTRACT>
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, expect, it, beforeEach, afterEach } from "vitest";
|
|
12
|
+
import * as fs from "node:fs/promises";
|
|
13
|
+
import * as os from "node:os";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import { runRfcList } from "./handlers/list-create.ts";
|
|
16
|
+
import type { ForgeCommandInput, ForgeRuntimeContext } from "../../src/types.ts";
|
|
17
|
+
|
|
18
|
+
function makeContext(root: string): ForgeRuntimeContext {
|
|
19
|
+
return {
|
|
20
|
+
workspaceRoot: root,
|
|
21
|
+
logger: {
|
|
22
|
+
info() {},
|
|
23
|
+
warn() {},
|
|
24
|
+
error() {},
|
|
25
|
+
success() {},
|
|
26
|
+
section() {},
|
|
27
|
+
getEvents: () => [],
|
|
28
|
+
},
|
|
29
|
+
outputFormat: "json",
|
|
30
|
+
dryRun: false,
|
|
31
|
+
} as unknown as ForgeRuntimeContext;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function makeInput(flags: Record<string, unknown> = {}): ForgeCommandInput {
|
|
35
|
+
return { argv: [], flags } as unknown as ForgeCommandInput;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function snapshotTree(root: string): Promise<Map<string, string>> {
|
|
39
|
+
const snapshot = new Map<string, string>();
|
|
40
|
+
async function walk(dir: string): Promise<void> {
|
|
41
|
+
for (const entry of await fs.readdir(dir, { withFileTypes: true })) {
|
|
42
|
+
const full = path.join(dir, entry.name);
|
|
43
|
+
if (entry.isDirectory()) {
|
|
44
|
+
await walk(full);
|
|
45
|
+
} else if (entry.isFile()) {
|
|
46
|
+
snapshot.set(path.relative(root, full), await fs.readFile(full, "utf8"));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
await walk(root);
|
|
51
|
+
return snapshot;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
describe("read-only commands — RFC-1139 no side-effect writes", () => {
|
|
55
|
+
let root: string;
|
|
56
|
+
|
|
57
|
+
beforeEach(async () => {
|
|
58
|
+
root = await fs.mkdtemp(path.join(os.tmpdir(), "rfc-readonly-"));
|
|
59
|
+
const rfcDir = path.join(root, "docs", "rfcs");
|
|
60
|
+
await fs.mkdir(rfcDir, { recursive: true });
|
|
61
|
+
await fs.writeFile(
|
|
62
|
+
path.join(rfcDir, "rfc-0001-test.md"),
|
|
63
|
+
`---\nid: RFC-0001\ntitle: "Test"\nstatus: draft\n---\n\n# RFC-0001\n`,
|
|
64
|
+
"utf8",
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
afterEach(async () => {
|
|
69
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("AC-4: rfc.list leaves the working tree byte-identical", async () => {
|
|
73
|
+
const before = await snapshotTree(root);
|
|
74
|
+
const result = await runRfcList(makeInput(), makeContext(root));
|
|
75
|
+
expect(result.data?.status).toBe("ok");
|
|
76
|
+
const after = await snapshotTree(root);
|
|
77
|
+
|
|
78
|
+
expect([...after.keys()].sort()).toEqual([...before.keys()].sort());
|
|
79
|
+
for (const [file, content] of before) {
|
|
80
|
+
expect(after.get(file), `${file} modified by read-only command`).toBe(content);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
package/os/rfc/rfc.module.ts
CHANGED
|
@@ -396,7 +396,7 @@ const {
|
|
|
396
396
|
"RFC-0476: the exclusive atomic path for accepted → implemented transitions. " +
|
|
397
397
|
"Verifies preconditions (accepted status, checked+evidenced criteria, clean tree, " +
|
|
398
398
|
"reachable RFC-referencing commit, passing probe evidence) then atomically sets " +
|
|
399
|
-
"status: implemented, implementedAt, and updatedAt. Use --dry-run to preview.",
|
|
399
|
+
"status: implemented, implementedAt, and updatedAt. Use --dry-run to preview. Required flags: `--id`.",
|
|
400
400
|
scope: "workspace",
|
|
401
401
|
mutatesState: true,
|
|
402
402
|
writes: ["docs/rfcs/**/*.md"],
|
package/os/spec/spec.module.ts
CHANGED
|
@@ -103,6 +103,7 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
103
103
|
"List all living feature specs in docs/specs/live/. " +
|
|
104
104
|
"Returns domain, title, lastMergedRfc, updatedAt, and historyCount for each spec.",
|
|
105
105
|
scope: "workspace",
|
|
106
|
+
flags: {},
|
|
106
107
|
reads: ["docs/specs/live/*.md"],
|
|
107
108
|
execute: runSpecLiveList,
|
|
108
109
|
},
|
|
@@ -128,6 +129,7 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
128
129
|
"V-LS-03 (lastMergedRfc is archived), V-LS-04 (history entries are archived), " +
|
|
129
130
|
"V-LS-05 (no duplicate domains).",
|
|
130
131
|
scope: "workspace",
|
|
132
|
+
flags: {},
|
|
131
133
|
reads: ["docs/specs/live/*.md", "docs/rfcs/**/*.md"],
|
|
132
134
|
execute: runSpecLiveValidate,
|
|
133
135
|
}
|
package/package.json
CHANGED
package/profiles/godot-game.yaml
CHANGED