@mmnto/cli 1.121.0 → 1.123.0
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/artifact-vocabulary.d.ts +23 -0
- package/dist/artifact-vocabulary.d.ts.map +1 -0
- package/dist/artifact-vocabulary.js +23 -0
- package/dist/artifact-vocabulary.js.map +1 -0
- package/dist/commands/config-drift.test.js +89 -1
- package/dist/commands/config-drift.test.js.map +1 -1
- package/dist/commands/init-templates.d.ts +6 -6
- package/dist/commands/init-templates.d.ts.map +1 -1
- package/dist/commands/init-templates.js +8 -7
- package/dist/commands/init-templates.js.map +1 -1
- package/dist/commands/init.test.js +18 -5
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/install-hooks.d.ts.map +1 -1
- package/dist/commands/install-hooks.js +241 -17
- package/dist/commands/install-hooks.js.map +1 -1
- package/dist/commands/install-hooks.test.js +1019 -23
- package/dist/commands/install-hooks.test.js.map +1 -1
- package/dist/commands/legs.d.ts +259 -0
- package/dist/commands/legs.d.ts.map +1 -0
- package/dist/commands/legs.js +623 -0
- package/dist/commands/legs.js.map +1 -0
- package/dist/commands/legs.test.d.ts +20 -0
- package/dist/commands/legs.test.d.ts.map +1 -0
- package/dist/commands/legs.test.js +1004 -0
- package/dist/commands/legs.test.js.map +1 -0
- package/dist/commands/pre-push-gate-matrix.test.js +14 -0
- package/dist/commands/pre-push-gate-matrix.test.js.map +1 -1
- package/dist/commands/review-fan.d.ts +40 -1
- package/dist/commands/review-fan.d.ts.map +1 -1
- package/dist/commands/review-fan.js +108 -3
- package/dist/commands/review-fan.js.map +1 -1
- package/dist/commands/review-fan.test.js +444 -6
- package/dist/commands/review-fan.test.js.map +1 -1
- package/dist/commands/shield-covariate.test.js +19 -2
- package/dist/commands/shield-covariate.test.js.map +1 -1
- package/dist/commands/shield-nonreview.test.js +140 -1
- package/dist/commands/shield-nonreview.test.js.map +1 -1
- package/dist/commands/shield.d.ts.map +1 -1
- package/dist/commands/shield.js +53 -1
- package/dist/commands/shield.js.map +1 -1
- package/dist/commands/spec-cli-wiring.test.d.ts +19 -0
- package/dist/commands/spec-cli-wiring.test.d.ts.map +1 -0
- package/dist/commands/spec-cli-wiring.test.js +90 -0
- package/dist/commands/spec-cli-wiring.test.js.map +1 -0
- package/dist/commands/spec-templates.d.ts +18 -0
- package/dist/commands/spec-templates.d.ts.map +1 -1
- package/dist/commands/spec-templates.js +21 -0
- package/dist/commands/spec-templates.js.map +1 -1
- package/dist/commands/spec.d.ts +168 -1
- package/dist/commands/spec.d.ts.map +1 -1
- package/dist/commands/spec.js +448 -7
- package/dist/commands/spec.js.map +1 -1
- package/dist/commands/spec.test.js +903 -20
- package/dist/commands/spec.test.js.map +1 -1
- package/dist/git.d.ts +19 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +13 -4
- package/dist/git.js.map +1 -1
- package/dist/index.js +47 -2
- package/dist/index.js.map +1 -1
- package/dist/services/run-artifacts.d.ts +12 -1
- package/dist/services/run-artifacts.d.ts.map +1 -1
- package/dist/services/run-artifacts.js +48 -3
- package/dist/services/run-artifacts.js.map +1 -1
- package/dist/services/run-artifacts.test.js +97 -1
- package/dist/services/run-artifacts.test.js.map +1 -1
- package/dist/utils.d.ts +22 -3
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +4 -0
- package/dist/utils.js.map +1 -1
- package/dist/utils.test.js +65 -1
- package/dist/utils.test.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `totem legs deposit` / `totem legs gate` — the two verbs over the
|
|
3
|
+
* leg-deposit store (mmnto-ai/totem#2698, ruled 2026-09-03;
|
|
4
|
+
* `doctrine/model-tiering.md` § Review legs).
|
|
5
|
+
*
|
|
6
|
+
* `deposit` is the ONLY writer: it resolves the head a falsification leg
|
|
7
|
+
* actually read, binds the leg's findings file to that sha, and hands the
|
|
8
|
+
* bytes to core's validate-on-write `saveLegDeposit`. `gate` is a READER — it
|
|
9
|
+
* never writes, never judges a finding's severity, and never decides policy:
|
|
10
|
+
* it answers one question for a push, *was this head read by a leg*, and says
|
|
11
|
+
* exactly how it derived the answer.
|
|
12
|
+
*
|
|
13
|
+
* Three properties of the gate are contract, not style:
|
|
14
|
+
*
|
|
15
|
+
* 1. **The tier changes only the exit code.** `--advisory` prints the
|
|
16
|
+
* BYTE-IDENTICAL lines of every state and exits 0; the strict caller is
|
|
17
|
+
* the pre-push hook, which maps 3 and 2 to a block. That is why the
|
|
18
|
+
* derivation returns its lines and BOTH codes, and the flag is applied at
|
|
19
|
+
* one place at the very end — a second formatting path per tier is how the
|
|
20
|
+
* advisory line and the blocking line drift apart.
|
|
21
|
+
* 2. **Not owed never consults the store.** The predicate is derived from the
|
|
22
|
+
* changed-file set alone; a repo whose diff matches no glob must not have
|
|
23
|
+
* its deposit directory read, so the "not owed" line is honest about
|
|
24
|
+
* having judged globs and nothing else.
|
|
25
|
+
* 3. **stdout is written SYNCHRONOUSLY before exit.** A piped write is
|
|
26
|
+
* asynchronous on macOS, so `process.stdout.write` followed by
|
|
27
|
+
* `process.exit` can truncate the very line the `sh` arm is about to echo
|
|
28
|
+
* — the `fs.writeSync(1, …)` precedent from the strict pre-commit reader.
|
|
29
|
+
*
|
|
30
|
+
* Everything the gate echoes is control-character sanitized. The deposit's own
|
|
31
|
+
* strings are already refused at the schema boundary (core `artifacts/legs.ts`),
|
|
32
|
+
* but paths, glob names and corrupt-file reasons come off a filesystem and a
|
|
33
|
+
* config file, so they are sanitized here too rather than trusted by provenance.
|
|
34
|
+
*
|
|
35
|
+
* Per the CLI command-module contract, every VALUE import is dynamic inside
|
|
36
|
+
* the command bodies (the core barrel pulls LanceDB into `--help` otherwise);
|
|
37
|
+
* `import type` is erased at build and stays static.
|
|
38
|
+
*/
|
|
39
|
+
/** Log tag for this command pair's human output (`log.*` writes to stderr). */
|
|
40
|
+
const TAG = 'Legs';
|
|
41
|
+
/**
|
|
42
|
+
* How many `glob → file` basis pairs the BLOCKED line names before it
|
|
43
|
+
* collapses the rest into `+K more`. Sized like `MAX_DISCLOSED_FILTERED_FILES`
|
|
44
|
+
* in `git.ts`: enough to show the reason, bounded so one broad glob cannot
|
|
45
|
+
* flood a hook's output.
|
|
46
|
+
*/
|
|
47
|
+
const MAX_DISCLOSED_BASIS_PAIRS = 5;
|
|
48
|
+
/**
|
|
49
|
+
* How many changed paths the gate's own scope line names before it collapses
|
|
50
|
+
* the rest into `+K more`. Higher than the basis cap because this line is the
|
|
51
|
+
* scope itself rather than a reason, but still bounded: an unbounded list is a
|
|
52
|
+
* screenful in a hook's output on a large branch, and the true count stays in
|
|
53
|
+
* the parentheses either way.
|
|
54
|
+
*/
|
|
55
|
+
const MAX_DISCLOSED_CHANGED_FILES = 12;
|
|
56
|
+
/**
|
|
57
|
+
* List what a candidate could have READ: the paths its own branch diff added
|
|
58
|
+
* relative to `base` (three-dot).
|
|
59
|
+
*
|
|
60
|
+
* `-z` is load-bearing, not a style choice (mmnto-ai/totem#2698 fold 4). Under
|
|
61
|
+
* git's default `core.quotePath=true`, `--name-only` C-QUOTES any path with a
|
|
62
|
+
* non-ASCII byte, a quote or a backslash — `docs/caf\303\251.md` — while the
|
|
63
|
+
* owed set comes from `extractChangedFiles`, which is unquoted. The two sets
|
|
64
|
+
* then never intersect for such a path, and a covering ancestor is rejected
|
|
65
|
+
* with the false reason "predates every owed change". `-z` emits raw
|
|
66
|
+
* NUL-separated names and never quotes, so both sides speak one spelling.
|
|
67
|
+
*
|
|
68
|
+
* One helper, taking the runner: the gate shells out through `safeExec` and the
|
|
69
|
+
* covariate through its injected `GitExec`, and a second copy of this argv is
|
|
70
|
+
* exactly how one of them would drift back to the quoted form.
|
|
71
|
+
*/
|
|
72
|
+
export function legReachPaths(run, base, head) {
|
|
73
|
+
const raw = run(['diff', '--name-only', '-z', `${base}...${head}`]);
|
|
74
|
+
// NUL-terminated, not NUL-separated: the payload ends with one, so the final
|
|
75
|
+
// split element is empty and is dropped along with any other empty.
|
|
76
|
+
return raw.split(LEG_PATH_SEPARATOR).filter((entry) => entry.length > 0);
|
|
77
|
+
}
|
|
78
|
+
/** The `-z` record separator, built rather than escaped (the banked decode trap). */
|
|
79
|
+
const LEG_PATH_SEPARATOR = String.fromCharCode(0);
|
|
80
|
+
/** The prefix `TotemError` stamps on every message — stripped when re-branding. */
|
|
81
|
+
const TOTEM_ERROR_BRAND = '[Totem Error] ';
|
|
82
|
+
/** Milliseconds in a day — the evidence line's age is reported in days. */
|
|
83
|
+
const MS_PER_DAY = 86_400_000;
|
|
84
|
+
/**
|
|
85
|
+
* Collapse every C0 (0-31) and DEL/C1 (127-159) code point to `?`.
|
|
86
|
+
*
|
|
87
|
+
* `sanitizeForTerminal` deliberately PRESERVES LF and HT — it defends a
|
|
88
|
+
* multi-line log payload — so it is not sufficient on its own for a value
|
|
89
|
+
* landing inside a single `[Totem] …` line that a shell arm echoes: one
|
|
90
|
+
* newline in a glob or a path would forge a second line and a reader could not
|
|
91
|
+
* tell the forged one from the gate's own. This is the strict-pre-commit
|
|
92
|
+
* reader's `safe()` rule (`install-hooks.ts`), applied AFTER the ANSI/CSI strip
|
|
93
|
+
* so both defenses hold: escapes removed, then every remaining control byte
|
|
94
|
+
* flattened. U+0085 (NEL) is inside the band because it breaks a line on some
|
|
95
|
+
* terminals.
|
|
96
|
+
*
|
|
97
|
+
* Written as a `charCodeAt` loop, not the equivalent regex class: the class
|
|
98
|
+
* would have to be authored with `\u`/`\x` escapes, and this repo has a banked
|
|
99
|
+
* incident where an editing tool decoded such an escape into a RAW control byte
|
|
100
|
+
* in the source (mmnto-ai/totem#2692 fold 3).
|
|
101
|
+
*/
|
|
102
|
+
function safeLine(text) {
|
|
103
|
+
let out = '';
|
|
104
|
+
for (let i = 0; i < text.length; i++) {
|
|
105
|
+
const code = text.charCodeAt(i);
|
|
106
|
+
const control = code < 32 || (code >= 127 && code <= 159);
|
|
107
|
+
out = out + (control ? '?' : text.charAt(i));
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The ONE spelling of "this value came from outside and is about to be echoed":
|
|
113
|
+
* strip ANSI/CSI escapes, then flatten every remaining control byte. Both verbs
|
|
114
|
+
* pass every filesystem-, config- and argv-sourced value through it
|
|
115
|
+
* (mmnto-ai/totem#2698 fold 2).
|
|
116
|
+
*/
|
|
117
|
+
function echoSafe(value) {
|
|
118
|
+
return safeLine(sanitizeForTerminalSync(value));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* `sanitizeForTerminal`, bound through a module-local slot so {@link echoSafe}
|
|
122
|
+
* stays synchronous inside message templates. Assigned from the same dynamic
|
|
123
|
+
* core import the rest of the module uses, before either verb echoes anything.
|
|
124
|
+
*/
|
|
125
|
+
let sanitizeForTerminalSync = (value) => value;
|
|
126
|
+
/** Bind the core sanitizer for this process. Idempotent; called by both verbs. */
|
|
127
|
+
async function loadSanitizer() {
|
|
128
|
+
const { sanitizeForTerminal } = await import('@mmnto/totem');
|
|
129
|
+
sanitizeForTerminalSync = sanitizeForTerminal;
|
|
130
|
+
}
|
|
131
|
+
/** Render the four counts the way both verbs spell them. */
|
|
132
|
+
function renderCounts(counts) {
|
|
133
|
+
return `blocking=${counts.blocking} material=${counts.material} minor=${counts.minor} folded=${counts.folded}`;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Resolve `ref` to a full 40-hex COMMIT sha, refusing anything that is not a
|
|
137
|
+
* commit in this repo by name. `^{commit}` is the peel that makes a tag or a
|
|
138
|
+
* tree fail here rather than silently addressing the store under a non-commit
|
|
139
|
+
* object name.
|
|
140
|
+
*/
|
|
141
|
+
async function resolveCommitSha(cwd, ref) {
|
|
142
|
+
const { safeExec, TotemError } = await import('@mmnto/totem');
|
|
143
|
+
await loadSanitizer();
|
|
144
|
+
const trimmed = ref.trim();
|
|
145
|
+
if (trimmed.length === 0 || trimmed.startsWith('-')) {
|
|
146
|
+
// Mirrors `getGitDiffRange`'s flag-injection guard: a ref starting with
|
|
147
|
+
// `-` reaches git as an option, not a revision.
|
|
148
|
+
throw new TotemError('GIT_FAILED', `Invalid --sha ${JSON.stringify(echoSafe(ref))}: a revision may not be empty or start with '-' (git-flag injection guard).`, 'Pass a plain revision such as HEAD or a commit sha.');
|
|
149
|
+
}
|
|
150
|
+
let out;
|
|
151
|
+
try {
|
|
152
|
+
out = safeExec('git', ['rev-parse', '--verify', `${trimmed}^{commit}`], { cwd });
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
// git's own failure rides as the CAUSE (styleguide rule 9): the message
|
|
156
|
+
// names the ref the seat passed, and `--debug` can still reach what git
|
|
157
|
+
// actually said.
|
|
158
|
+
throw new TotemError('GIT_FAILED', `--sha ${echoSafe(trimmed)} does not name a commit in this repository.`, 'Pass a commit this checkout can resolve (e.g. HEAD), or fetch the missing history first.', err);
|
|
159
|
+
}
|
|
160
|
+
const sha = out.trim();
|
|
161
|
+
if (!/^[0-9a-f]{40}$/.test(sha)) {
|
|
162
|
+
throw new TotemError('GIT_FAILED', `--sha ${echoSafe(trimmed)} resolved to ${JSON.stringify(echoSafe(sha))}, which is not a 40-character commit sha.`, 'Pass a commit this checkout can resolve (e.g. HEAD).');
|
|
163
|
+
}
|
|
164
|
+
return sha;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* `totem legs deposit --sha <ref> --from <file> [--replace] [--read-at <iso>]`
|
|
168
|
+
*
|
|
169
|
+
* The writer. Refuses, loudly and before touching the store, every way the
|
|
170
|
+
* deposit could name the wrong head: a `--sha` that is not a commit, a file
|
|
171
|
+
* whose own `diffSha` disagrees with it, and an occupied address without
|
|
172
|
+
* `--replace`. `readAt` is the leg's own instant — when the file carries none
|
|
173
|
+
* and none is passed, the stamp is `now` and that substitution is PRINTED,
|
|
174
|
+
* because a deposit's instant is what the resolver breaks ties on.
|
|
175
|
+
*/
|
|
176
|
+
export async function legsDepositCommand(options) {
|
|
177
|
+
const fs = await import('node:fs');
|
|
178
|
+
const path = await import('node:path');
|
|
179
|
+
const { LEG_DEPOSIT_SCHEMA_VERSION, countLegFindings, saveLegDeposit, TotemError } = await import('@mmnto/totem');
|
|
180
|
+
const { log } = await import('../ui.js');
|
|
181
|
+
const { loadConfig, loadEnv, resolveConfigPath } = await import('../utils.js');
|
|
182
|
+
await loadSanitizer();
|
|
183
|
+
const cwd = process.cwd();
|
|
184
|
+
const configPath = resolveConfigPath(cwd);
|
|
185
|
+
loadEnv(cwd);
|
|
186
|
+
const config = await loadConfig(configPath);
|
|
187
|
+
const totemDirAbs = path.join(path.dirname(configPath), config.totemDir);
|
|
188
|
+
const diffSha = await resolveCommitSha(cwd, options.sha ?? 'HEAD');
|
|
189
|
+
const fromPath = path.resolve(cwd, options.from);
|
|
190
|
+
let raw;
|
|
191
|
+
try {
|
|
192
|
+
raw = JSON.parse(fs.readFileSync(fromPath, 'utf-8'));
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
throw new TotemError('PARSE_FAILED', `Could not read the leg's findings at ${echoSafe(options.from)}.`, 'Pass --from <file> pointing at the leg deposit JSON the review leg returned.', err);
|
|
196
|
+
}
|
|
197
|
+
if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
|
|
198
|
+
throw new TotemError('PARSE_FAILED', `The leg's findings at ${echoSafe(options.from)} are not a JSON object.`, 'The file must be a deposit object: { findings, folded, verdict, ... }.');
|
|
199
|
+
}
|
|
200
|
+
const fields = raw;
|
|
201
|
+
// The deposit must NAME the head it read: a file that carries its own
|
|
202
|
+
// `diffSha` and disagrees with `--sha` is a mismatch, never a rewrite.
|
|
203
|
+
const declaredSha = fields['diffSha'];
|
|
204
|
+
if (typeof declaredSha === 'string' && declaredSha !== diffSha) {
|
|
205
|
+
throw new TotemError('PARSE_FAILED', `The findings file names diffSha ${echoSafe(declaredSha)}, but --sha resolved to ${diffSha}.`, 'Deposit against the head the leg actually read, or correct the diffSha in the file.');
|
|
206
|
+
}
|
|
207
|
+
const fileReadAt = typeof fields['readAt'] === 'string' ? fields['readAt'] : undefined;
|
|
208
|
+
const readAt = options.readAt ?? fileReadAt ?? new Date().toISOString();
|
|
209
|
+
if (options.readAt === undefined && fileReadAt === undefined) {
|
|
210
|
+
log.warn(TAG, `readAt defaulted to ${echoSafe(readAt)} — pass --read-at for the leg's own instant`);
|
|
211
|
+
}
|
|
212
|
+
const schemaVersion = typeof fields['schemaVersion'] === 'string'
|
|
213
|
+
? fields['schemaVersion']
|
|
214
|
+
: LEG_DEPOSIT_SCHEMA_VERSION;
|
|
215
|
+
// Assembled as `unknown` and handed to the validate-on-write path: the
|
|
216
|
+
// schema is the ONE validation boundary, so a malformed findings array
|
|
217
|
+
// surfaces with its Zod path instead of a hand-rolled second opinion.
|
|
218
|
+
const candidate = {
|
|
219
|
+
...fields,
|
|
220
|
+
schemaVersion,
|
|
221
|
+
diffSha,
|
|
222
|
+
readAt,
|
|
223
|
+
};
|
|
224
|
+
let result;
|
|
225
|
+
try {
|
|
226
|
+
result = saveLegDeposit(totemDirAbs, candidate, { replace: options.replace === true });
|
|
227
|
+
}
|
|
228
|
+
catch (err) {
|
|
229
|
+
// A ZodError's own message is a JSON blob; re-state it as the path→message
|
|
230
|
+
// pairs the seat has to fix (the `loadConfig` idiom). Every other failure —
|
|
231
|
+
// including core's typed LegDepositExistsError, which already carries the
|
|
232
|
+
// incumbent's readAt and names --replace — propagates untouched.
|
|
233
|
+
if (err instanceof Error && err.name === 'ZodError' && 'issues' in err) {
|
|
234
|
+
const issues = err.issues
|
|
235
|
+
// Each issue's path and message are line-safed INDIVIDUALLY; the
|
|
236
|
+
// newline between entries is this code's own layout, not attacker
|
|
237
|
+
// input, so it survives (a whole-block flatten would destroy the list).
|
|
238
|
+
.map((issue) => ` ${echoSafe(issue.path.join('.') || '<root>')}: ${echoSafe(issue.message)}`)
|
|
239
|
+
.join('\n');
|
|
240
|
+
throw new TotemError('PARSE_FAILED', `The leg deposit built from ${echoSafe(options.from)} is not valid:\n${issues}`, 'Fix the fields listed above; every finding needs a unique id, and folded may only name finding ids.', err);
|
|
241
|
+
}
|
|
242
|
+
throw err;
|
|
243
|
+
}
|
|
244
|
+
if (result.replaced !== undefined) {
|
|
245
|
+
log.warn(TAG, `replaced the deposit read at ${echoSafe(result.replaced.readAt ?? 'an unreadable instant')} for ${diffSha}`);
|
|
246
|
+
}
|
|
247
|
+
log.success(TAG, `${echoSafe(result.path)} · ${renderCounts(countLegFindings(candidate))}`);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* The coverage query for a set of owed paths, or `undefined` when it cannot be
|
|
251
|
+
* derived (no base). Exported because the covariate resolves through the SAME
|
|
252
|
+
* inputs as the gate — a field that named a deposit the gate rejects would be
|
|
253
|
+
* the round reading evidence the push gate does not accept.
|
|
254
|
+
*
|
|
255
|
+
* The basis lists one entry per `glob -> file` MATCH, so a file matching three
|
|
256
|
+
* globs appears three times; the owed set is those files, deduplicated in
|
|
257
|
+
* basis order.
|
|
258
|
+
*/
|
|
259
|
+
export function legsCoverageForBasis(base, basis) {
|
|
260
|
+
if (base === undefined)
|
|
261
|
+
return undefined;
|
|
262
|
+
const owedFiles = [...new Set(basis.map((entry) => entry.file))];
|
|
263
|
+
return owedFiles.length === 0 ? undefined : { base, owedFiles };
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Derive the gate's verdict and its lines.
|
|
267
|
+
*
|
|
268
|
+
* The tier is applied ONLY to `status`; `stdout` is produced once, so an
|
|
269
|
+
* advisory run and a strict run of the same state cannot print different text.
|
|
270
|
+
*/
|
|
271
|
+
export async function runLegsGate(options, deps) {
|
|
272
|
+
const path = await import('node:path');
|
|
273
|
+
const { classifyLegsOwed, countLegFindings, findLegDepositForHead, sanitizeForTerminal } = await import('@mmnto/totem');
|
|
274
|
+
const advisory = options.advisory === true;
|
|
275
|
+
const finish = (derived, stdout, stderr) => ({
|
|
276
|
+
derived,
|
|
277
|
+
status: advisory ? 0 : derived,
|
|
278
|
+
stdout,
|
|
279
|
+
stderr,
|
|
280
|
+
});
|
|
281
|
+
// Two-stage, in this order: strip ANSI/CSI escapes, then flatten every
|
|
282
|
+
// remaining control byte. The second stage is what keeps a newline in a glob
|
|
283
|
+
// or a path from forging a second `[Totem]` line (mmnto-ai/totem#2698 fold 2).
|
|
284
|
+
const safe = (value) => safeLine(sanitizeForTerminal(value));
|
|
285
|
+
/** Repo-root-relative, forward-slashed — the address a reader can act on. */
|
|
286
|
+
const relative = (target) => safe(path.relative(deps.root, target).split(path.sep).join('/'));
|
|
287
|
+
let head;
|
|
288
|
+
let scope;
|
|
289
|
+
let resolution;
|
|
290
|
+
let owed;
|
|
291
|
+
try {
|
|
292
|
+
const { TotemError } = await import('@mmnto/totem');
|
|
293
|
+
head = deps.resolveHead();
|
|
294
|
+
scope = await deps.changedFiles();
|
|
295
|
+
owed = classifyLegsOwed(scope.files, deps.globs);
|
|
296
|
+
// The store is consulted ONLY when the diff is owed — a not-owed push must
|
|
297
|
+
// not depend on the deposit directory being readable at all.
|
|
298
|
+
if (owed.owed) {
|
|
299
|
+
// Coverage is not optional for the GATE (mmnto-ai/totem#2698 fold 3): it
|
|
300
|
+
// only ever runs on the branch scope, so a scope that resolved without a
|
|
301
|
+
// base is a failure to derive, not a licence to fall back to
|
|
302
|
+
// ancestry-only — that fallback is exactly the merge-base pass the
|
|
303
|
+
// ruling closed.
|
|
304
|
+
const query = legsCoverageForBasis(scope.base, owed.basis);
|
|
305
|
+
if (query === undefined) {
|
|
306
|
+
throw new TotemError('GIT_FAILED', 'the branch scope resolved without a base ref, so coverage is not derivable', 'Fetch the base branch (git fetch origin <base>) and retry.');
|
|
307
|
+
}
|
|
308
|
+
resolution = findLegDepositForHead(deps.totemDirAbs, head, deps.git, query);
|
|
309
|
+
}
|
|
310
|
+
// totem-context: intentional — this is not a swallow but the gate's LOUDEST arm: any failure to derive (no repo, an unresolvable head, a branch diff or an ancestry probe that will not resolve) becomes the NOT DERIVED verdict, printed with its cause and exit 2, which the strict pre-push arm blocks on with its own line (mmnto-ai/totem#2698)
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
// `TotemError` brands its own message, and this line is already branded —
|
|
314
|
+
// `[Totem] legs: NOT DERIVED — [Totem Error] …` reads as two speakers. The
|
|
315
|
+
// gate owns the shape of its line, so the inner brand is stripped; the
|
|
316
|
+
// recovery hint stays on the error for any programmatic caller.
|
|
317
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
318
|
+
const cause = safe(raw.startsWith(TOTEM_ERROR_BRAND) ? raw.slice(TOTEM_ERROR_BRAND.length) : raw);
|
|
319
|
+
return finish(2, [`[Totem] legs: NOT DERIVED — ${cause}`], []);
|
|
320
|
+
}
|
|
321
|
+
const head8 = safe(head.slice(0, 8));
|
|
322
|
+
if (!owed.owed) {
|
|
323
|
+
return finish(0, [
|
|
324
|
+
`[Totem] legs: not owed — no changed path matched hooks.legsOwed.globs (${deps.globs.length} globs; head ${head8})`,
|
|
325
|
+
], []);
|
|
326
|
+
}
|
|
327
|
+
// The corrupt rows are a SENSOR, not a verdict: they are disclosed on stderr
|
|
328
|
+
// whatever the outcome, and they never mask a valid sibling deposit.
|
|
329
|
+
const stderr = (resolution?.corrupt ?? []).map((entry) => `[Totem] legs: sensor — ignoring corrupt deposit ${safe(entry.file)}: ${safe(entry.reason)}`);
|
|
330
|
+
const winner = resolution?.winner;
|
|
331
|
+
if (winner !== undefined) {
|
|
332
|
+
const counts = countLegFindings(winner.deposit);
|
|
333
|
+
const stamp = Date.parse(winner.deposit.readAt);
|
|
334
|
+
const deltaMs = Number.isNaN(stamp) ? undefined : Date.now() - stamp;
|
|
335
|
+
const days = deltaMs === undefined ? undefined : Math.floor(deltaMs / MS_PER_DAY);
|
|
336
|
+
// A negative age is not an unknown age. A deposit stamped in the FUTURE —
|
|
337
|
+
// a skewed clock, a hand-edited instant — used to print `age unknown`,
|
|
338
|
+
// which reads as "unparseable" and hides the one thing worth acting on:
|
|
339
|
+
// this instant is wrong, and ranking breaks ties on it.
|
|
340
|
+
const age = days === undefined
|
|
341
|
+
? 'age unknown'
|
|
342
|
+
: days >= 0
|
|
343
|
+
? `${days} days old`
|
|
344
|
+
: // The MAGNITUDE is floored, not the signed value: `Math.floor` on a
|
|
345
|
+
// negative delta rounds AWAY from zero, so a stamp two days and a
|
|
346
|
+
// second ahead reported three.
|
|
347
|
+
`read ${Math.floor(Math.abs(deltaMs ?? 0) / MS_PER_DAY)} days in the FUTURE — check the clock or the deposit`;
|
|
348
|
+
const reach = winner.rank === 'exact'
|
|
349
|
+
? 'exact'
|
|
350
|
+
: `nearest ancestor, +${winner.distance} commits since the leg read`;
|
|
351
|
+
// `covers K/N owed paths` is DISCLOSURE, never a block: a leg that read
|
|
352
|
+
// some of what this push owes is still a leg that read this head, and the
|
|
353
|
+
// re-arm is doctrine's call. The gate always supplies a coverage query, so
|
|
354
|
+
// the field is always present here; the guard exists because the core
|
|
355
|
+
// resolution is shared with the covariate, which may resolve without one.
|
|
356
|
+
const covers = winner.coverage === undefined
|
|
357
|
+
? ''
|
|
358
|
+
: ` · covers ${winner.coverage.covered}/${winner.coverage.owed} owed paths`;
|
|
359
|
+
const stdout = [
|
|
360
|
+
`[Totem] legs evidence: ${relative(winner.path)} (read ${safe(winner.deposit.readAt)}, ${age}) · head ${head8} · ${reach}${covers} · blocking=${counts.blocking} material=${counts.material} folded=${counts.folded}`,
|
|
361
|
+
];
|
|
362
|
+
const superseded = resolution?.superseded ?? [];
|
|
363
|
+
if (superseded.length > 0) {
|
|
364
|
+
const named = superseded
|
|
365
|
+
.map((candidate) => `${safe(candidate.diffSha.slice(0, 8))} (read ${safe(candidate.readAt)}, ${candidate.rank === 'exact' ? 'exact' : `ancestor +${candidate.distance}`})`)
|
|
366
|
+
.join(', ');
|
|
367
|
+
stdout.push(`[Totem] legs: ${superseded.length} superseded candidate(s) for this head: ${named}`);
|
|
368
|
+
}
|
|
369
|
+
return finish(0, stdout, stderr);
|
|
370
|
+
}
|
|
371
|
+
// Owed, and nothing answers for this head. The basis is what makes the block
|
|
372
|
+
// actionable — WHICH glob matched WHICH file — and every stale candidate is
|
|
373
|
+
// named with its own reason, because "not an ancestor" and "unknown to this
|
|
374
|
+
// repo" are different repairs.
|
|
375
|
+
const shown = owed.basis
|
|
376
|
+
.slice(0, MAX_DISCLOSED_BASIS_PAIRS)
|
|
377
|
+
.map((entry) => `${safe(entry.glob)} → ${safe(entry.file)}`)
|
|
378
|
+
.join(', ');
|
|
379
|
+
const more = owed.basis.length > MAX_DISCLOSED_BASIS_PAIRS
|
|
380
|
+
? `, +${owed.basis.length - MAX_DISCLOSED_BASIS_PAIRS} more`
|
|
381
|
+
: '';
|
|
382
|
+
const stdout = [
|
|
383
|
+
`[Totem] BLOCKED: this push is legs-owed (${shown}${more}) and carries no fresh falsification-leg deposit for head ${head8}`,
|
|
384
|
+
];
|
|
385
|
+
for (const candidate of resolution?.stale ?? []) {
|
|
386
|
+
// One reason per candidate, because the repairs differ: fetch the missing
|
|
387
|
+
// history, deposit against this branch, or run the leg over the owed diff.
|
|
388
|
+
// Exhaustive on purpose — a ternary chain's final arm silently ADOPTS any
|
|
389
|
+
// reason core adds later, printing the wrong repair for it.
|
|
390
|
+
const reason = (() => {
|
|
391
|
+
switch (candidate.reason) {
|
|
392
|
+
case 'not-ancestor':
|
|
393
|
+
return 'not an ancestor of head';
|
|
394
|
+
case 'unknown-commit':
|
|
395
|
+
return 'unknown to this repo';
|
|
396
|
+
case 'no-coverage':
|
|
397
|
+
return 'covers none of the owed paths (the deposit predates every owed change)';
|
|
398
|
+
default: {
|
|
399
|
+
const unreachable = candidate.reason;
|
|
400
|
+
return String(unreachable);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
})();
|
|
404
|
+
stdout.push(`[Totem] legs: stale deposit ${safe(candidate.diffSha.slice(0, 8))}: ${reason}`);
|
|
405
|
+
}
|
|
406
|
+
stdout.push('[Totem] legs: run the leg, then: totem legs deposit --sha HEAD --from <findings.json>');
|
|
407
|
+
return finish(3, stdout, stderr);
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Resolve the branch scope the floor is judged on — the ONE derivation the gate
|
|
411
|
+
* and the covariate both use (mmnto-ai/totem#2698 fold 3 item 3), so the
|
|
412
|
+
* covariate can never name a deposit the gate would reject.
|
|
413
|
+
*
|
|
414
|
+
* The push-gate scope (`--branch`): the branch-vs-base diff is what the leg
|
|
415
|
+
* read, and it is what the push actually proposes. An empty result is not owed
|
|
416
|
+
* — there is nothing for a leg to read.
|
|
417
|
+
*
|
|
418
|
+
* UNFILTERED, deliberately (mmnto-ai/totem#2698 fold 1). The same base/head
|
|
419
|
+
* resolution runs, but with an EMPTY ignore configuration, so neither
|
|
420
|
+
* `ignorePatterns` nor `shieldIgnorePatterns` can hide a path from the floor.
|
|
421
|
+
* Those keys carry INDEX-exclusion semantics that were merged into the
|
|
422
|
+
* review/lint diff filter for back-compat (mmnto-ai/totem#1746,
|
|
423
|
+
* mmnto-ai/totem#1748) — letting them narrow this predicate would mean a repo
|
|
424
|
+
* that excludes `README.md` from its index silently stops owing a leg for its
|
|
425
|
+
* public copy, which is the claim-without-mechanism shape the floor exists to
|
|
426
|
+
* close.
|
|
427
|
+
*
|
|
428
|
+
* The resolved BASE rides back with the files: coverage is measured against it,
|
|
429
|
+
* and it must be the same base HEAD was resolved against.
|
|
430
|
+
*/
|
|
431
|
+
export async function resolveUnfilteredBranchScope(cwd, options = {}) {
|
|
432
|
+
const { safeExec } = await import('@mmnto/totem');
|
|
433
|
+
const { getDiffForReview } = await import('../git.js');
|
|
434
|
+
const { log } = await import('../ui.js');
|
|
435
|
+
await loadSanitizer();
|
|
436
|
+
const run = options.run ?? ((args) => safeExec('git', [...args], { cwd }));
|
|
437
|
+
const narrate = options.suppressScopeNarration !== true;
|
|
438
|
+
// The GATE narrates its scope; the covariate does not. Since fold 4 the leg
|
|
439
|
+
// field derives coverage from HEAD's branch scope on every review scope, so
|
|
440
|
+
// this resolution runs inside `totem review` runs too — and a `[Legs]` line
|
|
441
|
+
// in the middle of a `[Review]` run describes a probe nobody asked for.
|
|
442
|
+
// `getDiffForReview` still resolves the BASE (its origin-preference logic is
|
|
443
|
+
// the one this gate must agree with) and still rules on the empty-diff case,
|
|
444
|
+
// but its narration is ALWAYS suppressed: its `Changed files` line is built
|
|
445
|
+
// from `extractChangedFiles`, which spells a non-ASCII path the C-quoted way,
|
|
446
|
+
// and this module prints the RAW list below. Letting both speak printed the
|
|
447
|
+
// same line twice, in two different spellings (caught on this branch's own
|
|
448
|
+
// gate run, mmnto-ai/totem#2698 fold 5).
|
|
449
|
+
const result = await getDiffForReview({ branch: true, suppressScopeNarration: true }, { ignorePatterns: [], shieldIgnorePatterns: [] }, cwd, TAG);
|
|
450
|
+
const base = result.base;
|
|
451
|
+
// One disclosure, ours, carrying the resolved base so nothing the suppressed
|
|
452
|
+
// line said is lost.
|
|
453
|
+
if (narrate) {
|
|
454
|
+
log.info(TAG, safeLine(`Diff source: branch-vs-base (${base ?? 'no base resolved'}...HEAD, unfiltered — ignorePatterns do not apply to the floor)`));
|
|
455
|
+
}
|
|
456
|
+
// The FILE LIST is read separately, with `-z` (mmnto-ai/totem#2698 fold 5).
|
|
457
|
+
//
|
|
458
|
+
// Not a preference: `extractChangedFiles` parses `diff --git` headers, which
|
|
459
|
+
// git C-QUOTES for any path carrying a non-ASCII byte, a double quote or a
|
|
460
|
+
// backslash. The reach probe reads the same names raw. Fold 4 tried to
|
|
461
|
+
// reconcile them by DECODING the quoted side, which handled octal triples
|
|
462
|
+
// and nothing else — a name with a quote or a backslash still missed, and a
|
|
463
|
+
// literal `\123` inside a legal filename was rewritten to `S`. Reading the
|
|
464
|
+
// owed side through the SAME `-z` helper the reach uses makes both sides raw
|
|
465
|
+
// by construction, so there is nothing left to decode and no name a decoder
|
|
466
|
+
// could corrupt.
|
|
467
|
+
const files = 'empty' in result || base === undefined
|
|
468
|
+
? // No base, or nothing changed: there is no `base...HEAD` to list, and
|
|
469
|
+
// an empty scope is not owed anyway.
|
|
470
|
+
[]
|
|
471
|
+
: legReachPaths(run, base, 'HEAD');
|
|
472
|
+
// The gate's own disclosure, from the RAW list — so the names it prints are
|
|
473
|
+
// the names it judged, spelled as they are on disk.
|
|
474
|
+
if (narrate) {
|
|
475
|
+
const shownFiles = files.slice(0, MAX_DISCLOSED_CHANGED_FILES).map(safeLine);
|
|
476
|
+
const moreFiles = files.length > shownFiles.length ? `, +${files.length - shownFiles.length} more` : '';
|
|
477
|
+
// The count in the parentheses is the TRUE one — the cap shortens the list,
|
|
478
|
+
// never the number.
|
|
479
|
+
log.info(TAG, safeLine(`Changed files (${files.length}): ${shownFiles.join(', ')}${moreFiles}`));
|
|
480
|
+
}
|
|
481
|
+
return { files, ...(base === undefined ? {} : { base }) };
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* The judgment-dense floor this repo declares, or the default when it declares
|
|
485
|
+
* none — the ONE spelling, shared by the gate and both covariate sites.
|
|
486
|
+
*/
|
|
487
|
+
export async function legsOwedGlobs(config) {
|
|
488
|
+
const { DEFAULT_LEGS_OWED_GLOBS } = await import('@mmnto/totem');
|
|
489
|
+
return config.hooks?.legsOwed?.globs ?? [...DEFAULT_LEGS_OWED_GLOBS];
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Derive the coverage query for a COVARIATE site (mmnto-ai/totem#2698 fold 3,
|
|
493
|
+
* corrected in fold 4).
|
|
494
|
+
*
|
|
495
|
+
* The inputs come from HEAD's branch-vs-base scope ALWAYS — never from the
|
|
496
|
+
* scope the review itself ran on. The leg field answers "was THIS HEAD read",
|
|
497
|
+
* so what it owes is a property of HEAD, not of whether the operator happened
|
|
498
|
+
* to review a staged slice or a dirty tree. Deriving from the review's scope
|
|
499
|
+
* meant the default `uncommitted` scope resolved ancestry-only and NAMED the
|
|
500
|
+
* merge-base deposit the gate rejects — the field disagreeing with the gate,
|
|
501
|
+
* which is the one thing it must never do.
|
|
502
|
+
*
|
|
503
|
+
* Both covariate sites route through this one function, and it reuses the
|
|
504
|
+
* gate's own pieces — the unfiltered branch scope and core's single
|
|
505
|
+
* `classifyLegsOwed` — so the guarantee is unconditional: the field never names
|
|
506
|
+
* a deposit the gate would reject. When HEAD has no branch base the answer is
|
|
507
|
+
* `leg: none` plus one sensor, never a name resolved on ancestry alone.
|
|
508
|
+
*/
|
|
509
|
+
export async function deriveLegsCoverageForHead(cwd, globs, options = {}) {
|
|
510
|
+
const { classifyLegsOwed } = await import('@mmnto/totem');
|
|
511
|
+
await loadSanitizer();
|
|
512
|
+
let scope;
|
|
513
|
+
try {
|
|
514
|
+
scope = await resolveUnfilteredBranchScope(cwd, options);
|
|
515
|
+
// totem-context: intentional — `--covariate` is a read-only sensor whose contract is to print a line and exit 0, so a branch scope that will not resolve (no repo, an unfetched base) yields the no-coverage answer with its reason printed, never a throw out of a transport verb
|
|
516
|
+
}
|
|
517
|
+
catch (err) {
|
|
518
|
+
return {
|
|
519
|
+
reason: `coverage was not derivable — HEAD has no branch base (${echoSafe(err instanceof Error ? err.message : String(err))})`,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
const owed = classifyLegsOwed(scope.files, globs);
|
|
523
|
+
const query = legsCoverageForBasis(scope.base, owed.basis);
|
|
524
|
+
if (query !== undefined)
|
|
525
|
+
return { query };
|
|
526
|
+
// Two shapes reach here and they are NOT the same answer. No base: coverage
|
|
527
|
+
// is underivable, so no deposit can be credited. Nothing owed: HEAD owes no
|
|
528
|
+
// leg at all, so an empty query is vacuously satisfied and the field resolves
|
|
529
|
+
// on ancestry — the gate would not even consult the store for this head.
|
|
530
|
+
return scope.base === undefined
|
|
531
|
+
? { reason: 'coverage was not derivable — HEAD has no branch base' }
|
|
532
|
+
: { query: { base: scope.base, owedFiles: [] } };
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Build the gate's real-world seam from the repo's config and git.
|
|
536
|
+
*
|
|
537
|
+
* Exported so the UNFILTERED-diff contract below is testable against a real
|
|
538
|
+
* checkout without capturing a process exit: a test resolves these deps in a
|
|
539
|
+
* fixture repo and asserts what `changedFiles()` actually returns.
|
|
540
|
+
*
|
|
541
|
+
* It takes no options: since `--head` was removed (mmnto-ai/totem#2698 fold 2)
|
|
542
|
+
* nothing about the seam varies with a flag — `--advisory` is applied to the
|
|
543
|
+
* STATUS, after the derivation, and never to what is derived.
|
|
544
|
+
*/
|
|
545
|
+
export async function buildLegsGateDeps() {
|
|
546
|
+
const path = await import('node:path');
|
|
547
|
+
const { safeExec, TotemError } = await import('@mmnto/totem');
|
|
548
|
+
// The branch scope (and its `Diff source:` disclosure) now lives in the
|
|
549
|
+
// shared `resolveUnfilteredBranchScope`, which the covariate calls too.
|
|
550
|
+
const { isAncestor } = await import('../git.js');
|
|
551
|
+
const { loadConfig, loadEnv, resolveConfigPath } = await import('../utils.js');
|
|
552
|
+
await loadSanitizer();
|
|
553
|
+
const cwd = process.cwd();
|
|
554
|
+
const configPath = resolveConfigPath(cwd);
|
|
555
|
+
loadEnv(cwd);
|
|
556
|
+
const config = await loadConfig(configPath);
|
|
557
|
+
const root = path.dirname(configPath);
|
|
558
|
+
const git = {
|
|
559
|
+
isCommit(sha) {
|
|
560
|
+
try {
|
|
561
|
+
safeExec('git', ['cat-file', '-e', `${sha}^{commit}`], { cwd });
|
|
562
|
+
return true;
|
|
563
|
+
// totem-context: intentional — "does this repo know that object" IS the boolean; git's failure text is not a second signal, and the caller reports the deposit as `unknown to this repo`
|
|
564
|
+
}
|
|
565
|
+
catch {
|
|
566
|
+
return false;
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
isAncestor(base, head) {
|
|
570
|
+
return isAncestor(cwd, base, head);
|
|
571
|
+
},
|
|
572
|
+
changedFiles: (base, head) => legReachPaths((args) => safeExec('git', [...args], { cwd }), base, head),
|
|
573
|
+
distance(base, head) {
|
|
574
|
+
const raw = safeExec('git', ['rev-list', '--count', `${base}..${head}`], { cwd }).trim();
|
|
575
|
+
const count = Number.parseInt(raw, 10);
|
|
576
|
+
if (Number.isNaN(count)) {
|
|
577
|
+
// Never guessed (mmnto-ai/totem#2698 fold 2, MINOR). The number is
|
|
578
|
+
// PRINTED as fact — `+N commits since the leg read` — so an
|
|
579
|
+
// unparseable answer is a failure to derive, not a zero: it throws,
|
|
580
|
+
// reaches the gate's NOT DERIVED arm, and the strict hook blocks on it.
|
|
581
|
+
// Guessing 0 would render a stale read as an exact one.
|
|
582
|
+
throw new TotemError('GIT_FAILED', `git rev-list --count ${base}..${head} returned ${JSON.stringify(echoSafe(raw))}, which is not a commit count.`, 'Fix the checkout (a corrupt or truncated object store) and retry.');
|
|
583
|
+
}
|
|
584
|
+
return count;
|
|
585
|
+
},
|
|
586
|
+
};
|
|
587
|
+
const deps = {
|
|
588
|
+
root,
|
|
589
|
+
totemDirAbs: path.join(root, config.totemDir),
|
|
590
|
+
globs: await legsOwedGlobs(config),
|
|
591
|
+
git,
|
|
592
|
+
resolveHead() {
|
|
593
|
+
return safeExec('git', ['rev-parse', '--verify', 'HEAD^{commit}'], { cwd }).trim();
|
|
594
|
+
},
|
|
595
|
+
changedFiles: () => resolveUnfilteredBranchScope(cwd, {
|
|
596
|
+
run: (args) => safeExec('git', [...args], { cwd }),
|
|
597
|
+
}),
|
|
598
|
+
};
|
|
599
|
+
return deps;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* `totem legs gate [--advisory]`
|
|
603
|
+
*
|
|
604
|
+
* The reader the strict pre-push arm calls. Loads the repo's config, builds
|
|
605
|
+
* the real git and diff seams, derives, writes SYNCHRONOUSLY, exits with the
|
|
606
|
+
* tier-mapped status. `--advisory` maps every GATE state to 0; a failure
|
|
607
|
+
* before the derivation (config load, flag parse) still exits non-zero
|
|
608
|
+
* through the CLI's error boundary.
|
|
609
|
+
*/
|
|
610
|
+
export async function legsGateCommand(options) {
|
|
611
|
+
const fs = await import('node:fs');
|
|
612
|
+
const deps = await buildLegsGateDeps();
|
|
613
|
+
const outcome = await runLegsGate(options, deps);
|
|
614
|
+
for (const line of outcome.stderr)
|
|
615
|
+
fs.writeSync(2, `${line}\n`);
|
|
616
|
+
// fs.writeSync, not console.log: stdout is a PIPE under the hook, and a
|
|
617
|
+
// piped write is asynchronous on macOS — process.exit could truncate the
|
|
618
|
+
// line the `sh` arm is about to echo.
|
|
619
|
+
for (const line of outcome.stdout)
|
|
620
|
+
fs.writeSync(1, `${line}\n`);
|
|
621
|
+
process.exit(outcome.status);
|
|
622
|
+
}
|
|
623
|
+
//# sourceMappingURL=legs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legs.js","sourceRoot":"","sources":["../../src/commands/legs.ts"],"names":[],"mappings":"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"}
|