@warpgogol/forge 2.9.4 → 2.9.5
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/dist/bin/cli.js +0 -0
- package/dist/os/adr/handlers/implement-stamp.js +1 -1
- package/dist/os/adr/handlers/implement-stamp.js.map +1 -1
- package/dist/os/adr/handlers/list-create.d.ts.map +1 -1
- package/dist/os/adr/handlers/list-create.js +40 -4
- package/dist/os/adr/handlers/list-create.js.map +1 -1
- package/dist/os/adr/handlers/validate.d.ts.map +1 -1
- package/dist/os/adr/handlers/validate.js +10 -4
- package/dist/os/adr/handlers/validate.js.map +1 -1
- package/dist/os/adr/types.d.ts +1 -0
- package/dist/os/adr/types.d.ts.map +1 -1
- package/dist/os/adr/types.js +1 -0
- package/dist/os/adr/types.js.map +1 -1
- package/dist/os/core/handlers/package-health.d.ts.map +1 -1
- package/dist/os/core/handlers/package-health.js +8 -4
- package/dist/os/core/handlers/package-health.js.map +1 -1
- package/dist/os/core/handlers/pinned-validate.d.ts.map +1 -1
- package/dist/os/core/handlers/pinned-validate.js +2 -2
- package/dist/os/core/handlers/pinned-validate.js.map +1 -1
- package/dist/os/program/handlers/complete.js +2 -2
- package/dist/os/program/handlers/complete.js.map +1 -1
- package/dist/os/program/handlers/lease.js +1 -1
- package/dist/os/program/handlers/lease.js.map +1 -1
- package/dist/os/program/handlers/seal.js +2 -2
- package/dist/os/program/handlers/seal.js.map +1 -1
- package/dist/os/program/handlers/validate.js +3 -3
- package/dist/os/program/handlers/validate.js.map +1 -1
- package/dist/os/rfc/dna-trace.js +1 -1
- package/dist/os/rfc/dna-trace.js.map +1 -1
- package/dist/os/rfc/handlers/check.js +3 -3
- package/dist/os/rfc/handlers/check.js.map +1 -1
- package/dist/os/rfc/handlers/implement-stamp.js +1 -1
- package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
- package/dist/os/rfc/handlers/index-graph.js +4 -4
- package/dist/os/rfc/handlers/index-graph.js.map +1 -1
- package/dist/os/rfc/handlers/lifecycle.js +1 -1
- package/dist/os/rfc/handlers/lifecycle.js.map +1 -1
- package/dist/os/rfc/handlers/validate.d.ts.map +1 -1
- package/dist/os/rfc/handlers/validate.js +10 -4
- package/dist/os/rfc/handlers/validate.js.map +1 -1
- package/dist/os/session/handlers/validate.d.ts.map +1 -1
- package/dist/os/session/handlers/validate.js +10 -4
- package/dist/os/session/handlers/validate.js.map +1 -1
- package/dist/os/spec/live-spec-validate.js +2 -2
- package/dist/os/spec/live-spec-validate.js.map +1 -1
- package/dist/os/spec/spec-validate.js +1 -1
- package/dist/os/spec/spec-validate.js.map +1 -1
- package/dist/os/workflow/handlers.js +1 -1
- package/dist/os/workflow/handlers.js.map +1 -1
- package/dist/src/onboarding/create.js +1 -1
- package/dist/src/onboarding/create.js.map +1 -1
- package/dist/src/onboarding/doctor.js +1 -1
- 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 +31 -1
- package/dist/src/onboarding/init.js.map +1 -1
- package/dist/src/onboarding/profile-validate.js +1 -1
- package/dist/src/onboarding/profile-validate.js.map +1 -1
- package/dist/src/utils/fs-trash.d.ts.map +1 -1
- package/dist/src/utils/fs-trash.js +1 -1
- package/dist/src/utils/fs-trash.js.map +1 -1
- package/dist/src/validators/note-frontmatter-validate.js +1 -1
- package/dist/src/validators/note-frontmatter-validate.js.map +1 -1
- package/dist/src/validators/note-link-validate.js +1 -1
- package/dist/src/validators/note-link-validate.js.map +1 -1
- package/os/adr/adr-0000-template.md +46 -0
- package/os/adr/handlers/implement-stamp.ts +1 -1
- package/os/adr/handlers/list-create.ts +48 -4
- package/os/adr/handlers/validate.ts +8 -4
- package/os/adr/types.ts +1 -0
- package/os/core/handlers/package-health.ts +9 -5
- package/os/core/handlers/pinned-validate.ts +4 -2
- package/os/program/handlers/complete.ts +2 -2
- package/os/program/handlers/lease.ts +1 -1
- package/os/program/handlers/seal.ts +2 -2
- package/os/program/handlers/validate.ts +3 -3
- package/os/rfc/dna-trace.ts +1 -1
- package/os/rfc/handlers/check.ts +3 -3
- package/os/rfc/handlers/implement-stamp.ts +1 -1
- package/os/rfc/handlers/index-graph.ts +4 -4
- package/os/rfc/handlers/lifecycle.ts +1 -1
- package/os/rfc/handlers/validate.ts +8 -4
- package/os/rfc/rfc-0000-template.md +16 -20
- package/os/session/handlers/validate.ts +8 -4
- package/os/spec/live-spec-validate.ts +2 -2
- package/os/spec/spec-validate.ts +1 -1
- package/os/workflow/handlers.ts +1 -1
- package/package.json +72 -194
- package/skills/_shared/fo-pipeline-conventions.md +5 -5
- package/skills/fo/fo-extract-dna/SKILL.md +1 -1
- package/skills/fo/fo-idea-audit/AUDIT-AXES.md +1 -1
- package/skills/fo/fo-idea-create-adr/SKILL.md +1 -1
- package/skills/fo/fo-idea-create-rfc/SKILL.md +3 -3
- package/skills/fo/fo-idea-implement/ADR-FLOW.md +2 -2
- package/skills/fo/fo-idea-implement/SKILL.md +1 -1
- package/skills/fo/fo-idea-plan/SKILL.md +2 -2
- package/skills/fo/fo-step-commit/SKILL.md +2 -2
- package/src/onboarding/create.ts +1 -1
- package/src/onboarding/doctor.ts +1 -1
- package/src/onboarding/init.ts +30 -1
- package/src/onboarding/profile-validate.ts +1 -1
- package/src/utils/fs-trash.ts +1 -1
- package/src/validators/note-frontmatter-validate.ts +1 -1
- package/src/validators/note-link-validate.ts +1 -1
|
@@ -114,7 +114,7 @@ export function runNoteLinkValidate(input, context) {
|
|
|
114
114
|
},
|
|
115
115
|
exitCode: violations.length > 0 ? 1 : 0,
|
|
116
116
|
summary: violations.length > 0
|
|
117
|
-
? `note.link.validate: ${violations.length} violation
|
|
117
|
+
? `note.link.validate: ${violations.length} violation${violations.length === 1 ? "" : "s"} found`
|
|
118
118
|
: "note.link.validate: OK — 0 violations",
|
|
119
119
|
};
|
|
120
120
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"note-link-validate.js","sourceRoot":"","sources":["../../../src/validators/note-link-validate.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"note-link-validate.js","sourceRoot":"","sources":["../../../src/validators/note-link-validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ADR-0000
|
|
3
|
+
title: "Short imperative title"
|
|
4
|
+
# Lifecycle:
|
|
5
|
+
# proposed → reviewing → accepted → implemented
|
|
6
|
+
# any → superseded (requires supersededBy)
|
|
7
|
+
# any → rejected
|
|
8
|
+
status: proposed
|
|
9
|
+
scope: package
|
|
10
|
+
decider: architecture
|
|
11
|
+
createdAt: YYYY-MM-DD
|
|
12
|
+
updatedAt: YYYY-MM-DD
|
|
13
|
+
implementedAt:
|
|
14
|
+
closedAt:
|
|
15
|
+
supersedes: []
|
|
16
|
+
supersededBy:
|
|
17
|
+
related: []
|
|
18
|
+
# Set by the deciding human together with the status change.
|
|
19
|
+
# Draft scaffolds must keep this empty; do not prefill a default identity.
|
|
20
|
+
# Format: human:<handle>
|
|
21
|
+
reviewers: []
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# ADR-0000: Short imperative title
|
|
25
|
+
|
|
26
|
+
## Context
|
|
27
|
+
|
|
28
|
+
Brief description of the local situation, constraints, and RFC or DNA context that bounds the decision. Name actual packages, files, or components.
|
|
29
|
+
|
|
30
|
+
## Decision
|
|
31
|
+
|
|
32
|
+
A single sentence in the present tense stating the decision as a fact. Add 1-3 bullets clarifying scope or boundaries if needed.
|
|
33
|
+
|
|
34
|
+
## Justification
|
|
35
|
+
|
|
36
|
+
Forces and trade-offs that led to the decision: alternatives considered, constraints, alignment with existing architecture.
|
|
37
|
+
|
|
38
|
+
## Consequences
|
|
39
|
+
|
|
40
|
+
- Positive: what becomes simpler, safer, cheaper, or more predictable.
|
|
41
|
+
- Negative: trade-offs, limitations, operational overhead.
|
|
42
|
+
- Technical debt: what is knowingly postponed.
|
|
43
|
+
|
|
44
|
+
## Evolution
|
|
45
|
+
|
|
46
|
+
How the decision may change: thresholds that trigger revisiting it, metrics to watch, and — for post-hoc ADRs — references to commits or PRs that implemented it.
|
|
@@ -332,6 +332,6 @@ function stampFailResult(
|
|
|
332
332
|
violations,
|
|
333
333
|
},
|
|
334
334
|
exitCode: 1,
|
|
335
|
-
summary: `${prefix}adr.implement.stamp: ${violations.length} violation
|
|
335
|
+
summary: `${prefix}adr.implement.stamp: ${violations.length} violation${violations.length === 1 ? "" : "s"}`,
|
|
336
336
|
};
|
|
337
337
|
}
|
|
@@ -12,8 +12,11 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import fs from "node:fs/promises";
|
|
15
|
+
import { existsSync } from "node:fs";
|
|
15
16
|
import path from "node:path";
|
|
17
|
+
import { fileURLToPath } from "node:url";
|
|
16
18
|
import { toKebabCase } from "../../../src/utils/string-utils.ts";
|
|
19
|
+
import { resolveForgeRoot } from "../../../src/config/forge-config.ts";
|
|
17
20
|
import { listAdrFiles, readAndParseAdr } from "../frontmatter-io.ts";
|
|
18
21
|
import type {
|
|
19
22
|
ForgeCommandInput,
|
|
@@ -27,7 +30,13 @@ import type {
|
|
|
27
30
|
AdrStatus,
|
|
28
31
|
AdrScope,
|
|
29
32
|
} from "../types.ts";
|
|
30
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
ADR_DIR,
|
|
35
|
+
ADR_TEMPLATE_FILE,
|
|
36
|
+
ADR_TEMPLATE_FALLBACK_FILE,
|
|
37
|
+
ADR_SCOPES,
|
|
38
|
+
ADR_STATUSES,
|
|
39
|
+
} from "../types.ts";
|
|
31
40
|
|
|
32
41
|
function toIsoDate(d: Date): string {
|
|
33
42
|
return d.toISOString().slice(0, 10);
|
|
@@ -137,14 +146,13 @@ export async function runAdrCreate(
|
|
|
137
146
|
const nextSlug = `adr-${paddedNum}`;
|
|
138
147
|
const nextId = `ADR-${paddedNum}`;
|
|
139
148
|
|
|
140
|
-
const
|
|
141
|
-
const templatePath = path.join(workspaceRoot, templateRelPath);
|
|
149
|
+
const templatePath = resolveAdrTemplate(workspaceRoot);
|
|
142
150
|
let templateContent: string;
|
|
143
151
|
try {
|
|
144
152
|
templateContent = await fs.readFile(templatePath, "utf-8");
|
|
145
153
|
} catch {
|
|
146
154
|
throw new Error(
|
|
147
|
-
`ADR template not found at ${
|
|
155
|
+
`ADR template not found at ${templatePath}. Ensure docs/adrs/ contains the template.`,
|
|
148
156
|
);
|
|
149
157
|
}
|
|
150
158
|
|
|
@@ -205,3 +213,39 @@ export async function runAdrCreate(
|
|
|
205
213
|
summary: `Created ${nextId}: ${title}`,
|
|
206
214
|
};
|
|
207
215
|
}
|
|
216
|
+
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
// ADR template resolver — finds adr-0000-template.md from project docs/adrs/
|
|
219
|
+
// first (canonical location), then falls back to the forge package copy
|
|
220
|
+
// (npm consumers without a project-level template).
|
|
221
|
+
// ---------------------------------------------------------------------------
|
|
222
|
+
|
|
223
|
+
function resolveAdrTemplate(workspaceRoot: string): string {
|
|
224
|
+
// 1. Try project-level docs/adrs/adr-0000-template.md (canonical)
|
|
225
|
+
const projectPath = path.join(workspaceRoot, ADR_TEMPLATE_FILE);
|
|
226
|
+
if (existsSync(projectPath)) return projectPath;
|
|
227
|
+
|
|
228
|
+
// 2. Try forge root (monorepo or npm-installed) — fallback copy
|
|
229
|
+
try {
|
|
230
|
+
const forgeRoot = resolveForgeRoot(workspaceRoot);
|
|
231
|
+
const p = path.join(forgeRoot, ADR_TEMPLATE_FALLBACK_FILE);
|
|
232
|
+
if (existsSync(p)) return p;
|
|
233
|
+
} catch {
|
|
234
|
+
// forge root not resolvable — fall through to module-relative search
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// 3. Fallback: walk up from this module's location to find os/adr/adr-0000-template.md
|
|
238
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
239
|
+
let dir = here;
|
|
240
|
+
for (let i = 0; i < 10; i++) {
|
|
241
|
+
const candidate = path.join(dir, "os", "adr", "adr-0000-template.md");
|
|
242
|
+
if (existsSync(candidate)) return candidate;
|
|
243
|
+
const parent = path.dirname(dir);
|
|
244
|
+
if (parent === dir) break;
|
|
245
|
+
dir = parent;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
throw new Error(
|
|
249
|
+
`ADR template not found. Tried ${ADR_TEMPLATE_FILE} relative to ${workspaceRoot}, forge root, and module-relative search from ${here}.`,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
@@ -135,10 +135,14 @@ export async function runAdrValidate(
|
|
|
135
135
|
}
|
|
136
136
|
const errorCount = violations.filter((v) => v.severity === "error").length;
|
|
137
137
|
const warnCount = violations.filter((v) => v.severity === "warning").length;
|
|
138
|
+
const parts: string[] = [];
|
|
139
|
+
if (errorCount > 0) parts.push(`${errorCount} error${errorCount === 1 ? "" : "s"}`);
|
|
140
|
+
if (warnCount > 0) parts.push(`${warnCount} warning${warnCount === 1 ? "" : "s"}`);
|
|
141
|
+
const counts = parts.join(", ");
|
|
138
142
|
if (errorCount > 0) {
|
|
139
|
-
logger.error(
|
|
143
|
+
logger.error(counts);
|
|
140
144
|
} else {
|
|
141
|
-
logger.warn(`${
|
|
145
|
+
logger.warn(`${counts} — passed`);
|
|
142
146
|
}
|
|
143
147
|
}
|
|
144
148
|
}
|
|
@@ -152,12 +156,12 @@ export async function runAdrValidate(
|
|
|
152
156
|
},
|
|
153
157
|
exitCode: hasErrors ? 1 : 0,
|
|
154
158
|
summary: hasErrors
|
|
155
|
-
? `${violations.filter((v) => v.severity === "error").length} error(
|
|
159
|
+
? `${violations.filter((v) => v.severity === "error").length} error${violations.filter((v) => v.severity === "error").length === 1 ? "" : "s"} found`
|
|
156
160
|
: `All ${filesToValidate.length} ADR(s) passed validation`,
|
|
157
161
|
nextSteps: hasErrors
|
|
158
162
|
? [
|
|
159
163
|
{
|
|
160
|
-
action: `Fix the ${violations.filter((v) => v.severity === "error").length} error(
|
|
164
|
+
action: `Fix the ${violations.filter((v) => v.severity === "error").length} error${violations.filter((v) => v.severity === "error").length === 1 ? "" : "s"} above, then re-run: pnpm exec forge run adr.validate`,
|
|
161
165
|
kind: "required",
|
|
162
166
|
},
|
|
163
167
|
]
|
package/os/adr/types.ts
CHANGED
|
@@ -92,6 +92,7 @@ export interface AdrCreateResult {
|
|
|
92
92
|
|
|
93
93
|
export const ADR_DIR = "docs/adrs";
|
|
94
94
|
export const ADR_TEMPLATE_FILE = "docs/adrs/adr-0000-template.md";
|
|
95
|
+
export const ADR_TEMPLATE_FALLBACK_FILE = "os/adr/adr-0000-template.md";
|
|
95
96
|
export const ADR_ID_PATTERN = /^ADR-\d{4}$/;
|
|
96
97
|
|
|
97
98
|
export const ADR_REQUIRED_SECTIONS = [
|
|
@@ -199,12 +199,16 @@ export async function runPackageHealth(
|
|
|
199
199
|
`forge.package.health: all ${packagesChecked} published package(s) healthy.`,
|
|
200
200
|
);
|
|
201
201
|
} else if (passed) {
|
|
202
|
-
logger.
|
|
203
|
-
`forge.package.health: ${packagesChecked} package(s) checked, ${warnings.length} warning
|
|
202
|
+
logger.warn(
|
|
203
|
+
`forge.package.health: ${packagesChecked} package(s) checked, ${warnings.length} warning${warnings.length === 1 ? "" : "s"}.`,
|
|
204
204
|
);
|
|
205
205
|
} else {
|
|
206
|
+
const parts: string[] = [];
|
|
207
|
+
parts.push(`${errors.length} error${errors.length === 1 ? "" : "s"}`);
|
|
208
|
+
if (warnings.length > 0)
|
|
209
|
+
parts.push(`${warnings.length} warning${warnings.length === 1 ? "" : "s"}`);
|
|
206
210
|
logger.error(
|
|
207
|
-
`forge.package.health: ${
|
|
211
|
+
`forge.package.health: ${parts.join(", ")} across ${packagesChecked} package(s).`,
|
|
208
212
|
);
|
|
209
213
|
}
|
|
210
214
|
}
|
|
@@ -220,9 +224,9 @@ export async function runPackageHealth(
|
|
|
220
224
|
exitCode: passed ? 0 : 1,
|
|
221
225
|
summary: passed
|
|
222
226
|
? warnings.length > 0
|
|
223
|
-
? `All ${packagesChecked} package(s) passed with ${warnings.length} warning
|
|
227
|
+
? `All ${packagesChecked} package(s) passed with ${warnings.length} warning${warnings.length === 1 ? "" : "s"}.`
|
|
224
228
|
: `All ${packagesChecked} package(s) healthy.`
|
|
225
|
-
: `${errors.length} error
|
|
229
|
+
: `${errors.length} error${errors.length === 1 ? "" : "s"} found across ${packagesChecked} package(s).`,
|
|
226
230
|
nextSteps: errors.map((e) => ({
|
|
227
231
|
action: e.fixHint ?? e.message,
|
|
228
232
|
kind: "required" as const,
|
|
@@ -283,7 +283,9 @@ export async function runPinnedValidate(
|
|
|
283
283
|
logger.success("pinned.validate: no violations");
|
|
284
284
|
}
|
|
285
285
|
} else {
|
|
286
|
-
logger.error(
|
|
286
|
+
logger.error(
|
|
287
|
+
`pinned.validate: ${remainingViolations.length} violation${remainingViolations.length === 1 ? "" : "s"} found`,
|
|
288
|
+
);
|
|
287
289
|
for (const v of remainingViolations) {
|
|
288
290
|
logger.error(` ${v.operation}: ${v.path} (mode: ${v.mode}) — ${v.reason}`);
|
|
289
291
|
}
|
|
@@ -296,6 +298,6 @@ export async function runPinnedValidate(
|
|
|
296
298
|
summary:
|
|
297
299
|
status === "pass"
|
|
298
300
|
? `No violations${appliedOverrides.length > 0 ? ` (${appliedOverrides.length} override(s) applied)` : ""}`
|
|
299
|
-
: `${remainingViolations.length} violation
|
|
301
|
+
: `${remainingViolations.length} violation${remainingViolations.length === 1 ? "" : "s"} found`,
|
|
300
302
|
};
|
|
301
303
|
}
|
|
@@ -426,10 +426,10 @@ function completeFail(
|
|
|
426
426
|
violations,
|
|
427
427
|
},
|
|
428
428
|
exitCode: 1,
|
|
429
|
-
summary: `program.packet.complete: ${packetId} failed with ${violations.length} violation
|
|
429
|
+
summary: `program.packet.complete: ${packetId} failed with ${violations.length} violation${violations.length === 1 ? "" : "s"}`,
|
|
430
430
|
nextSteps: [
|
|
431
431
|
{
|
|
432
|
-
action: `Fix the ${violations.length} violation
|
|
432
|
+
action: `Fix the ${violations.length} violation${violations.length === 1 ? "" : "s"} above, then re-run: pnpm exec forge run program.packet.complete --packet ${packetId}`,
|
|
433
433
|
kind: "required",
|
|
434
434
|
},
|
|
435
435
|
],
|
|
@@ -434,6 +434,6 @@ function leaseFail(
|
|
|
434
434
|
violations,
|
|
435
435
|
},
|
|
436
436
|
exitCode: 1,
|
|
437
|
-
summary: `program.packet.lease: ${packetId} ${action} failed with ${violations.length} violation
|
|
437
|
+
summary: `program.packet.lease: ${packetId} ${action} failed with ${violations.length} violation${violations.length === 1 ? "" : "s"}`,
|
|
438
438
|
};
|
|
439
439
|
}
|
|
@@ -248,10 +248,10 @@ function sealFail(
|
|
|
248
248
|
violations,
|
|
249
249
|
},
|
|
250
250
|
exitCode: 1,
|
|
251
|
-
summary: `program.packet.seal: ${packetId} failed with ${violations.length} violation
|
|
251
|
+
summary: `program.packet.seal: ${packetId} failed with ${violations.length} violation${violations.length === 1 ? "" : "s"}`,
|
|
252
252
|
nextSteps: [
|
|
253
253
|
{
|
|
254
|
-
action: `Fix the ${violations.length} violation
|
|
254
|
+
action: `Fix the ${violations.length} violation${violations.length === 1 ? "" : "s"} above, then re-run: pnpm exec forge run program.packet.seal --packet ${packetId}`,
|
|
255
255
|
kind: "required",
|
|
256
256
|
},
|
|
257
257
|
],
|
|
@@ -186,7 +186,7 @@ export async function runValidate(
|
|
|
186
186
|
summary:
|
|
187
187
|
status === "pass"
|
|
188
188
|
? `program.packet.validate: ${packetId} passed (${phase})`
|
|
189
|
-
: `program.packet.validate: ${packetId} failed with ${violations.length} violation
|
|
189
|
+
: `program.packet.validate: ${packetId} failed with ${violations.length} violation${violations.length === 1 ? "" : "s"}`,
|
|
190
190
|
};
|
|
191
191
|
}
|
|
192
192
|
|
|
@@ -208,10 +208,10 @@ function failResult(
|
|
|
208
208
|
violations,
|
|
209
209
|
},
|
|
210
210
|
exitCode: 1,
|
|
211
|
-
summary: `program.packet.validate: ${packetId} failed with ${violations.length} violation
|
|
211
|
+
summary: `program.packet.validate: ${packetId} failed with ${violations.length} violation${violations.length === 1 ? "" : "s"}`,
|
|
212
212
|
nextSteps: [
|
|
213
213
|
{
|
|
214
|
-
action: `Fix the ${violations.length} violation
|
|
214
|
+
action: `Fix the ${violations.length} violation${violations.length === 1 ? "" : "s"} above, then re-run: pnpm exec forge run program.packet.validate --packet ${packetId}`,
|
|
215
215
|
kind: "required",
|
|
216
216
|
},
|
|
217
217
|
],
|
package/os/rfc/dna-trace.ts
CHANGED
|
@@ -233,7 +233,7 @@ export async function runRfcDnaTraceValidate(
|
|
|
233
233
|
diagnostics,
|
|
234
234
|
},
|
|
235
235
|
exitCode: hasErrors ? 1 : 0,
|
|
236
|
-
summary: `rfc.dna.trace.validate: ${registryIds.size} DNA invariants, ${tracedDnaCount} traced, ${diagnostics.filter((d) => d.severity === "error").length} error(s
|
|
236
|
+
summary: `rfc.dna.trace.validate: ${registryIds.size} DNA invariants, ${tracedDnaCount} traced, ${diagnostics.filter((d) => d.severity === "error").length} error${diagnostics.filter((d) => d.severity === "error").length === 1 ? "" : "s"}`,
|
|
237
237
|
};
|
|
238
238
|
}
|
|
239
239
|
|
package/os/rfc/handlers/check.ts
CHANGED
|
@@ -219,7 +219,7 @@ export async function runRfcCheck(
|
|
|
219
219
|
for (const v of violations) {
|
|
220
220
|
logger.error(`[${v.kind}] ${v.rfcId}: ${v.message}`);
|
|
221
221
|
}
|
|
222
|
-
logger.error(`${violations.length} violation
|
|
222
|
+
logger.error(`${violations.length} violation${violations.length === 1 ? "" : "s"} found`);
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
|
|
@@ -232,12 +232,12 @@ export async function runRfcCheck(
|
|
|
232
232
|
},
|
|
233
233
|
exitCode: hasErrors ? 1 : 0,
|
|
234
234
|
summary: hasErrors
|
|
235
|
-
? `${violations.length} artifact violation
|
|
235
|
+
? `${violations.length} artifact violation${violations.length === 1 ? "" : "s"} found across ${checkedRfcs} RFC(s)`
|
|
236
236
|
: `All ${checkedRfcs} RFC(s) passed artifact check`,
|
|
237
237
|
nextSteps: hasErrors
|
|
238
238
|
? [
|
|
239
239
|
{
|
|
240
|
-
action: `Fix the ${violations.length} artifact violation
|
|
240
|
+
action: `Fix the ${violations.length} artifact violation${violations.length === 1 ? "" : "s"} above, then re-run: pnpm exec forge run rfc.check`,
|
|
241
241
|
kind: "required",
|
|
242
242
|
},
|
|
243
243
|
]
|
|
@@ -516,6 +516,6 @@ function stampFailResult(
|
|
|
516
516
|
violations,
|
|
517
517
|
},
|
|
518
518
|
exitCode: 1,
|
|
519
|
-
summary: `${prefix}rfc.implement.stamp: ${violations.length} violation
|
|
519
|
+
summary: `${prefix}rfc.implement.stamp: ${violations.length} violation${violations.length === 1 ? "" : "s"}`,
|
|
520
520
|
};
|
|
521
521
|
}
|
|
@@ -175,7 +175,7 @@ export async function runRfcIndexValidate(
|
|
|
175
175
|
return {
|
|
176
176
|
data: result,
|
|
177
177
|
exitCode: 1,
|
|
178
|
-
summary: "1 error
|
|
178
|
+
summary: "1 error found",
|
|
179
179
|
};
|
|
180
180
|
}
|
|
181
181
|
|
|
@@ -196,7 +196,7 @@ export async function runRfcIndexValidate(
|
|
|
196
196
|
return {
|
|
197
197
|
data: result,
|
|
198
198
|
exitCode: 1,
|
|
199
|
-
summary: "1 error
|
|
199
|
+
summary: "1 error found",
|
|
200
200
|
};
|
|
201
201
|
}
|
|
202
202
|
|
|
@@ -221,7 +221,7 @@ export async function runRfcIndexValidate(
|
|
|
221
221
|
for (const v of violations) {
|
|
222
222
|
logger.error(`[${v.rule}] ${v.message}`);
|
|
223
223
|
}
|
|
224
|
-
logger.error(`${violations.length} error
|
|
224
|
+
logger.error(`${violations.length} error${violations.length === 1 ? "" : "s"} found`);
|
|
225
225
|
} else {
|
|
226
226
|
logger.success(`Index valid — ${indexCount} entries match ${fileCount} RFC files.`);
|
|
227
227
|
}
|
|
@@ -231,7 +231,7 @@ export async function runRfcIndexValidate(
|
|
|
231
231
|
data: result,
|
|
232
232
|
exitCode: hasErrors ? 1 : 0,
|
|
233
233
|
summary: hasErrors
|
|
234
|
-
? `${violations.length} error
|
|
234
|
+
? `${violations.length} error${violations.length === 1 ? "" : "s"} found`
|
|
235
235
|
: `Index valid — ${indexCount} entries match ${fileCount} RFC files`,
|
|
236
236
|
};
|
|
237
237
|
}
|
|
@@ -243,7 +243,7 @@ export async function runRfcCommandLifecycleValidate(
|
|
|
243
243
|
},
|
|
244
244
|
exitCode: hasErrors ? 1 : 0,
|
|
245
245
|
summary: hasErrors
|
|
246
|
-
? `${violations.filter((v) => v.severity === "error").length} command lifecycle error(
|
|
246
|
+
? `${violations.filter((v) => v.severity === "error").length} command lifecycle error${violations.filter((v) => v.severity === "error").length === 1 ? "" : "s"} found`
|
|
247
247
|
: `All ${checkedCount} RFC(s) passed command lifecycle validation`,
|
|
248
248
|
};
|
|
249
249
|
}
|
|
@@ -142,10 +142,14 @@ export async function runRfcValidate(
|
|
|
142
142
|
}
|
|
143
143
|
const errorCount = violations.filter((v) => v.severity === "error").length;
|
|
144
144
|
const warnCount = violations.filter((v) => v.severity === "warning").length;
|
|
145
|
+
const parts: string[] = [];
|
|
146
|
+
if (errorCount > 0) parts.push(`${errorCount} error${errorCount === 1 ? "" : "s"}`);
|
|
147
|
+
if (warnCount > 0) parts.push(`${warnCount} warning${warnCount === 1 ? "" : "s"}`);
|
|
148
|
+
const counts = parts.join(", ");
|
|
145
149
|
if (errorCount > 0) {
|
|
146
|
-
logger.error(
|
|
150
|
+
logger.error(counts);
|
|
147
151
|
} else {
|
|
148
|
-
logger.warn(`${
|
|
152
|
+
logger.warn(`${counts} — passed`);
|
|
149
153
|
}
|
|
150
154
|
}
|
|
151
155
|
}
|
|
@@ -160,12 +164,12 @@ export async function runRfcValidate(
|
|
|
160
164
|
},
|
|
161
165
|
exitCode: hasErrors ? 1 : 0,
|
|
162
166
|
summary: hasErrors
|
|
163
|
-
? `${violations.filter((v) => v.severity === "error").length} error(
|
|
167
|
+
? `${violations.filter((v) => v.severity === "error").length} error${violations.filter((v) => v.severity === "error").length === 1 ? "" : "s"} found`
|
|
164
168
|
: `All ${filesToValidate.length} RFC(s) passed validation`,
|
|
165
169
|
nextSteps: hasErrors
|
|
166
170
|
? [
|
|
167
171
|
{
|
|
168
|
-
action: `Fix the ${violations.filter((v) => v.severity === "error").length} error(
|
|
172
|
+
action: `Fix the ${violations.filter((v) => v.severity === "error").length} error${violations.filter((v) => v.severity === "error").length === 1 ? "" : "s"} above, then re-run: pnpm exec forge run rfc.validate`,
|
|
169
173
|
kind: "required",
|
|
170
174
|
},
|
|
171
175
|
]
|
|
@@ -8,10 +8,9 @@ kind: architecture
|
|
|
8
8
|
scope: workspace
|
|
9
9
|
owners:
|
|
10
10
|
- architecture
|
|
11
|
-
# Set by the deciding human together with the status change
|
|
11
|
+
# Set by the deciding human together with the status change.
|
|
12
12
|
# Draft scaffolds must keep this empty; do not prefill a default identity.
|
|
13
|
-
# Format: human:<handle>
|
|
14
|
-
# Default reviewer when none is specified by the operator: human:andrii-syrokomskyi
|
|
13
|
+
# Format: human:<handle>
|
|
15
14
|
reviewers: []
|
|
16
15
|
createdAt: YYYY-MM-DD
|
|
17
16
|
updatedAt: YYYY-MM-DD
|
|
@@ -26,8 +25,6 @@ related:
|
|
|
26
25
|
# - DNA-1
|
|
27
26
|
# - AP-3
|
|
28
27
|
# - RFC-0005
|
|
29
|
-
# - PAGE-MANDATORY-ARTIFACTS
|
|
30
|
-
# - COMPONENT-THREE-WAY-MIRROR
|
|
31
28
|
# RFC-0331: DNA invariants this RFC implements, protects, or extends.
|
|
32
29
|
# Required for architecture/contract RFCs created on or after 2026-07-07.
|
|
33
30
|
# Entries must match ^DNA-\d+$ and exist in docs/architecture-dna.md.
|
|
@@ -55,17 +52,16 @@ appsImpacted: []
|
|
|
55
52
|
packagesImpacted: []
|
|
56
53
|
successSignals: []
|
|
57
54
|
nonGoals: []
|
|
58
|
-
#
|
|
59
|
-
# via `pnpm exec
|
|
60
|
-
# automatically inside build pipelines).
|
|
61
|
-
# docs/rfcs/rfc-0268-make-rfc-acceptance-criteria-machine-checkable.md.
|
|
55
|
+
# OPTIONAL machine-checkable acceptance probes, executed on-demand
|
|
56
|
+
# via `pnpm exec forge rfc.acceptance.run --id <this-rfc-id>` (never
|
|
57
|
+
# automatically inside build pipelines).
|
|
62
58
|
# acceptance:
|
|
63
59
|
# - probe: run
|
|
64
|
-
# command: "
|
|
60
|
+
# command: "pnpm exec forge some.command.validate"
|
|
65
61
|
# expect:
|
|
66
62
|
# exitCode: 0
|
|
67
63
|
# - probe: file-exists
|
|
68
|
-
# path: "packages/
|
|
64
|
+
# path: "packages/my-package/src/some-new-module.ts"
|
|
69
65
|
# - probe: command-registered
|
|
70
66
|
# name: "some.new.command"
|
|
71
67
|
# - probe: file-contains
|
|
@@ -119,8 +115,8 @@ nonGoals: []
|
|
|
119
115
|
<!-- Show the exact command(s) as a user would type them:
|
|
120
116
|
|
|
121
117
|
```sh
|
|
122
|
-
pnpm exec
|
|
123
|
-
pnpm exec
|
|
118
|
+
pnpm exec forge domain.command
|
|
119
|
+
pnpm exec forge domain.command --json
|
|
124
120
|
```
|
|
125
121
|
|
|
126
122
|
Describe flags, arguments, and scope (app | workspace).
|
|
@@ -150,7 +146,7 @@ interface ExampleResult {
|
|
|
150
146
|
|
|
151
147
|
| Path | Role |
|
|
152
148
|
|---|---|
|
|
153
|
-
| `src
|
|
149
|
+
| `src/**/*.ts` | Scanned for violations |
|
|
154
150
|
| `docs/rfcs/index.json` | Updated by rfc.index.generate |
|
|
155
151
|
-->
|
|
156
152
|
|
|
@@ -163,7 +159,7 @@ interface ExampleResult {
|
|
|
163
159
|
"command": "domain.command",
|
|
164
160
|
"status": "fail",
|
|
165
161
|
"violations": [
|
|
166
|
-
{ "file": "src/
|
|
162
|
+
{ "file": "src/some-file.ts", "rule": "missing-schema", "message": "..." }
|
|
167
163
|
]
|
|
168
164
|
}
|
|
169
165
|
```
|
|
@@ -216,12 +212,12 @@ interface ExampleResult {
|
|
|
216
212
|
|
|
217
213
|
- Agents MAY implement code changes ONLY when this RFC has status: accepted (or implemented).
|
|
218
214
|
- Agents MAY transition this RFC from `accepted` to `implemented` per RFC-0224 preconditions; reference this RFC ID in commits.
|
|
219
|
-
- For RFCs
|
|
220
|
-
`
|
|
221
|
-
in the same commit
|
|
215
|
+
- For RFCs with acceptance probes: before stamping `implemented`, run
|
|
216
|
+
`pnpm exec forge rfc.verification.emit --id <this-rfc-id>` and commit the evidence file
|
|
217
|
+
in the same commit.
|
|
222
218
|
- Agents MUST NOT weaken or remove enforcement rules established by this RFC
|
|
223
219
|
without a new RFC that supersedes it.
|
|
224
220
|
- If implementation reveals an invariant conflict, run
|
|
225
|
-
`
|
|
226
|
-
instead of working around it
|
|
221
|
+
`pnpm exec forge rfc.supersede.propose --id <this-rfc-id> --reason "..." --invariant "DNA-N"`
|
|
222
|
+
instead of working around it.
|
|
227
223
|
-->
|
|
@@ -227,10 +227,14 @@ export async function runSessionValidate(
|
|
|
227
227
|
}
|
|
228
228
|
const errorCount = violations.filter((v) => v.severity === "error").length;
|
|
229
229
|
const warnCount = violations.filter((v) => v.severity === "warning").length;
|
|
230
|
+
const parts: string[] = [];
|
|
231
|
+
if (errorCount > 0) parts.push(`${errorCount} error${errorCount === 1 ? "" : "s"}`);
|
|
232
|
+
if (warnCount > 0) parts.push(`${warnCount} warning${warnCount === 1 ? "" : "s"}`);
|
|
233
|
+
const counts = parts.join(", ");
|
|
230
234
|
if (errorCount > 0) {
|
|
231
|
-
logger.error(
|
|
235
|
+
logger.error(counts);
|
|
232
236
|
} else {
|
|
233
|
-
logger.warn(`${
|
|
237
|
+
logger.warn(`${counts} — passed`);
|
|
234
238
|
}
|
|
235
239
|
}
|
|
236
240
|
}
|
|
@@ -244,12 +248,12 @@ export async function runSessionValidate(
|
|
|
244
248
|
},
|
|
245
249
|
exitCode: hasErrors ? 1 : 0,
|
|
246
250
|
summary: hasErrors
|
|
247
|
-
? `${violations.filter((v) => v.severity === "error").length} error(
|
|
251
|
+
? `${violations.filter((v) => v.severity === "error").length} error${violations.filter((v) => v.severity === "error").length === 1 ? "" : "s"} found`
|
|
248
252
|
: `All ${filesToValidate.length} session file(s) passed validation`,
|
|
249
253
|
nextSteps: hasErrors
|
|
250
254
|
? [
|
|
251
255
|
{
|
|
252
|
-
action: `Fix the ${violations.filter((v) => v.severity === "error").length} error(
|
|
256
|
+
action: `Fix the ${violations.filter((v) => v.severity === "error").length} error${violations.filter((v) => v.severity === "error").length === 1 ? "" : "s"} above, then re-run: pnpm exec forge run session.validate`,
|
|
253
257
|
kind: "required",
|
|
254
258
|
},
|
|
255
259
|
]
|
|
@@ -151,7 +151,7 @@ export async function runSpecLiveValidate(
|
|
|
151
151
|
|
|
152
152
|
if (outputFormat === "pretty") {
|
|
153
153
|
if (hasFailures) {
|
|
154
|
-
logger.error(`spec.live.validate: ${violations.length} violation
|
|
154
|
+
logger.error(`spec.live.validate: ${violations.length} violation${violations.length === 1 ? "" : "s"} across ${specsChecked} spec(s)`);
|
|
155
155
|
for (const v of violations) {
|
|
156
156
|
logger.error(` ${v.rule}: ${v.message}`);
|
|
157
157
|
}
|
|
@@ -164,7 +164,7 @@ export async function runSpecLiveValidate(
|
|
|
164
164
|
data: result,
|
|
165
165
|
exitCode: hasFailures ? 1 : 0,
|
|
166
166
|
summary: hasFailures
|
|
167
|
-
? `spec.live.validate: ${violations.length} violation
|
|
167
|
+
? `spec.live.validate: ${violations.length} violation${violations.length === 1 ? "" : "s"}`
|
|
168
168
|
: `spec.live.validate: ${specsChecked} spec(s) — pass`,
|
|
169
169
|
};
|
|
170
170
|
}
|
package/os/spec/spec-validate.ts
CHANGED
|
@@ -490,7 +490,7 @@ export async function runSpecValidate(
|
|
|
490
490
|
if (result.violations.length === 0) {
|
|
491
491
|
logger.success(`spec.validate: ${result.id} — pass`);
|
|
492
492
|
} else {
|
|
493
|
-
logger.error(`spec.validate: ${result.id} — ${result.violations.length} violation
|
|
493
|
+
logger.error(`spec.validate: ${result.id} — ${result.violations.length} violation${result.violations.length === 1 ? "" : "s"}`);
|
|
494
494
|
for (const v of result.violations) {
|
|
495
495
|
logger.error(` ${v.rule}: ${v.message}`);
|
|
496
496
|
}
|
package/os/workflow/handlers.ts
CHANGED
|
@@ -307,7 +307,7 @@ export async function runWorkflowLint(
|
|
|
307
307
|
exitCode: violations.length > 0 ? 1 : 0,
|
|
308
308
|
summary:
|
|
309
309
|
violations.length > 0
|
|
310
|
-
? `workflow.lint: ${violations.length} violation
|
|
310
|
+
? `workflow.lint: ${violations.length} violation${violations.length === 1 ? "" : "s"}`
|
|
311
311
|
: `workflow.lint: ${workflows.length} workflow file(s) valid`,
|
|
312
312
|
};
|
|
313
313
|
}
|