@mmnto/cli 2.2.0 → 2.2.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/gate-install.d.ts +18 -0
- package/dist/commands/gate-install.d.ts.map +1 -1
- package/dist/commands/gate-install.js +25 -0
- package/dist/commands/gate-install.js.map +1 -1
- package/dist/commands/gate-install.test.js +221 -9
- package/dist/commands/gate-install.test.js.map +1 -1
- package/dist/commands/gate.d.ts.map +1 -1
- package/dist/commands/gate.js +14 -1
- package/dist/commands/gate.js.map +1 -1
- package/dist/commands/init-templates.d.ts +4 -4
- package/dist/commands/init-templates.d.ts.map +1 -1
- package/dist/commands/init-templates.js +148 -27
- package/dist/commands/init-templates.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +15 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +10 -0
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/session-context-journal-select.test.d.ts +2 -0
- package/dist/commands/session-context-journal-select.test.d.ts.map +1 -0
- package/dist/commands/session-context-journal-select.test.js +95 -0
- package/dist/commands/session-context-journal-select.test.js.map +1 -0
- package/dist/commands/sync-labels-forms.test.d.ts +33 -0
- package/dist/commands/sync-labels-forms.test.d.ts.map +1 -0
- package/dist/commands/sync-labels-forms.test.js +325 -0
- package/dist/commands/sync-labels-forms.test.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-context-journal-select.test.d.ts","sourceRoot":"","sources":["../../src/commands/session-context-journal-select.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { pathToFileURL } from 'node:url';
|
|
3
|
+
import { beforeAll, describe, expect, it } from 'vitest';
|
|
4
|
+
const repoRoot = path.resolve(__dirname, '..', '..', '..', '..');
|
|
5
|
+
const helperPath = path.join(repoRoot, '.claude', 'hooks', 'lib', 'select-latest-journal.mjs');
|
|
6
|
+
let selectLatestJournal;
|
|
7
|
+
beforeAll(async () => {
|
|
8
|
+
const mod = (await import(pathToFileURL(helperPath).href));
|
|
9
|
+
selectLatestJournal = mod.selectLatestJournal;
|
|
10
|
+
});
|
|
11
|
+
/** A stat function over a fixed mtime table; a missing key throws like fs would. */
|
|
12
|
+
function statOf(table) {
|
|
13
|
+
return (file) => {
|
|
14
|
+
if (!(file in table)) {
|
|
15
|
+
throw new Error(`ENOENT: no such file or directory, stat '${file}'`);
|
|
16
|
+
}
|
|
17
|
+
return table[file];
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const T1 = 1_000;
|
|
21
|
+
const T2 = 2_000;
|
|
22
|
+
const T3 = 3_000;
|
|
23
|
+
describe('selectLatestJournal — the recency policy behind the hook', () => {
|
|
24
|
+
it('a conforming directory (counter order == write order) serves the lexical-newest with no drift', () => {
|
|
25
|
+
const pick = selectLatestJournal(['claude-0001-a.md', 'claude-0002-b.md', 'claude-0003-c.md'], statOf({
|
|
26
|
+
'claude-0001-a.md': T1,
|
|
27
|
+
'claude-0002-b.md': T2,
|
|
28
|
+
'claude-0003-c.md': T3,
|
|
29
|
+
}));
|
|
30
|
+
expect(pick).not.toBeNull();
|
|
31
|
+
expect(pick.latest).toBe('claude-0003-c.md');
|
|
32
|
+
expect(pick.lexicalLatest).toBe('claude-0003-c.md');
|
|
33
|
+
expect(pick.drift).toBe(false);
|
|
34
|
+
expect(pick.reason).toBe('lexical');
|
|
35
|
+
expect(pick.statFailures).toEqual([]);
|
|
36
|
+
});
|
|
37
|
+
it('a clock-named file that out-sorts a later write is naming drift: the newer write is served and named', () => {
|
|
38
|
+
// The 2026-09-07 incident shape: `claude-2315-…` (a 23:15 clock stamp) out-sorted the
|
|
39
|
+
// 01:33 signoff `claude-0132-…`; the pre-fix hook served the stale file silently.
|
|
40
|
+
const pick = selectLatestJournal(['claude-0001-first.md', 'claude-2315-clock-named.md', 'claude-0100-newest-write.md'], statOf({
|
|
41
|
+
'claude-0001-first.md': T1,
|
|
42
|
+
'claude-2315-clock-named.md': T2,
|
|
43
|
+
'claude-0100-newest-write.md': T3,
|
|
44
|
+
}));
|
|
45
|
+
expect(pick.lexicalLatest).toBe('claude-2315-clock-named.md');
|
|
46
|
+
expect(pick.mtimeLatest).toBe('claude-0100-newest-write.md');
|
|
47
|
+
expect(pick.latest).toBe('claude-0100-newest-write.md');
|
|
48
|
+
expect(pick.drift).toBe(true);
|
|
49
|
+
expect(pick.reason).toBe('newest-write');
|
|
50
|
+
});
|
|
51
|
+
it('an mtime tie keeps the lexical pick (no drift reported)', () => {
|
|
52
|
+
const pick = selectLatestJournal(['claude-0001-a.md', 'claude-0002-b.md'], statOf({
|
|
53
|
+
'claude-0001-a.md': T2,
|
|
54
|
+
'claude-0002-b.md': T2,
|
|
55
|
+
}));
|
|
56
|
+
expect(pick.latest).toBe('claude-0002-b.md');
|
|
57
|
+
expect(pick.drift).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
it('a sibling whose stat throws is skipped and reported — it never drops the pick', () => {
|
|
60
|
+
// The GCA / Greptile / CodeRabbit round-1 finding: pre-fix, one dangling entry threw
|
|
61
|
+
// inside the hook's outer try and the whole journal block was lost.
|
|
62
|
+
const pick = selectLatestJournal(['claude-0001-a.md', 'claude-0002-dangling.md', 'claude-0003-c.md'], statOf({ 'claude-0001-a.md': T1, 'claude-0003-c.md': T3 }));
|
|
63
|
+
expect(pick.latest).toBe('claude-0003-c.md');
|
|
64
|
+
expect(pick.drift).toBe(false);
|
|
65
|
+
expect(pick.reason).toBe('lexical');
|
|
66
|
+
expect(pick.statFailures).toHaveLength(1);
|
|
67
|
+
expect(pick.statFailures[0].file).toBe('claude-0002-dangling.md');
|
|
68
|
+
expect(pick.statFailures[0].message).toContain('ENOENT');
|
|
69
|
+
});
|
|
70
|
+
it('when the lexical-newest itself cannot be stat-ed, the newest readable write is served and the reason says so, not drift', () => {
|
|
71
|
+
const pick = selectLatestJournal(['claude-0001-a.md', 'claude-0002-b.md', 'claude-0003-gone.md'], statOf({
|
|
72
|
+
'claude-0001-a.md': T1,
|
|
73
|
+
'claude-0002-b.md': T2,
|
|
74
|
+
}));
|
|
75
|
+
expect(pick.lexicalLatest).toBe('claude-0003-gone.md');
|
|
76
|
+
expect(pick.latest).toBe('claude-0002-b.md');
|
|
77
|
+
expect(pick.drift).toBe(false);
|
|
78
|
+
expect(pick.reason).toBe('lexical-unreadable');
|
|
79
|
+
expect(pick.statFailures.map((s) => s.file)).toEqual(['claude-0003-gone.md']);
|
|
80
|
+
});
|
|
81
|
+
it('when nothing can be stat-ed the lexical pick stands with every failure reported', () => {
|
|
82
|
+
const pick = selectLatestJournal(['claude-0001-a.md', 'claude-0002-b.md'], statOf({}));
|
|
83
|
+
expect(pick.latest).toBe('claude-0002-b.md');
|
|
84
|
+
expect(pick.reason).toBe('lexical');
|
|
85
|
+
expect(pick.drift).toBe(false);
|
|
86
|
+
expect(pick.statFailures).toHaveLength(2);
|
|
87
|
+
});
|
|
88
|
+
it('filters non-markdown entries and returns null for an empty directory', () => {
|
|
89
|
+
expect(selectLatestJournal(['legacy', 'notes.txt'], statOf({}))).toBeNull();
|
|
90
|
+
const pick = selectLatestJournal(['legacy', 'claude-0001-a.md'], statOf({ 'claude-0001-a.md': T1 }));
|
|
91
|
+
expect(pick.files).toEqual(['claude-0001-a.md']);
|
|
92
|
+
expect(pick.latest).toBe('claude-0001-a.md');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
//# sourceMappingURL=session-context-journal-select.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-context-journal-select.test.js","sourceRoot":"","sources":["../../src/commands/session-context-journal-select.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The issue-form ↔ label-canon coupling, and the `-WhatIf` dry run of
|
|
3
|
+
* `scripts/sync-labels.ps1` (mmnto-ai/totem#2792).
|
|
4
|
+
*
|
|
5
|
+
* Two contracts are locked here, both DERIVED from the real script rather than
|
|
6
|
+
* mirrored (Tenet 20 — the same discipline `parity-label-canon.test.ts` applies
|
|
7
|
+
* to the canon itself):
|
|
8
|
+
*
|
|
9
|
+
* 1. Every `.github/ISSUE_TEMPLATE/*.yml` form parses and applies exactly its
|
|
10
|
+
* own `type: <basename>` label, a name the script defines. A space-less
|
|
11
|
+
* `type:bug` would leave the canon's type label missing on every issue the
|
|
12
|
+
* form creates (whether GitHub drops the unknown label or mints a stray
|
|
13
|
+
* one); here it fails the suite instead.
|
|
14
|
+
* 2. Every form's `Tier` and `Scope` dropdowns offer exactly the canon's
|
|
15
|
+
* `tier-*` names and its `scope: ` names with the namespace stripped. Both
|
|
16
|
+
* option sets are computed from the parsed script — never hand-listed — so
|
|
17
|
+
* a new scope in the script is a failing test until the forms carry it.
|
|
18
|
+
* The scope derivation reads ONLY names starting with `scope: `, so the
|
|
19
|
+
* `disposition: ` namespace can never leak into the dropdown.
|
|
20
|
+
*
|
|
21
|
+
* The last two cases spawn `pwsh` against the real script. The first proves the
|
|
22
|
+
* `-WhatIf` shadow prints every `gh` call and executes none (a stub `gh` sits on
|
|
23
|
+
* PATH and must stay untouched); the second proves the shadow does NOT leak into
|
|
24
|
+
* a normal run — the same stub, no `-WhatIf`, must receive the whole canon. Both
|
|
25
|
+
* run against `-Repo example/stub`; neither can reach GitHub, because `gh` on the
|
|
26
|
+
* child's PATH is a log-appending stub.
|
|
27
|
+
*
|
|
28
|
+
* Every case skips when the repo-root files are absent (a packaged install
|
|
29
|
+
* carries neither the script nor `.github/`), and the spawning ones skip when
|
|
30
|
+
* `pwsh` is not on PATH.
|
|
31
|
+
*/
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=sync-labels-forms.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-labels-forms.test.d.ts","sourceRoot":"","sources":["../../src/commands/sync-labels-forms.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG"}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The issue-form ↔ label-canon coupling, and the `-WhatIf` dry run of
|
|
3
|
+
* `scripts/sync-labels.ps1` (mmnto-ai/totem#2792).
|
|
4
|
+
*
|
|
5
|
+
* Two contracts are locked here, both DERIVED from the real script rather than
|
|
6
|
+
* mirrored (Tenet 20 — the same discipline `parity-label-canon.test.ts` applies
|
|
7
|
+
* to the canon itself):
|
|
8
|
+
*
|
|
9
|
+
* 1. Every `.github/ISSUE_TEMPLATE/*.yml` form parses and applies exactly its
|
|
10
|
+
* own `type: <basename>` label, a name the script defines. A space-less
|
|
11
|
+
* `type:bug` would leave the canon's type label missing on every issue the
|
|
12
|
+
* form creates (whether GitHub drops the unknown label or mints a stray
|
|
13
|
+
* one); here it fails the suite instead.
|
|
14
|
+
* 2. Every form's `Tier` and `Scope` dropdowns offer exactly the canon's
|
|
15
|
+
* `tier-*` names and its `scope: ` names with the namespace stripped. Both
|
|
16
|
+
* option sets are computed from the parsed script — never hand-listed — so
|
|
17
|
+
* a new scope in the script is a failing test until the forms carry it.
|
|
18
|
+
* The scope derivation reads ONLY names starting with `scope: `, so the
|
|
19
|
+
* `disposition: ` namespace can never leak into the dropdown.
|
|
20
|
+
*
|
|
21
|
+
* The last two cases spawn `pwsh` against the real script. The first proves the
|
|
22
|
+
* `-WhatIf` shadow prints every `gh` call and executes none (a stub `gh` sits on
|
|
23
|
+
* PATH and must stay untouched); the second proves the shadow does NOT leak into
|
|
24
|
+
* a normal run — the same stub, no `-WhatIf`, must receive the whole canon. Both
|
|
25
|
+
* run against `-Repo example/stub`; neither can reach GitHub, because `gh` on the
|
|
26
|
+
* child's PATH is a log-appending stub.
|
|
27
|
+
*
|
|
28
|
+
* Every case skips when the repo-root files are absent (a packaged install
|
|
29
|
+
* carries neither the script nor `.github/`), and the spawning ones skip when
|
|
30
|
+
* `pwsh` is not on PATH.
|
|
31
|
+
*/
|
|
32
|
+
import { spawnSync } from 'node:child_process';
|
|
33
|
+
import * as fs from 'node:fs';
|
|
34
|
+
import * as os from 'node:os';
|
|
35
|
+
import * as path from 'node:path';
|
|
36
|
+
import { fileURLToPath } from 'node:url';
|
|
37
|
+
import { describe, expect, it } from 'vitest';
|
|
38
|
+
import { parse as parseYaml } from 'yaml';
|
|
39
|
+
import { parseLabelCanon } from '@mmnto/totem';
|
|
40
|
+
/** packages/cli/src/commands → the repo root. */
|
|
41
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', '..');
|
|
42
|
+
const SCRIPT_PATH = path.join(ROOT, 'scripts', 'sync-labels.ps1');
|
|
43
|
+
const TEMPLATE_DIR = path.join(ROOT, '.github', 'ISSUE_TEMPLATE');
|
|
44
|
+
const CONFIG_PATH = path.join(TEMPLATE_DIR, 'config.yml');
|
|
45
|
+
const ONBOARDING_PATH = path.join(TEMPLATE_DIR, 'onboarding.md');
|
|
46
|
+
const REPO_FILES_PRESENT = fs.existsSync(SCRIPT_PATH) && fs.existsSync(TEMPLATE_DIR);
|
|
47
|
+
/** `pwsh` on PATH and runnable — absent on a minimal container, present on every GitHub runner. */
|
|
48
|
+
function pwshRunnable() {
|
|
49
|
+
const probe = spawnSync('pwsh', ['-NoProfile', '-Command', 'exit 0'], { encoding: 'utf8' });
|
|
50
|
+
return probe.error === undefined && probe.status === 0;
|
|
51
|
+
}
|
|
52
|
+
const PWSH_PRESENT = REPO_FILES_PRESENT && pwshRunnable();
|
|
53
|
+
/** The form files, `config.yml` excluded (it is not a form). */
|
|
54
|
+
function formFiles() {
|
|
55
|
+
return fs
|
|
56
|
+
.readdirSync(TEMPLATE_DIR)
|
|
57
|
+
.filter((file) => file.endsWith('.yml') && file !== 'config.yml')
|
|
58
|
+
.sort();
|
|
59
|
+
}
|
|
60
|
+
function readForm(file) {
|
|
61
|
+
return parseYaml(fs.readFileSync(path.join(TEMPLATE_DIR, file), 'utf8'));
|
|
62
|
+
}
|
|
63
|
+
/** The canon of record, parsed from the real script exactly as the sensor parses it. */
|
|
64
|
+
function realCanon() {
|
|
65
|
+
return parseLabelCanon(fs.readFileSync(SCRIPT_PATH, 'utf8'));
|
|
66
|
+
}
|
|
67
|
+
/** The `tier-*` canonical names — the Tier dropdown's option set, derived. */
|
|
68
|
+
function tierOptionsFromCanon(names) {
|
|
69
|
+
return names.filter((name) => name.startsWith('tier-')).sort();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The `scope: ` canonical names with the namespace stripped — the Scope
|
|
73
|
+
* dropdown's option set, derived. The `scope: ` prefix is the ONLY source, so a
|
|
74
|
+
* `disposition: ` (or any other namespace) entry can never enter this set.
|
|
75
|
+
*/
|
|
76
|
+
function scopeOptionsFromCanon(names) {
|
|
77
|
+
const prefix = 'scope: ';
|
|
78
|
+
return names
|
|
79
|
+
.filter((name) => name.startsWith(prefix))
|
|
80
|
+
.map((name) => name.slice(prefix.length))
|
|
81
|
+
.sort();
|
|
82
|
+
}
|
|
83
|
+
/** The one dropdown in `form.body` whose rendered label is `label`. */
|
|
84
|
+
function dropdownByLabel(form, label) {
|
|
85
|
+
return (form.body ?? []).find((field) => field.type === 'dropdown' && field.attributes?.label === label);
|
|
86
|
+
}
|
|
87
|
+
// ─── Forms ↔ canon ───────────────────────────────────────
|
|
88
|
+
describe.skipIf(!REPO_FILES_PRESENT)('issue forms', () => {
|
|
89
|
+
it('ships one form per canonical type, each parsing as YAML with a name and a description', () => {
|
|
90
|
+
const files = formFiles();
|
|
91
|
+
expect(files).toEqual([
|
|
92
|
+
'bug.yml',
|
|
93
|
+
'chore.yml',
|
|
94
|
+
'docs.yml',
|
|
95
|
+
'epic.yml',
|
|
96
|
+
'feature.yml',
|
|
97
|
+
'security.yml',
|
|
98
|
+
]);
|
|
99
|
+
for (const file of files) {
|
|
100
|
+
const form = readForm(file);
|
|
101
|
+
expect(typeof form.name, file).toBe('string');
|
|
102
|
+
expect(typeof form.description, file).toBe('string');
|
|
103
|
+
expect(Array.isArray(form.body), file).toBe(true);
|
|
104
|
+
// Titles stay free-form — no `title:` prefix is imposed on the author.
|
|
105
|
+
expect(Object.keys(form), file).not.toContain('title');
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
it('applies exactly its own type: label, one the script defines (the space in `type: bug` is load-bearing)', () => {
|
|
109
|
+
const canonNames = new Set(realCanon().labels.map((label) => label.name));
|
|
110
|
+
// The canon must be non-empty, or this assertion would pass vacuously the
|
|
111
|
+
// moment the script's grammar changed (the readers' own empty-canon refusal).
|
|
112
|
+
expect(canonNames.size).toBeGreaterThan(0);
|
|
113
|
+
for (const file of formFiles()) {
|
|
114
|
+
const form = readForm(file);
|
|
115
|
+
// Charter § 4c(ii): one template per `type:` value, applying THAT label —
|
|
116
|
+
// derived from the filename, so `docs.yml` cannot ship `type: bug`, an
|
|
117
|
+
// empty list, or two type labels and still pass.
|
|
118
|
+
const expected = `type: ${file.replace(/\.yml$/, '')}`;
|
|
119
|
+
expect(form.labels, file).toEqual([expected]);
|
|
120
|
+
expect(canonNames.has(expected), `${file} applies ${expected}`).toBe(true);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
it("carries a required Tier dropdown whose options are the canon's tier-* names", () => {
|
|
124
|
+
const expected = tierOptionsFromCanon(realCanon().labels.map((label) => label.name));
|
|
125
|
+
expect(expected.length).toBeGreaterThan(0);
|
|
126
|
+
for (const file of formFiles()) {
|
|
127
|
+
const form = readForm(file);
|
|
128
|
+
const tier = dropdownByLabel(form, 'Tier');
|
|
129
|
+
expect(tier, `${file} has a Tier dropdown`).toBeDefined();
|
|
130
|
+
// The id and the label are BOTH a contract with the rung-1 body sensor.
|
|
131
|
+
expect(tier?.id, file).toBe('tier');
|
|
132
|
+
expect(tier?.validations?.required, file).toBe(true);
|
|
133
|
+
expect([...(tier?.attributes?.options ?? [])].sort(), file).toEqual(expected);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
it("carries a required multi-select Scope dropdown whose options are the canon's scope: names, namespace stripped", () => {
|
|
137
|
+
const expected = scopeOptionsFromCanon(realCanon().labels.map((label) => label.name));
|
|
138
|
+
expect(expected.length).toBeGreaterThan(0);
|
|
139
|
+
// Derived from `scope: ` alone — never "every label that is not a tier".
|
|
140
|
+
expect(expected.some((option) => option.includes('disposition'))).toBe(false);
|
|
141
|
+
for (const file of formFiles()) {
|
|
142
|
+
const form = readForm(file);
|
|
143
|
+
const scope = dropdownByLabel(form, 'Scope');
|
|
144
|
+
expect(scope, `${file} has a Scope dropdown`).toBeDefined();
|
|
145
|
+
expect(scope?.id, file).toBe('scope');
|
|
146
|
+
expect(scope?.attributes?.multiple, file).toBe(true);
|
|
147
|
+
expect(scope?.validations?.required, file).toBe(true);
|
|
148
|
+
expect([...(scope?.attributes?.options ?? [])].sort(), file).toEqual(expected);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
it('renders every field under a distinct heading (the body sensor keys on heading text, never on ids)', () => {
|
|
152
|
+
// The epic form once carried a `Scope` textarea beside the `Scope` dropdown:
|
|
153
|
+
// two `### Scope` headings in one rendered body, and a heading-keyed parser
|
|
154
|
+
// cannot tell them apart. Labels are the contract; ids never render.
|
|
155
|
+
for (const file of formFiles()) {
|
|
156
|
+
const form = readForm(file);
|
|
157
|
+
const labels = (form.body ?? [])
|
|
158
|
+
.map((field) => field.attributes?.label)
|
|
159
|
+
.filter((label) => typeof label === 'string');
|
|
160
|
+
expect(new Set(labels).size, `${file} field labels: ${labels.join(' | ')}`).toBe(labels.length);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
it('routes an exploitable vulnerability out of the public security form', () => {
|
|
164
|
+
const form = readForm('security.yml');
|
|
165
|
+
const first = (form.body ?? [])[0];
|
|
166
|
+
expect(first?.type).toBe('markdown');
|
|
167
|
+
expect(first?.attributes?.value ?? '').toMatch(/advisor/i);
|
|
168
|
+
});
|
|
169
|
+
it('disables blank issues and leaves the onboarding template in place', () => {
|
|
170
|
+
const config = parseYaml(fs.readFileSync(CONFIG_PATH, 'utf8'));
|
|
171
|
+
expect(config.blank_issues_enabled).toBe(false);
|
|
172
|
+
expect(fs.existsSync(ONBOARDING_PATH)).toBe(true);
|
|
173
|
+
// Untouched by mmnto-ai/totem#2792: still the front-matter markdown template it was.
|
|
174
|
+
expect(fs.readFileSync(ONBOARDING_PATH, 'utf8').startsWith('---')).toBe(true);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
// ─── The pwsh dry run ────────────────────────────────────
|
|
178
|
+
/**
|
|
179
|
+
* A temp dir holding a `gh` stub that appends its whole argument line to a log
|
|
180
|
+
* and exits 0. Prepended to the child's PATH, it satisfies the script's `gh`
|
|
181
|
+
* presence check and its `gh auth status` preflight while making a real GitHub
|
|
182
|
+
* call impossible.
|
|
183
|
+
*/
|
|
184
|
+
function makeGhStub() {
|
|
185
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-gh-stub-'));
|
|
186
|
+
const logPath = path.join(dir, 'gh-calls.log');
|
|
187
|
+
// With TOTEM_GH_STUB_FAIL set in the child's environment the stub still logs
|
|
188
|
+
// every call but exits 1 on `label edit` — the failure path of the script's
|
|
189
|
+
// mutation tally (Greptile P1 on mmnto-ai/totem#2827).
|
|
190
|
+
if (process.platform === 'win32') {
|
|
191
|
+
fs.writeFileSync(path.join(dir, 'gh.cmd'), [
|
|
192
|
+
'@echo off',
|
|
193
|
+
`>>"${logPath}" echo %*`,
|
|
194
|
+
'if "%TOTEM_GH_STUB_FAIL%"=="" exit /b 0',
|
|
195
|
+
'echo %* | findstr /C:"label edit" >nul',
|
|
196
|
+
'if %errorlevel%==0 exit /b 1',
|
|
197
|
+
'exit /b 0',
|
|
198
|
+
'',
|
|
199
|
+
].join('\r\n'), 'utf8');
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const stub = path.join(dir, 'gh');
|
|
203
|
+
fs.writeFileSync(stub, [
|
|
204
|
+
'#!/bin/sh',
|
|
205
|
+
`printf '%s\\n' "$*" >> "${logPath}"`,
|
|
206
|
+
'if [ -n "$TOTEM_GH_STUB_FAIL" ]; then',
|
|
207
|
+
' case "$*" in *"label edit"*) exit 1 ;; esac',
|
|
208
|
+
'fi',
|
|
209
|
+
'exit 0',
|
|
210
|
+
'',
|
|
211
|
+
].join('\n'), { encoding: 'utf8', mode: 0o755 });
|
|
212
|
+
fs.chmodSync(stub, 0o755);
|
|
213
|
+
}
|
|
214
|
+
return { dir, logPath };
|
|
215
|
+
}
|
|
216
|
+
/** `process.env` with `dir` prepended to PATH, whatever case the platform spells it. */
|
|
217
|
+
function envWithPathPrefix(dir) {
|
|
218
|
+
const env = {};
|
|
219
|
+
let currentPath = '';
|
|
220
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
221
|
+
if (key.toUpperCase() === 'PATH') {
|
|
222
|
+
currentPath = value ?? '';
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
env[key] = value;
|
|
226
|
+
}
|
|
227
|
+
env.PATH = dir + path.delimiter + currentPath;
|
|
228
|
+
return env;
|
|
229
|
+
}
|
|
230
|
+
function runScript(args, stubDir, extraEnv = {}) {
|
|
231
|
+
return spawnSync('pwsh', ['-NoProfile', '-File', SCRIPT_PATH, ...args], {
|
|
232
|
+
cwd: ROOT,
|
|
233
|
+
encoding: 'utf8',
|
|
234
|
+
env: { ...envWithPathPrefix(stubDir), ...extraEnv },
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
describe.skipIf(!PWSH_PRESENT)('scripts/sync-labels.ps1 dry run', () => {
|
|
238
|
+
it('-WhatIf prints every gh call and executes none', () => {
|
|
239
|
+
const stub = makeGhStub();
|
|
240
|
+
try {
|
|
241
|
+
const run = runScript(['-WhatIf', '-Repo', 'example/stub'], stub.dir);
|
|
242
|
+
expect(run.error).toBeUndefined();
|
|
243
|
+
expect(run.status, run.stderr).toBe(0);
|
|
244
|
+
const stdout = run.stdout;
|
|
245
|
+
expect(stdout).toContain('[WhatIf] gh label edit "disposition: done"');
|
|
246
|
+
const labelLines = stdout
|
|
247
|
+
.split(/\r?\n/)
|
|
248
|
+
.filter((line) => line.startsWith('[WhatIf] gh label'));
|
|
249
|
+
// One line per would-be call, derived from the canon rather than pinned:
|
|
250
|
+
// an `edit` per canonical label, a `create` per disposition label, and a
|
|
251
|
+
// `delete` per Merge-Label retirement.
|
|
252
|
+
const canon = realCanon();
|
|
253
|
+
const creates = canon.labels.filter((label) => label.name.startsWith('disposition: ')).length;
|
|
254
|
+
expect(labelLines.length).toBe(canon.labels.length + creates + canon.merges.length);
|
|
255
|
+
// The shadow replaces the executable, so the stub on PATH never ran: no
|
|
256
|
+
// log file at all. This is the "-WhatIf touches nothing" invariant.
|
|
257
|
+
expect(fs.existsSync(stub.logPath)).toBe(false);
|
|
258
|
+
}
|
|
259
|
+
finally {
|
|
260
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
it('a normal run reaches gh for the whole canon — the -WhatIf shadow never leaks', () => {
|
|
264
|
+
const stub = makeGhStub();
|
|
265
|
+
try {
|
|
266
|
+
const run = runScript(['-Repo', 'example/stub'], stub.dir);
|
|
267
|
+
expect(run.error).toBeUndefined();
|
|
268
|
+
expect(run.status, run.stderr).toBe(0);
|
|
269
|
+
expect(run.stdout).not.toContain('[WhatIf]');
|
|
270
|
+
expect(fs.existsSync(stub.logPath), 'the stub gh was invoked').toBe(true);
|
|
271
|
+
const calls = fs
|
|
272
|
+
.readFileSync(stub.logPath, 'utf8')
|
|
273
|
+
.split(/\r?\n/)
|
|
274
|
+
.map((line) => line.trim())
|
|
275
|
+
.filter((line) => line.length > 0);
|
|
276
|
+
// The preflight ran (the unauthenticated silent no-op is now a hard stop).
|
|
277
|
+
expect(calls.some((call) => call.startsWith('auth status'))).toBe(true);
|
|
278
|
+
// Every canonical label was edited, by name, exactly once — the set and
|
|
279
|
+
// the count both derive from the real script (CodeRabbit on mmnto-ai/totem#2827).
|
|
280
|
+
const edited = calls
|
|
281
|
+
.map((call) => /^label edit "?(.+?)"? --color /.exec(call)?.[1])
|
|
282
|
+
.filter((name) => name !== undefined)
|
|
283
|
+
.sort();
|
|
284
|
+
const expectedEdited = realCanon()
|
|
285
|
+
.labels.map((label) => label.name)
|
|
286
|
+
.sort();
|
|
287
|
+
expect(edited).toEqual(expectedEdited);
|
|
288
|
+
const created = calls
|
|
289
|
+
.map((call) => /^label create "?(disposition: [a-z-]+)"?/.exec(call)?.[1])
|
|
290
|
+
.filter((name) => name !== undefined)
|
|
291
|
+
.sort();
|
|
292
|
+
const expectedCreated = realCanon()
|
|
293
|
+
.labels.map((label) => label.name)
|
|
294
|
+
.filter((name) => name.startsWith('disposition: '))
|
|
295
|
+
.sort();
|
|
296
|
+
expect(expectedCreated).toHaveLength(6);
|
|
297
|
+
expect(created).toEqual(expectedCreated);
|
|
298
|
+
}
|
|
299
|
+
finally {
|
|
300
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
it('a failed label edit fails the run — mutation errors never reach "sync complete"', () => {
|
|
304
|
+
// Authenticated but without write access, or an API failure: the literal
|
|
305
|
+
// lines suppress stderr by design, so only the exit CODE can carry the
|
|
306
|
+
// failure. The stub exits 1 on every `label edit`; the tally must name each
|
|
307
|
+
// canonical label and the script must exit non-zero (Greptile P1).
|
|
308
|
+
const stub = makeGhStub();
|
|
309
|
+
try {
|
|
310
|
+
const run = runScript(['-Repo', 'example/stub'], stub.dir, { TOTEM_GH_STUB_FAIL: '1' });
|
|
311
|
+
expect(run.error).toBeUndefined();
|
|
312
|
+
expect(run.status, run.stdout).toBe(1);
|
|
313
|
+
expect(run.stdout).toContain('label mutation(s) failed');
|
|
314
|
+
expect(run.stdout).not.toContain('sync complete');
|
|
315
|
+
const tallied = run.stdout
|
|
316
|
+
.split(/\r?\n/)
|
|
317
|
+
.filter((line) => line.includes('[Error] gh label edit')).length;
|
|
318
|
+
expect(tallied).toBe(realCanon().labels.length);
|
|
319
|
+
}
|
|
320
|
+
finally {
|
|
321
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
//# sourceMappingURL=sync-labels-forms.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-labels-forms.test.js","sourceRoot":"","sources":["../../src/commands/sync-labels-forms.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmnto/cli",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Totem: local-first toolkit that keeps AI-agent work queryable, enforceable, and derivable as plain files in your codebase",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"smol-toml": "^1.6.1",
|
|
29
29
|
"yaml": "^2.4.0",
|
|
30
30
|
"zod": "^3.24.0",
|
|
31
|
-
"@mmnto/totem": "2.2.
|
|
31
|
+
"@mmnto/totem": "2.2.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@anthropic-ai/sdk": "^0.98.0",
|