@mmnto/cli 1.15.0 → 1.15.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/dist/commands/adr.d.ts +15 -0
- package/dist/commands/adr.d.ts.map +1 -0
- package/dist/commands/adr.js +24 -0
- package/dist/commands/adr.js.map +1 -0
- package/dist/commands/adr.test.d.ts +2 -0
- package/dist/commands/adr.test.d.ts.map +1 -0
- package/dist/commands/adr.test.js +70 -0
- package/dist/commands/adr.test.js.map +1 -0
- package/dist/commands/proposal.d.ts +15 -0
- package/dist/commands/proposal.d.ts.map +1 -0
- package/dist/commands/proposal.js +24 -0
- package/dist/commands/proposal.js.map +1 -0
- package/dist/commands/proposal.test.d.ts +2 -0
- package/dist/commands/proposal.test.d.ts.map +1 -0
- package/dist/commands/proposal.test.js +66 -0
- package/dist/commands/proposal.test.js.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/governance.d.ts +175 -0
- package/dist/utils/governance.d.ts.map +1 -0
- package/dist/utils/governance.js +327 -0
- package/dist/utils/governance.js.map +1 -0
- package/dist/utils/governance.test.d.ts +2 -0
- package/dist/utils/governance.test.d.ts.map +1 -0
- package/dist/utils/governance.test.js +525 -0
- package/dist/utils/governance.test.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Governance-artifact scaffolding utilities (mmnto/totem#1288).
|
|
3
|
+
*
|
|
4
|
+
* Shared helpers for the `totem proposal new` and `totem adr new` commands.
|
|
5
|
+
* Nothing in this module carries module-level state — every helper takes
|
|
6
|
+
* its context via arguments so the tests can exercise both the submodule
|
|
7
|
+
* (`<totem>/.strategy/`) and the standalone (strategy-repo root) cases.
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'node:fs';
|
|
10
|
+
import * as path from 'node:path';
|
|
11
|
+
import { resolveGitRoot, safeExec, TotemError } from '@mmnto/totem';
|
|
12
|
+
import { log } from '../ui.js';
|
|
13
|
+
const STRATEGY_SUBDIR = '.strategy';
|
|
14
|
+
function targetSubpath(type) {
|
|
15
|
+
return type === 'proposal' ? path.join('proposals', 'active') : 'adr';
|
|
16
|
+
}
|
|
17
|
+
function templateFilename(type) {
|
|
18
|
+
return type === 'proposal' ? 'proposal.md' : 'adr.md';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve governance paths for the current invocation.
|
|
22
|
+
*
|
|
23
|
+
* Two supported contexts:
|
|
24
|
+
* 1. **Submodule case** — `<gitRoot>/.strategy/` exists. Used when Totem is
|
|
25
|
+
* the parent repo and `.strategy/` is a submodule/worktree.
|
|
26
|
+
* 2. **Standalone case** — `<gitRoot>` itself is the strategy repo
|
|
27
|
+
* (`proposals/active/` sits at the repo root). Used when the CLI is run
|
|
28
|
+
* from inside the strategy repo directly.
|
|
29
|
+
*
|
|
30
|
+
* Throws `TotemError` when cwd is not inside a git repo, or when neither
|
|
31
|
+
* layout can be detected.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveGovernancePaths(cwd, type) {
|
|
34
|
+
const gitRoot = resolveGitRoot(cwd);
|
|
35
|
+
if (gitRoot === null) {
|
|
36
|
+
throw new TotemError('CONFIG_MISSING', `Not inside a git repository: ${cwd}`, 'Run this command from inside a Totem or Totem-strategy repository checkout.');
|
|
37
|
+
}
|
|
38
|
+
const submoduleRoot = path.join(gitRoot, STRATEGY_SUBDIR);
|
|
39
|
+
const submoduleHasProposals = fs.existsSync(path.join(submoduleRoot, 'proposals'));
|
|
40
|
+
const submoduleHasAdr = fs.existsSync(path.join(submoduleRoot, 'adr'));
|
|
41
|
+
const standaloneHasProposals = fs.existsSync(path.join(gitRoot, 'proposals'));
|
|
42
|
+
const standaloneHasAdr = fs.existsSync(path.join(gitRoot, 'adr'));
|
|
43
|
+
let rootDir;
|
|
44
|
+
if (submoduleHasProposals || submoduleHasAdr) {
|
|
45
|
+
rootDir = submoduleRoot;
|
|
46
|
+
}
|
|
47
|
+
else if (standaloneHasProposals || standaloneHasAdr) {
|
|
48
|
+
rootDir = gitRoot;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
throw new TotemError('CONFIG_MISSING', `No Totem-strategy layout found under ${gitRoot}.`, 'Expected either a `.strategy/` submodule or top-level `proposals/` and `adr/` directories. Clone or link the strategy repo first.');
|
|
52
|
+
}
|
|
53
|
+
const targetDir = path.join(rootDir, targetSubpath(type));
|
|
54
|
+
const templatePath = path.join(rootDir, 'templates', templateFilename(type));
|
|
55
|
+
const dashboardFile = path.join(rootDir, 'README.md');
|
|
56
|
+
return {
|
|
57
|
+
rootDir: path.normalize(rootDir),
|
|
58
|
+
targetDir: path.normalize(targetDir),
|
|
59
|
+
templatePath: path.normalize(templatePath),
|
|
60
|
+
dashboardFile: path.normalize(dashboardFile),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// ─── Auto-increment + filename sanitization ─────────────
|
|
64
|
+
const ARTIFACT_FILENAME_RE = /^(\d{3})-(.+)\.md$/;
|
|
65
|
+
const MAX_ARTIFACT_ID = 999;
|
|
66
|
+
/**
|
|
67
|
+
* Scan `targetDir` for `NNN-slug.md` files, parse the prefix to an int,
|
|
68
|
+
* and return `(max + 1)` zero-padded to three digits.
|
|
69
|
+
*
|
|
70
|
+
* Returns `'001'` when the directory is missing or contains no matching
|
|
71
|
+
* files. Files that do not match `^(\d{3})-(.+)\.md$` are ignored so
|
|
72
|
+
* README.md or non-padded prefixes (e.g. `42-x.md`) do not pollute the
|
|
73
|
+
* count. Throws `TotemError` when the next id would exceed 999.
|
|
74
|
+
*/
|
|
75
|
+
export function getNextArtifactId(targetDir) {
|
|
76
|
+
if (!fs.existsSync(targetDir)) {
|
|
77
|
+
return '001';
|
|
78
|
+
}
|
|
79
|
+
let highest = 0;
|
|
80
|
+
const entries = fs.readdirSync(targetDir);
|
|
81
|
+
for (const entry of entries) {
|
|
82
|
+
const match = ARTIFACT_FILENAME_RE.exec(entry);
|
|
83
|
+
if (!match)
|
|
84
|
+
continue;
|
|
85
|
+
const parsed = parseInt(match[1], 10);
|
|
86
|
+
if (Number.isFinite(parsed) && parsed > highest) {
|
|
87
|
+
highest = parsed;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const next = highest + 1;
|
|
91
|
+
if (next > MAX_ARTIFACT_ID) {
|
|
92
|
+
throw new TotemError('CONFIG_INVALID', `NNN-prefix format saturated at ${targetDir} (highest id is ${highest}).`, 'Archive older artifacts or extend the numbering scheme before adding more.');
|
|
93
|
+
}
|
|
94
|
+
return String(next).padStart(3, '0');
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Build the final artifact filename from a numeric id and a raw title.
|
|
98
|
+
*
|
|
99
|
+
* Sanitization: lowercase, any non-alphanumeric run becomes a single hyphen,
|
|
100
|
+
* leading/trailing hyphens are stripped. Throws `TotemError` when the
|
|
101
|
+
* sanitized slug is empty — the error fires BEFORE any filesystem write so
|
|
102
|
+
* the caller never strands a half-written artifact.
|
|
103
|
+
*/
|
|
104
|
+
export function formatArtifactFilename(id, title) {
|
|
105
|
+
const slug = title
|
|
106
|
+
.toLowerCase()
|
|
107
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
108
|
+
.replace(/^-+|-+$/g, '');
|
|
109
|
+
if (slug.length === 0) {
|
|
110
|
+
throw new TotemError('CONFIG_INVALID', `Title "${title}" produces an empty slug.`, 'Titles must contain at least one alphanumeric character.');
|
|
111
|
+
}
|
|
112
|
+
return `${id}-${slug}.md`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Sanitize a raw title for safe inclusion in the scaffolded markdown body.
|
|
116
|
+
*
|
|
117
|
+
* Strips C0 control characters and `DEL` (0x00-0x1F, 0x7F) — most notably
|
|
118
|
+
* newlines, carriage returns, and tabs — then collapses any remaining run
|
|
119
|
+
* of whitespace to a single space and trims the edges. Without this pass,
|
|
120
|
+
* a title like `Fix\n## Fake Heading` would inject a fresh markdown block
|
|
121
|
+
* into the scaffolded artifact, shifting document structure out of the
|
|
122
|
+
* scaffolder's control. The `#` character itself is allowed through on
|
|
123
|
+
* purpose: a single-line heading that contains `#` characters stays a
|
|
124
|
+
* single h1 heading in markdown.
|
|
125
|
+
*/
|
|
126
|
+
export function sanitizeArtifactTitle(title) {
|
|
127
|
+
return (title
|
|
128
|
+
// eslint-disable-next-line no-control-regex -- intentional: strip ASCII C0 controls + DEL
|
|
129
|
+
.replace(/[\x00-\x1F\x7F]+/g, ' ')
|
|
130
|
+
.replace(/\s+/g, ' ')
|
|
131
|
+
.trim());
|
|
132
|
+
}
|
|
133
|
+
// ─── Template engine ────────────────────────────────────
|
|
134
|
+
/**
|
|
135
|
+
* Default proposal template. Exported so tests and callers can inspect the
|
|
136
|
+
* baseline shape without re-deriving it. Uses ADR-091's exact heading form
|
|
137
|
+
* (`# Proposal NNN: Title` with a SPACE separator, not a hyphen). Keep in
|
|
138
|
+
* sync with `DEFAULT_ADR_TEMPLATE` below.
|
|
139
|
+
*/
|
|
140
|
+
export const DEFAULT_PROPOSAL_TEMPLATE = `# Proposal {{ID}}: {{TITLE}}
|
|
141
|
+
|
|
142
|
+
**Status:** Draft
|
|
143
|
+
**Date:** {{DATE}}
|
|
144
|
+
|
|
145
|
+
## Problem Statement
|
|
146
|
+
|
|
147
|
+
_Describe the problem this proposal addresses._
|
|
148
|
+
|
|
149
|
+
## Proposal
|
|
150
|
+
|
|
151
|
+
_Describe the proposed change._
|
|
152
|
+
|
|
153
|
+
## Alternatives Considered
|
|
154
|
+
|
|
155
|
+
_List alternatives and why they were rejected._
|
|
156
|
+
|
|
157
|
+
## Impact
|
|
158
|
+
|
|
159
|
+
_Who / what does this affect?_
|
|
160
|
+
`;
|
|
161
|
+
/**
|
|
162
|
+
* Default ADR template. Mirrors `DEFAULT_PROPOSAL_TEMPLATE` but with the
|
|
163
|
+
* `# ADR NNN: Title` heading form required by ADR-091.
|
|
164
|
+
*/
|
|
165
|
+
export const DEFAULT_ADR_TEMPLATE = `# ADR {{ID}}: {{TITLE}}
|
|
166
|
+
|
|
167
|
+
**Status:** Draft
|
|
168
|
+
**Date:** {{DATE}}
|
|
169
|
+
|
|
170
|
+
## Context
|
|
171
|
+
|
|
172
|
+
_Describe the architectural context and forces at play._
|
|
173
|
+
|
|
174
|
+
## Decision
|
|
175
|
+
|
|
176
|
+
_State the decision._
|
|
177
|
+
|
|
178
|
+
## Consequences
|
|
179
|
+
|
|
180
|
+
_List the consequences. Note what improves and what regresses._
|
|
181
|
+
`;
|
|
182
|
+
/**
|
|
183
|
+
* Render the artifact template with variable substitution.
|
|
184
|
+
*
|
|
185
|
+
* If `templatePath` exists on disk, its contents are used; otherwise the
|
|
186
|
+
* hardcoded `DEFAULT_PROPOSAL_TEMPLATE` / `DEFAULT_ADR_TEMPLATE` string is
|
|
187
|
+
* used. Substitutes `{{TITLE}}`, `{{DATE}}`, and `{{ID}}` globally.
|
|
188
|
+
*
|
|
189
|
+
* MVP variable set per spec #1288: only `{{TITLE}}` and `{{DATE}}` are
|
|
190
|
+
* user-facing; `{{ID}}` is internal to the default templates so the NNN
|
|
191
|
+
* number lands in the heading without the caller having to splice it.
|
|
192
|
+
*/
|
|
193
|
+
export function renderArtifactTemplate(opts) {
|
|
194
|
+
const { type, id, title, templatePath, date } = opts;
|
|
195
|
+
let template;
|
|
196
|
+
if (fs.existsSync(templatePath)) {
|
|
197
|
+
template = fs.readFileSync(templatePath, 'utf-8');
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
template = type === 'proposal' ? DEFAULT_PROPOSAL_TEMPLATE : DEFAULT_ADR_TEMPLATE;
|
|
201
|
+
}
|
|
202
|
+
// Single-pass regex + keyed replacer function. Two reasons:
|
|
203
|
+
// 1. Sequential `.replace()` calls allow template injection (a title of
|
|
204
|
+
// `{{DATE}}` would be substituted into the template and then picked
|
|
205
|
+
// up by the next pass as an actual DATE token). One pass eliminates
|
|
206
|
+
// that class of bug.
|
|
207
|
+
// 2. The replacer-function form avoids `$&` / `$1` back-reference
|
|
208
|
+
// interpretation in the replacement string (see PR #1429 review
|
|
209
|
+
// cycle). A title like `Fix $foo bug` mis-renders otherwise.
|
|
210
|
+
const replacements = { TITLE: title, DATE: date, ID: id };
|
|
211
|
+
return template.replace(/\{\{(TITLE|DATE|ID)\}\}/g, (_match, key) => replacements[key]);
|
|
212
|
+
}
|
|
213
|
+
const defaultExec = (cmd, args, cwd) => {
|
|
214
|
+
safeExec(cmd, args, { cwd });
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* Run the two post-scaffold side-effects in sequence:
|
|
218
|
+
*
|
|
219
|
+
* 1. `pnpm run docs:inject` (refresh the dashboard index). On non-zero exit
|
|
220
|
+
* or missing script, warn to stderr and continue — the scaffolded file
|
|
221
|
+
* already exists on disk, so a dashboard refresh failure should not
|
|
222
|
+
* strand the artifact.
|
|
223
|
+
* 2. `git add <newFilePath> <dashboardFile>`. Stages ONLY those two paths;
|
|
224
|
+
* never `-A` or `.` (per lesson-8067935e / lesson-4a01b498). On failure,
|
|
225
|
+
* warn and return `staged: false` so the caller can surface the stage
|
|
226
|
+
* state in its user-facing summary.
|
|
227
|
+
*
|
|
228
|
+
* Neither step throws; both failures degrade gracefully so the user always
|
|
229
|
+
* walks away with the new artifact on disk.
|
|
230
|
+
*/
|
|
231
|
+
export function runPostScaffoldHooks(opts) {
|
|
232
|
+
const { rootDir, newFilePath, dashboardFile, exec = defaultExec } = opts;
|
|
233
|
+
let dashboardRefreshed = false;
|
|
234
|
+
try {
|
|
235
|
+
exec('pnpm', ['run', 'docs:inject'], rootDir);
|
|
236
|
+
dashboardRefreshed = true; // totem-context: intentional warn-and-continue per spec 1288 — dashboard refresh failure must not strand the scaffolded artifact on disk.
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
240
|
+
log.warn('Totem', `docs:inject did not run cleanly (${msg}). Dashboard not refreshed; run 'pnpm run docs:inject' manually.`);
|
|
241
|
+
}
|
|
242
|
+
let staged = false;
|
|
243
|
+
try {
|
|
244
|
+
exec('git', ['add', newFilePath, dashboardFile], rootDir);
|
|
245
|
+
staged = true; // totem-context: intentional warn-and-continue per spec 1288 — git add failure must not strand the scaffolded artifact on disk.
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
249
|
+
log.warn('Totem', `git add failed (${msg}). File created but not staged; run 'git add' manually.`);
|
|
250
|
+
}
|
|
251
|
+
return { dashboardRefreshed, staged };
|
|
252
|
+
}
|
|
253
|
+
function todayIso() {
|
|
254
|
+
const now = new Date();
|
|
255
|
+
const y = now.getUTCFullYear();
|
|
256
|
+
const m = String(now.getUTCMonth() + 1).padStart(2, '0');
|
|
257
|
+
const d = String(now.getUTCDate()).padStart(2, '0');
|
|
258
|
+
return `${y}-${m}-${d}`;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Full scaffolding pipeline, invoked by both `totem proposal new` and
|
|
262
|
+
* `totem adr new`:
|
|
263
|
+
*
|
|
264
|
+
* resolve paths → compute id → sanitize filename → render template →
|
|
265
|
+
* collision guard → write file → run docs:inject + git add
|
|
266
|
+
*
|
|
267
|
+
* Pre-disk validation (path resolution, id computation, slug sanitization,
|
|
268
|
+
* collision check) happens BEFORE the filesystem is touched so a bad input
|
|
269
|
+
* never strands a half-written artifact.
|
|
270
|
+
*/
|
|
271
|
+
export function scaffoldGovernanceArtifact(options, internals = {}) {
|
|
272
|
+
const paths = resolveGovernancePaths(options.cwd, options.type);
|
|
273
|
+
// Sanitize once at the orchestrator entry. Both the filename slug and the
|
|
274
|
+
// template body render against the cleaned form so a title carrying
|
|
275
|
+
// newlines, tabs, or control characters cannot inject markdown blocks
|
|
276
|
+
// into the scaffolded artifact.
|
|
277
|
+
const cleanTitle = sanitizeArtifactTitle(options.title);
|
|
278
|
+
const id = internals.forceId ?? getNextArtifactId(paths.targetDir);
|
|
279
|
+
const filename = formatArtifactFilename(id, cleanTitle);
|
|
280
|
+
const filePath = path.join(paths.targetDir, filename);
|
|
281
|
+
// Collision pre-check gives a clean user-facing error on the common path.
|
|
282
|
+
// The authoritative collision guard is the `flag: 'wx'` on `writeFileSync`
|
|
283
|
+
// below, which closes the TOCTOU race between the pre-check and the write
|
|
284
|
+
// (a concurrent scaffolder could slip in between the two). Keeping both
|
|
285
|
+
// gives a nice error when the file already exists AND safety against the
|
|
286
|
+
// narrow race window.
|
|
287
|
+
if (fs.existsSync(filePath)) {
|
|
288
|
+
throw new TotemError('CONFIG_INVALID', `Artifact already exists at ${filePath}.`, 'Choose a different title, or remove the existing file before re-scaffolding.');
|
|
289
|
+
}
|
|
290
|
+
const date = internals.date ?? todayIso();
|
|
291
|
+
const rendered = renderArtifactTemplate({
|
|
292
|
+
type: options.type,
|
|
293
|
+
id,
|
|
294
|
+
title: cleanTitle,
|
|
295
|
+
templatePath: paths.templatePath,
|
|
296
|
+
date,
|
|
297
|
+
});
|
|
298
|
+
// Ensure parent dir exists (it should, from resolveGovernancePaths, but
|
|
299
|
+
// cheap to defend against a manually-pruned target).
|
|
300
|
+
fs.mkdirSync(paths.targetDir, { recursive: true });
|
|
301
|
+
try {
|
|
302
|
+
// `flag: 'wx'` = write exclusive. Atomic fail with EEXIST if the file
|
|
303
|
+
// was created between the pre-check and now. Closes the TOCTOU race.
|
|
304
|
+
fs.writeFileSync(filePath, rendered, { encoding: 'utf-8', flag: 'wx' });
|
|
305
|
+
}
|
|
306
|
+
catch (err) {
|
|
307
|
+
if (err.code === 'EEXIST') {
|
|
308
|
+
throw new TotemError('CONFIG_INVALID', `Artifact already exists at ${filePath}.`, 'A concurrent scaffolder created this file between the pre-check and the write. Re-run the command to pick up a fresh NNN.');
|
|
309
|
+
}
|
|
310
|
+
throw err;
|
|
311
|
+
}
|
|
312
|
+
const hookResult = runPostScaffoldHooks({
|
|
313
|
+
rootDir: paths.rootDir,
|
|
314
|
+
newFilePath: filePath,
|
|
315
|
+
dashboardFile: paths.dashboardFile,
|
|
316
|
+
exec: internals.exec,
|
|
317
|
+
});
|
|
318
|
+
return {
|
|
319
|
+
id,
|
|
320
|
+
filename,
|
|
321
|
+
filePath,
|
|
322
|
+
dashboardFile: paths.dashboardFile,
|
|
323
|
+
dashboardRefreshed: hookResult.dashboardRefreshed,
|
|
324
|
+
staged: hookResult.staged,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=governance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"governance.js","sourceRoot":"","sources":["../../src/utils/governance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"governance.test.d.ts","sourceRoot":"","sources":["../../src/utils/governance.test.ts"],"names":[],"mappings":""}
|