etymd 0.3.0 → 0.3.2
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/CHANGELOG.md +49 -0
- package/dist/{approve-JEOEC2MV.js → approve-P255DGOI.js} +2 -2
- package/dist/{audit-GYZ5YZ7U.js → audit-IGIUGKSQ.js} +4 -4
- package/dist/{brief-ZK7TXAC4.js → brief-SFZ2DR65.js} +2 -2
- package/dist/{chunk-MKYPLNLH.js → chunk-7MOBQ4N5.js} +1 -1
- package/dist/{chunk-NFENQ3IK.js → chunk-B3SUTZVY.js} +1 -1
- package/dist/{chunk-3NYDVB4Z.js → chunk-VFUYQLW7.js} +22 -4
- package/dist/{chunk-XTAX4YNT.js → chunk-WOBHQQ6H.js} +1 -1
- package/dist/{chunk-V3DPLOOM.js → chunk-WUGBAW6Z.js} +7 -7
- package/dist/cli.js +13 -13
- package/dist/{doctor-C2RTL2QV.js → doctor-4LBUZHVD.js} +4 -4
- package/dist/{fleet-YZGR4UC2.js → fleet-Q6J5XIHH.js} +10 -5
- package/dist/{gates-ILE4PXDA.js → gates-T5J3H7WL.js} +5 -15
- package/dist/generate-I75IEXXF.js +6 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +34 -10
- package/dist/{init-OVLO4OBZ.js → init-WYVDRQ2J.js} +4 -3
- package/dist/scan-IY3LCBJ6.js +5 -0
- package/dist/{scan-RAJUFTQR.js → scan-PZFF6LDA.js} +2 -2
- package/package.json +2 -2
- package/dist/generate-IYCQETQB.js +0 -4
- package/dist/scan-ZYZ7XDSJ.js +0 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# etymd
|
|
2
2
|
|
|
3
|
+
## 0.3.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- A truth finding from any lens now reaches a `doctor` run.
|
|
8
|
+
|
|
9
|
+
`doctor` filters to truth-only, and it used to filter at the **lens** level — so `gate-integrity`
|
|
10
|
+
(an improvement lens) was skipped entirely, and its `hooks-not-wired` finding (tier: risk —
|
|
11
|
+
"tracked hooks exist but never run") was invisible in the one view meant to catch it. The lens
|
|
12
|
+
label was never the right granularity: a lens can emit both kinds, and "hooks exist and are
|
|
13
|
+
unwired" is as objective as anything the truth lens reports.
|
|
14
|
+
|
|
15
|
+
`kind` now lives on the Finding, defaulting to the lens kind when a finding does not set its
|
|
16
|
+
own, and the `--truth` filter operates at the finding level. Every lens still runs under
|
|
17
|
+
`--truth`; findings are filtered afterward, so nothing objective is invisible.
|
|
18
|
+
|
|
19
|
+
Also in this release: CI proves the publish tarball's exact manifest on every push (packagers
|
|
20
|
+
ignore `.gitignore`, so a stray local file can ship while every git-scoped check stays green),
|
|
21
|
+
and the generated hook companions (`.githooks/<hook>.local`) ship in this repo as a worked
|
|
22
|
+
example of the resolve-by-name convention.
|
|
23
|
+
|
|
24
|
+
## 0.3.1
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- Regeneration keeps what a repo already had, and a fleet can declare a repo has no gates.
|
|
29
|
+
|
|
30
|
+
**Preservation moved into the generator.** `etymd gates` read the existing hook and kept a test
|
|
31
|
+
step it already ran; every other caller of `planWorkflow` did not — including the fleet gate-drift
|
|
32
|
+
check, which therefore compared each repo against a hook missing checks the repo really runs.
|
|
33
|
+
That reported permanent false drift, and anyone acting on it would have silently lost a check. A
|
|
34
|
+
guarantee that holds only on the path someone remembered to wire it into is not a guarantee.
|
|
35
|
+
|
|
36
|
+
**`gates: "none"` in a fleet manifest** declares that generated gates are deliberately absent — a
|
|
37
|
+
prose repo with nothing mechanically checkable, or one that gates itself by hand. Gate drift sits
|
|
38
|
+
among the wall checks, which are deliberately not ledger-quietable because a leak or a partition
|
|
39
|
+
breach has no honest resolution except a fix; that reasoning does not transfer to a settled
|
|
40
|
+
choice, and an un-silenceable finding for a decision already made is how a report teaches people
|
|
41
|
+
to stop reading it. The absence is disclosed rather than hidden, and an _undeclared_ absence still
|
|
42
|
+
reports — silence has to be earned by declaring it.
|
|
43
|
+
|
|
44
|
+
**A hand-written `.etymd/config.json` no longer crashes the generator.** Setting only
|
|
45
|
+
`gates.failOn` threw: the type declares `commands` as required, describing the shape etymd writes
|
|
46
|
+
rather than the shape a user writes.
|
|
47
|
+
|
|
48
|
+
**The publish gate points at the committed script.** `prepublishOnly` resolving a bare
|
|
49
|
+
`artifact-check` from `PATH` meant the door guarding what actually ships was silently absent for
|
|
50
|
+
every clone but one.
|
|
51
|
+
|
|
3
52
|
## 0.3.0
|
|
4
53
|
|
|
5
54
|
### Minor Changes
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { section, theme, print, renderBaselineDrift, glyph } from './chunk-TADKOW6P.js';
|
|
3
|
+
import { scanProject } from './chunk-7MOBQ4N5.js';
|
|
4
|
+
import { VERSION } from './chunk-B3SUTZVY.js';
|
|
3
5
|
import { readBaseline, summarizeBaselineDrift, isDriftEmpty, writeBaseline, deriveProfile } from './chunk-R74SJ7HS.js';
|
|
4
|
-
import { scanProject } from './chunk-MKYPLNLH.js';
|
|
5
|
-
import { VERSION } from './chunk-NFENQ3IK.js';
|
|
6
6
|
import { PACK_VERSION } from './chunk-CRJHIXJH.js';
|
|
7
7
|
import './chunk-YLNQQZ5F.js';
|
|
8
8
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { run } from './chunk-
|
|
3
|
-
import './chunk-
|
|
2
|
+
export { run } from './chunk-WOBHQQ6H.js';
|
|
3
|
+
import './chunk-WUGBAW6Z.js';
|
|
4
4
|
import './chunk-LT67FU2Y.js';
|
|
5
5
|
import './chunk-WWBF4Y7K.js';
|
|
6
6
|
import './chunk-NMZ3RHWW.js';
|
|
7
7
|
import './chunk-TADKOW6P.js';
|
|
8
|
+
import './chunk-7MOBQ4N5.js';
|
|
9
|
+
import './chunk-B3SUTZVY.js';
|
|
8
10
|
import './chunk-R74SJ7HS.js';
|
|
9
|
-
import './chunk-MKYPLNLH.js';
|
|
10
|
-
import './chunk-NFENQ3IK.js';
|
|
11
11
|
import './chunk-CRJHIXJH.js';
|
|
12
12
|
import './chunk-YLNQQZ5F.js';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { print, theme } from './chunk-TADKOW6P.js';
|
|
3
|
+
import { scanProject } from './chunk-7MOBQ4N5.js';
|
|
4
|
+
import './chunk-B3SUTZVY.js';
|
|
3
5
|
import { ETYMD_DIR } from './chunk-R74SJ7HS.js';
|
|
4
|
-
import { scanProject } from './chunk-MKYPLNLH.js';
|
|
5
|
-
import './chunk-NFENQ3IK.js';
|
|
6
6
|
import './chunk-CRJHIXJH.js';
|
|
7
7
|
import './chunk-YLNQQZ5F.js';
|
|
8
8
|
import { promises } from 'node:fs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { VERSION } from './chunk-
|
|
2
|
+
import { VERSION } from './chunk-B3SUTZVY.js';
|
|
3
3
|
import { PACK_VERSION } from './chunk-CRJHIXJH.js';
|
|
4
4
|
import { normalizeRelPath, isDirectory, readJson, git, matchesAnyGlob, pathExists, readText } from './chunk-YLNQQZ5F.js';
|
|
5
5
|
import path from 'node:path';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { DEFAULT_CONFIG } from './chunk-NMZ3RHWW.js';
|
|
2
3
|
import { PACK_VERSION } from './chunk-CRJHIXJH.js';
|
|
3
|
-
import {
|
|
4
|
+
import { readText, pathExists } from './chunk-YLNQQZ5F.js';
|
|
4
5
|
import path from 'node:path';
|
|
5
6
|
|
|
6
7
|
// src/pack/templates.ts
|
|
@@ -160,7 +161,7 @@ exit 0
|
|
|
160
161
|
function generatePrePushHook(facts, gates) {
|
|
161
162
|
const run = runPrefix(facts.packageManager);
|
|
162
163
|
const c = facts.commands;
|
|
163
|
-
const candidates = gates?.commands
|
|
164
|
+
const candidates = gates?.commands?.length ? gates.commands : [c.formatCheck, c.typecheck, c.lint];
|
|
164
165
|
const allowed = new Set(gates?.allowWriting ?? []);
|
|
165
166
|
const steps = candidates.filter(
|
|
166
167
|
(key) => Boolean(key) && (allowed.has(key) || isSafeGateCommand(c.raw[key]))
|
|
@@ -227,6 +228,16 @@ exit 0
|
|
|
227
228
|
}
|
|
228
229
|
|
|
229
230
|
// src/core/generate.ts
|
|
231
|
+
function derivedCommands(facts, existingHook) {
|
|
232
|
+
const c = facts.commands;
|
|
233
|
+
const base = [c.formatCheck, c.typecheck, c.lint].filter(
|
|
234
|
+
(k) => Boolean(k) && isSafeGateCommand(c.raw[k])
|
|
235
|
+
);
|
|
236
|
+
if (c.test && existingHook && new RegExp(`\\b${c.test}\\b`).test(existingHook)) {
|
|
237
|
+
base.push(c.test);
|
|
238
|
+
}
|
|
239
|
+
return base;
|
|
240
|
+
}
|
|
230
241
|
async function planWorkflow(root, facts, opts) {
|
|
231
242
|
const out = [];
|
|
232
243
|
const add = async (rel, contents, label, executable = false) => {
|
|
@@ -246,6 +257,7 @@ async function planWorkflow(root, facts, opts) {
|
|
|
246
257
|
await add("AGENTS.md", generateAgentsMd(facts), "Minimal operating contract (scaffold)");
|
|
247
258
|
}
|
|
248
259
|
if (opts.gates) {
|
|
260
|
+
const existingPrePush = await readText(path.join(root, ".githooks", "pre-push"));
|
|
249
261
|
await add(".githooks/pre-commit", generatePreCommitHook(), "Process gate (pre-commit)", true);
|
|
250
262
|
await add(
|
|
251
263
|
".githooks/commit-msg",
|
|
@@ -253,9 +265,15 @@ async function planWorkflow(root, facts, opts) {
|
|
|
253
265
|
"Content screen (commit message)",
|
|
254
266
|
true
|
|
255
267
|
);
|
|
268
|
+
const gateConfig = opts.gateConfig?.commands?.length ? opts.gateConfig : {
|
|
269
|
+
commands: derivedCommands(facts, existingPrePush ?? void 0),
|
|
270
|
+
failOn: opts.gateConfig?.failOn ?? DEFAULT_CONFIG.gates.failOn,
|
|
271
|
+
publishGate: opts.gateConfig?.publishGate,
|
|
272
|
+
allowWriting: opts.gateConfig?.allowWriting ?? []
|
|
273
|
+
};
|
|
256
274
|
await add(
|
|
257
275
|
".githooks/pre-push",
|
|
258
|
-
generatePrePushHook(facts,
|
|
276
|
+
generatePrePushHook(facts, gateConfig),
|
|
259
277
|
"Correctness gate (pre-push)",
|
|
260
278
|
true
|
|
261
279
|
);
|
|
@@ -271,4 +289,4 @@ async function planWorkflow(root, facts, opts) {
|
|
|
271
289
|
return out;
|
|
272
290
|
}
|
|
273
291
|
|
|
274
|
-
export { isSafeGateCommand, planWorkflow, runPrefix };
|
|
292
|
+
export { derivedCommands, isSafeGateCommand, planWorkflow, runPrefix };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { parseFailOnTier, runAudit, meetsFailOn } from './chunk-
|
|
2
|
+
import { parseFailOnTier, runAudit, meetsFailOn } from './chunk-WUGBAW6Z.js';
|
|
3
3
|
import { print, section, theme, renderLensCoverage, renderFindings, renderLedgerDiff } from './chunk-TADKOW6P.js';
|
|
4
4
|
|
|
5
5
|
// src/commands/audit.ts
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { measureContext } from './chunk-LT67FU2Y.js';
|
|
3
3
|
import { readLedger, reconcileLedger, writeLedger, visibleFindings } from './chunk-WWBF4Y7K.js';
|
|
4
4
|
import { DEFAULT_CONFIG, readConfig, CONFIG_FILE } from './chunk-NMZ3RHWW.js';
|
|
5
|
+
import { scanProject, expandFileGlobs } from './chunk-7MOBQ4N5.js';
|
|
5
6
|
import { ETYMD_DIR, writeCachedFacts, readBaseline, deriveProfile, baselineCarriesMachinePath, BASELINE_FILE } from './chunk-R74SJ7HS.js';
|
|
6
|
-
import { scanProject, expandFileGlobs } from './chunk-MKYPLNLH.js';
|
|
7
7
|
import { PACK_VERSION } from './chunk-CRJHIXJH.js';
|
|
8
8
|
import { pathExists, readJson, git, readText, isDirectory, matchesAnyGlob, isCiEnvironment, normalizeRelPath } from './chunk-YLNQQZ5F.js';
|
|
9
9
|
import path from 'node:path';
|
|
@@ -474,6 +474,7 @@ function deriveGateFindings(inv, disclosures = []) {
|
|
|
474
474
|
finding({
|
|
475
475
|
id: `${LENS_ID2}/hooks-not-wired`,
|
|
476
476
|
tier: "risk",
|
|
477
|
+
kind: "truth",
|
|
477
478
|
claim: "Tracked .githooks/ exist but git core.hooksPath is unset \u2014 the hooks never run",
|
|
478
479
|
evidence: [".githooks/"],
|
|
479
480
|
why: "Every check in those hooks is silently skipped on this clone.",
|
|
@@ -1329,9 +1330,7 @@ async function runAudit(root, opts = {}) {
|
|
|
1329
1330
|
};
|
|
1330
1331
|
}
|
|
1331
1332
|
const profile = baseline?.profile ?? deriveProfile(facts);
|
|
1332
|
-
const selected = LENSES.filter(
|
|
1333
|
-
(lens) => (!opts.kind || lens.kind === opts.kind) && (!opts.lensIds || opts.lensIds.includes(lens.id))
|
|
1334
|
-
);
|
|
1333
|
+
const selected = LENSES.filter((lens) => !opts.lensIds || opts.lensIds.includes(lens.id));
|
|
1335
1334
|
const reports = [];
|
|
1336
1335
|
for (const lens of selected) {
|
|
1337
1336
|
try {
|
|
@@ -1349,11 +1348,12 @@ async function runAudit(root, opts = {}) {
|
|
|
1349
1348
|
});
|
|
1350
1349
|
}
|
|
1351
1350
|
}
|
|
1352
|
-
const all = reports.flatMap((r) => r.findings);
|
|
1351
|
+
const all = reports.flatMap((r) => r.findings.map((f) => ({ ...f, kind: f.kind ?? r.kind })));
|
|
1352
|
+
const visible = opts.kind ? all.filter((f) => f.kind === opts.kind) : all;
|
|
1353
1353
|
const previous = await readLedger(ledgerRoot);
|
|
1354
1354
|
const outOfScope = reports.flatMap((r) => r.outOfScope ?? []);
|
|
1355
1355
|
const { ledger, diff } = reconcileLedger(previous, all, void 0, outOfScope);
|
|
1356
|
-
const fullRun =
|
|
1356
|
+
const fullRun = !opts.kind && !opts.lensIds;
|
|
1357
1357
|
const ledgerWritable = !opts.readOnlyRoot || ledgerRoot !== root;
|
|
1358
1358
|
if ((opts.persistLedger ?? true) && fullRun && ledgerWritable) {
|
|
1359
1359
|
await writeLedger(ledgerRoot, ledger);
|
|
@@ -1364,7 +1364,7 @@ async function runAudit(root, opts = {}) {
|
|
|
1364
1364
|
baseline,
|
|
1365
1365
|
config,
|
|
1366
1366
|
reports,
|
|
1367
|
-
findings: rankFindings(visibleFindings(
|
|
1367
|
+
findings: rankFindings(visibleFindings(visible, previous)),
|
|
1368
1368
|
ledger,
|
|
1369
1369
|
diff
|
|
1370
1370
|
};
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { VERSION } from './chunk-
|
|
2
|
+
import { VERSION } from './chunk-B3SUTZVY.js';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { Command } from 'commander';
|
|
5
5
|
import pc from 'picocolors';
|
|
@@ -31,7 +31,7 @@ program.command("audit").description("Verify every instruction claim against the
|
|
|
31
31
|
"exit non-zero when findings at/above this tier exist (risk|gap|polish)"
|
|
32
32
|
).action(
|
|
33
33
|
(opts, cmd) => action(async () => {
|
|
34
|
-
const { run } = await import('./audit-
|
|
34
|
+
const { run } = await import('./audit-IGIUGKSQ.js');
|
|
35
35
|
await run({
|
|
36
36
|
cwd: resolveCwd(cmd),
|
|
37
37
|
json: opts.json,
|
|
@@ -44,7 +44,7 @@ program.command("audit").description("Verify every instruction claim against the
|
|
|
44
44
|
);
|
|
45
45
|
program.command("init").description("Onboard the truth guard: approve the baseline; scaffold AGENTS.md only if missing").option("-y, --yes", "accept defaults without prompting (never overwrites)").action(
|
|
46
46
|
(opts, cmd) => action(async () => {
|
|
47
|
-
const { run } = await import('./init-
|
|
47
|
+
const { run } = await import('./init-WYVDRQ2J.js');
|
|
48
48
|
await run({ cwd: resolveCwd(cmd), yes: opts.yes });
|
|
49
49
|
})
|
|
50
50
|
);
|
|
@@ -52,19 +52,19 @@ program.command("approve").description(
|
|
|
52
52
|
"Re-approve the committed baseline after intentional structural changes (non-interactive)"
|
|
53
53
|
).action(
|
|
54
54
|
(_opts, cmd) => action(async () => {
|
|
55
|
-
const { run } = await import('./approve-
|
|
55
|
+
const { run } = await import('./approve-P255DGOI.js');
|
|
56
56
|
await run({ cwd: resolveCwd(cmd) });
|
|
57
57
|
})
|
|
58
58
|
);
|
|
59
59
|
program.command("scan").description("Deterministically reckon the project into a facts index").option("--json", "print the raw facts as JSON").option("--no-save", "do not write the .etymd cache").action(
|
|
60
60
|
(opts, cmd) => action(async () => {
|
|
61
|
-
const { run } = await import('./scan-
|
|
61
|
+
const { run } = await import('./scan-PZFF6LDA.js');
|
|
62
62
|
await run({ cwd: resolveCwd(cmd), json: opts.json, save: opts.save });
|
|
63
63
|
})
|
|
64
64
|
);
|
|
65
65
|
program.command("doctor").description('Alias for `audit --truth` \u2014 "are the recorded instructions still true?"').option("--json", "print findings as JSON").action(
|
|
66
66
|
(opts, cmd) => action(async () => {
|
|
67
|
-
const { run } = await import('./doctor-
|
|
67
|
+
const { run } = await import('./doctor-4LBUZHVD.js');
|
|
68
68
|
await run({ cwd: resolveCwd(cmd), json: opts.json });
|
|
69
69
|
})
|
|
70
70
|
);
|
|
@@ -76,7 +76,7 @@ program.command("context").description("Measure the always-loaded context footpr
|
|
|
76
76
|
);
|
|
77
77
|
program.command("brief").description("Emit a grounded briefing for the in-repo agent to complete the semantic layer").option("--human", "write a human onboarding brief instead of the agent briefing").action(
|
|
78
78
|
(opts, cmd) => action(async () => {
|
|
79
|
-
const { run } = await import('./brief-
|
|
79
|
+
const { run } = await import('./brief-SFZ2DR65.js');
|
|
80
80
|
await run({ cwd: resolveCwd(cmd), human: opts.human });
|
|
81
81
|
})
|
|
82
82
|
);
|
|
@@ -111,7 +111,7 @@ var fleet = program.command("fleet").description(
|
|
|
111
111
|
"exit non-zero when findings at/above this tier exist (risk|gap|polish)"
|
|
112
112
|
).action(
|
|
113
113
|
(opts, cmd) => action(async () => {
|
|
114
|
-
const { sweep } = await import('./fleet-
|
|
114
|
+
const { sweep } = await import('./fleet-Q6J5XIHH.js');
|
|
115
115
|
await sweep({
|
|
116
116
|
cwd: resolveCwd(cmd),
|
|
117
117
|
manifest: opts.manifest,
|
|
@@ -126,7 +126,7 @@ var fleet = program.command("fleet").description(
|
|
|
126
126
|
);
|
|
127
127
|
fleet.command("check").description("Validate the manifest pair only \u2014 no lenses: dangling mappings, duplicates, leaks").option("--manifest <file>", "the fleet manifest \u2014 required unless the cwd holds registry.json").option("--json", "print the findings as JSON (EXPERIMENTAL through 0.2.x)").action(
|
|
128
128
|
(_opts, cmd) => action(async () => {
|
|
129
|
-
const { check } = await import('./fleet-
|
|
129
|
+
const { check } = await import('./fleet-Q6J5XIHH.js');
|
|
130
130
|
const opts = cmd.optsWithGlobals();
|
|
131
131
|
await check({ cwd: resolveCwd(cmd), manifest: opts.manifest, json: opts.json });
|
|
132
132
|
})
|
|
@@ -136,7 +136,7 @@ fleet.command("add").argument("<dir>", "directory of the project to register").d
|
|
|
136
136
|
"public-repo | public-bound | private \u2014 mandatory for personal entries"
|
|
137
137
|
).option("-y, --yes", "skip prompts; every mandatory value must be passed as a flag").option("--manifest <file>", "the fleet manifest \u2014 required unless the cwd holds registry.json").action(
|
|
138
138
|
(dir, opts, cmd) => action(async () => {
|
|
139
|
-
const { add } = await import('./fleet-
|
|
139
|
+
const { add } = await import('./fleet-Q6J5XIHH.js');
|
|
140
140
|
const shared = cmd.optsWithGlobals();
|
|
141
141
|
await add({
|
|
142
142
|
cwd: resolveCwd(cmd),
|
|
@@ -154,7 +154,7 @@ fleet.command("dismiss").argument("<name>", "the registered project name").argum
|
|
|
154
154
|
"Dismiss a project's finding from any cwd \u2014 corp ledgers persist beside the manifest"
|
|
155
155
|
).requiredOption("--reason <text>", "why it is dismissed \u2014 recorded so the decision survives").option("--manifest <file>", "the fleet manifest \u2014 required unless the cwd holds registry.json").action(
|
|
156
156
|
(name, id, _opts, cmd) => action(async () => {
|
|
157
|
-
const { dismiss } = await import('./fleet-
|
|
157
|
+
const { dismiss } = await import('./fleet-Q6J5XIHH.js');
|
|
158
158
|
const opts = cmd.optsWithGlobals();
|
|
159
159
|
await dismiss({
|
|
160
160
|
cwd: resolveCwd(cmd),
|
|
@@ -169,7 +169,7 @@ fleet.command("accept").argument("<name>", "the registered project name").argume
|
|
|
169
169
|
"Accept a project's finding as a known trade-off \u2014 corp ledgers persist beside the manifest"
|
|
170
170
|
).option("--reason <text>", "optional note on why the trade-off is accepted").option("--manifest <file>", "the fleet manifest \u2014 required unless the cwd holds registry.json").action(
|
|
171
171
|
(name, id, _opts, cmd) => action(async () => {
|
|
172
|
-
const { accept } = await import('./fleet-
|
|
172
|
+
const { accept } = await import('./fleet-Q6J5XIHH.js');
|
|
173
173
|
const opts = cmd.optsWithGlobals();
|
|
174
174
|
await accept({ cwd: resolveCwd(cmd), manifest: opts.manifest, name, id, reason: opts.reason });
|
|
175
175
|
})
|
|
@@ -191,7 +191,7 @@ program.command("screen").description(
|
|
|
191
191
|
);
|
|
192
192
|
program.command("gates").description("Install the local git-hook gates (process \u2192 pre-commit, correctness \u2192 pre-push)").option("--ci", "note about the CI review gate (ships later; local gates install now)").option("-y, --yes", "skip prompts; never overwrites a hand-edited hook").action(
|
|
193
193
|
(opts, cmd) => action(async () => {
|
|
194
|
-
const { run } = await import('./gates-
|
|
194
|
+
const { run } = await import('./gates-T5J3H7WL.js');
|
|
195
195
|
await run({ cwd: resolveCwd(cmd), ci: opts.ci, yes: opts.yes });
|
|
196
196
|
})
|
|
197
197
|
);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { run } from './chunk-
|
|
3
|
-
import './chunk-
|
|
2
|
+
import { run } from './chunk-WOBHQQ6H.js';
|
|
3
|
+
import './chunk-WUGBAW6Z.js';
|
|
4
4
|
import './chunk-LT67FU2Y.js';
|
|
5
5
|
import './chunk-WWBF4Y7K.js';
|
|
6
6
|
import './chunk-NMZ3RHWW.js';
|
|
7
7
|
import './chunk-TADKOW6P.js';
|
|
8
|
+
import './chunk-7MOBQ4N5.js';
|
|
9
|
+
import './chunk-B3SUTZVY.js';
|
|
8
10
|
import './chunk-R74SJ7HS.js';
|
|
9
|
-
import './chunk-MKYPLNLH.js';
|
|
10
|
-
import './chunk-NFENQ3IK.js';
|
|
11
11
|
import './chunk-CRJHIXJH.js';
|
|
12
12
|
import './chunk-YLNQQZ5F.js';
|
|
13
13
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { dismiss, accept } from './chunk-MMPV67FW.js';
|
|
3
|
-
import { parseFailOnTier, meetsFailOn, runAudit } from './chunk-
|
|
3
|
+
import { parseFailOnTier, meetsFailOn, runAudit } from './chunk-WUGBAW6Z.js';
|
|
4
4
|
import './chunk-LT67FU2Y.js';
|
|
5
5
|
import { readLedger } from './chunk-WWBF4Y7K.js';
|
|
6
6
|
import { DEFAULT_CONFIG } from './chunk-NMZ3RHWW.js';
|
|
7
7
|
import { print, theme, section, renderFleetRows, renderFleetNotes, renderFindings, TIER_BADGE, glyph } from './chunk-TADKOW6P.js';
|
|
8
|
+
import { scanProject } from './chunk-7MOBQ4N5.js';
|
|
9
|
+
import './chunk-B3SUTZVY.js';
|
|
8
10
|
import { ETYMD_DIR } from './chunk-R74SJ7HS.js';
|
|
9
|
-
import { scanProject } from './chunk-MKYPLNLH.js';
|
|
10
|
-
import './chunk-NFENQ3IK.js';
|
|
11
11
|
import './chunk-CRJHIXJH.js';
|
|
12
12
|
import { readText, pathExists, git, isDirectory } from './chunk-YLNQQZ5F.js';
|
|
13
13
|
import { promises } from 'node:fs';
|
|
@@ -119,6 +119,7 @@ function loadRegistryEntries(projects, manifest, manifestFile) {
|
|
|
119
119
|
// An unknown value is NOT coerced to a default: trust gates content screening, so a typo
|
|
120
120
|
// must surface as "undeclared" (a finding) rather than quietly picking an answer.
|
|
121
121
|
trust: isFleetTrust(rec.trust) ? rec.trust : void 0,
|
|
122
|
+
gates: asString(rec.gates),
|
|
122
123
|
trustRaw: asString(rec.trust),
|
|
123
124
|
staleAfterDays: typeof rec.staleAfterDays === "number" ? rec.staleAfterDays : void 0,
|
|
124
125
|
stateBudget: typeof rec.stateBudget === "number" ? rec.stateBudget : void 0,
|
|
@@ -686,13 +687,17 @@ async function checkCorpEmails(manifest, findings, disclosures) {
|
|
|
686
687
|
}
|
|
687
688
|
}
|
|
688
689
|
async function checkGateDrift(manifest, findings, disclosures) {
|
|
689
|
-
const { planWorkflow } = await import('./generate-
|
|
690
|
-
const { scanProject: scanProject2 } = await import('./scan-
|
|
690
|
+
const { planWorkflow } = await import('./generate-I75IEXXF.js');
|
|
691
|
+
const { scanProject: scanProject2 } = await import('./scan-IY3LCBJ6.js');
|
|
691
692
|
const { readConfig } = await import('./config-MX7OYI7F.js');
|
|
692
693
|
for (const entry of manifest.entries) {
|
|
693
694
|
const root = entry.resolvedRoot;
|
|
694
695
|
if (!root || !await isDirectory(root)) continue;
|
|
695
696
|
if (entry.profile === "corp" || entry.private) continue;
|
|
697
|
+
if (entry.gates === "none") {
|
|
698
|
+
disclosures.push(`${entry.name}: gates declared \`none\` \u2014 deliberately absent, not missing`);
|
|
699
|
+
continue;
|
|
700
|
+
}
|
|
696
701
|
const facts = await scanProject2(root);
|
|
697
702
|
if (!facts.git.isRepo) continue;
|
|
698
703
|
if (facts.hooks.source === "husky" || facts.hooks.source === "husky-legacy") {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { readConfig, CONFIG_FILE, configPath } from './chunk-NMZ3RHWW.js';
|
|
3
2
|
import { applyFiles } from './chunk-EF6BPBG6.js';
|
|
4
|
-
import {
|
|
3
|
+
import { derivedCommands, planWorkflow, runPrefix, isSafeGateCommand } from './chunk-VFUYQLW7.js';
|
|
4
|
+
import { readConfig, CONFIG_FILE, configPath } from './chunk-NMZ3RHWW.js';
|
|
5
5
|
import { section, print, glyph, theme, renderPlan } from './chunk-TADKOW6P.js';
|
|
6
|
+
import { scanProject } from './chunk-7MOBQ4N5.js';
|
|
7
|
+
import './chunk-B3SUTZVY.js';
|
|
6
8
|
import './chunk-R74SJ7HS.js';
|
|
7
|
-
import { scanProject } from './chunk-MKYPLNLH.js';
|
|
8
|
-
import './chunk-NFENQ3IK.js';
|
|
9
9
|
import './chunk-CRJHIXJH.js';
|
|
10
10
|
import { readText, git } from './chunk-YLNQQZ5F.js';
|
|
11
11
|
import { promises } from 'node:fs';
|
|
@@ -55,16 +55,6 @@ var PUBLISH_GATE_VALUE = `./${PUBLISH_GATE_SCRIPT}`;
|
|
|
55
55
|
function publishGateKey(route) {
|
|
56
56
|
return route === "vscode" ? "vscode:prepublish" : "prepublishOnly";
|
|
57
57
|
}
|
|
58
|
-
function derivedCommands(facts, existingHook) {
|
|
59
|
-
const c = facts.commands;
|
|
60
|
-
const base = [c.formatCheck, c.typecheck, c.lint].filter(
|
|
61
|
-
(k) => Boolean(k) && isSafeGateCommand(c.raw[k])
|
|
62
|
-
);
|
|
63
|
-
if (c.test && existingHook && new RegExp(`\\b${c.test}\\b`).test(existingHook)) {
|
|
64
|
-
base.push(c.test);
|
|
65
|
-
}
|
|
66
|
-
return base;
|
|
67
|
-
}
|
|
68
58
|
function printGateSummary(gates, facts, source) {
|
|
69
59
|
const run2 = runPrefix(facts.packageManager);
|
|
70
60
|
const cmds = gates.commands.length ? gates.commands.map((c) => `${run2} ${c}`).join(", ") : "none detected";
|
|
@@ -269,4 +259,4 @@ async function run(opts) {
|
|
|
269
259
|
}
|
|
270
260
|
}
|
|
271
261
|
|
|
272
|
-
export {
|
|
262
|
+
export { mergeGateSection, run };
|
package/dist/index.d.ts
CHANGED
|
@@ -279,6 +279,13 @@ interface Finding {
|
|
|
279
279
|
id: string;
|
|
280
280
|
lens: string;
|
|
281
281
|
tier: FindingTier;
|
|
282
|
+
/**
|
|
283
|
+
* Whether this finding is an objective truth (the repo is lying) or an improvement opinion
|
|
284
|
+
* (something worth doing). Lives ON THE FINDING, not the lens: a lens can emit both kinds —
|
|
285
|
+
* gate-integrity is an improvement lens, but "hooks-not-wired" is an objective truth a `doctor`
|
|
286
|
+
* run must not skip. Defaulted from the lens kind when a finding does not set its own.
|
|
287
|
+
*/
|
|
288
|
+
kind?: LensKind;
|
|
282
289
|
/** One sentence: what is wrong / missing. */
|
|
283
290
|
claim: string;
|
|
284
291
|
/** File paths, job names, or metrics that ground the claim. Never empty. */
|
|
@@ -492,6 +499,15 @@ interface FleetEntry {
|
|
|
492
499
|
/** A declared `trust` value outside the vocabulary — preserved verbatim so the check can name it. */
|
|
493
500
|
trustRaw?: string;
|
|
494
501
|
staleAfterDays?: number;
|
|
502
|
+
/**
|
|
503
|
+
* How this entry's git hooks are governed. `"none"` declares that generated gates are
|
|
504
|
+
* deliberately absent — a prose repo with nothing mechanically checkable, or one whose gate is
|
|
505
|
+
* hand-written on purpose. Wall findings cannot be quieted through the ledger (004: their only
|
|
506
|
+
* honest resolution is fixing them), which is right for leak and partition conditions but
|
|
507
|
+
* wrong for a state a fleet legitimately chooses; without this, a settled decision is
|
|
508
|
+
* re-reported on every sweep until the report is ignored.
|
|
509
|
+
*/
|
|
510
|
+
gates?: string;
|
|
495
511
|
/** Per-entry state char-budget override (ships unset — the schema slot exists). */
|
|
496
512
|
stateBudget?: number;
|
|
497
513
|
contract: FleetContract;
|
package/dist/index.js
CHANGED
|
@@ -29,7 +29,7 @@ var init_package = __esm({
|
|
|
29
29
|
"package.json"() {
|
|
30
30
|
package_default = {
|
|
31
31
|
name: "etymd",
|
|
32
|
-
version: "0.3.
|
|
32
|
+
version: "0.3.2",
|
|
33
33
|
description: "Keep your agent instructions true \u2014 verify AGENTS.md, CLAUDE.md, rules & skills against the actual repo, with drift caught over time and a regression ledger.",
|
|
34
34
|
keywords: [
|
|
35
35
|
"cli",
|
|
@@ -87,7 +87,7 @@ var init_package = __esm({
|
|
|
87
87
|
"format:check": "prettier --check . && npm run guard:md",
|
|
88
88
|
"guard:md": "! grep -rnF --include=*.md --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=.git '\\*\\*' .",
|
|
89
89
|
prepare: "npm run build",
|
|
90
|
-
prepublishOnly: "npm run build && artifact-check",
|
|
90
|
+
prepublishOnly: "npm run build && ./scripts/artifact-check.sh",
|
|
91
91
|
changeset: "changeset",
|
|
92
92
|
"version:packages": "changeset version",
|
|
93
93
|
release: "npm run build && changeset publish"
|
|
@@ -1118,7 +1118,7 @@ exit 0
|
|
|
1118
1118
|
function generatePrePushHook(facts, gates) {
|
|
1119
1119
|
const run = runPrefix(facts.packageManager);
|
|
1120
1120
|
const c = facts.commands;
|
|
1121
|
-
const candidates = gates?.commands
|
|
1121
|
+
const candidates = gates?.commands?.length ? gates.commands : [c.formatCheck, c.typecheck, c.lint];
|
|
1122
1122
|
const allowed = new Set(gates?.allowWriting ?? []);
|
|
1123
1123
|
const steps = candidates.filter(
|
|
1124
1124
|
(key) => Boolean(key) && (allowed.has(key) || isSafeGateCommand(c.raw[key]))
|
|
@@ -1194,8 +1194,19 @@ var init_templates = __esm({
|
|
|
1194
1194
|
// src/core/generate.ts
|
|
1195
1195
|
var generate_exports = {};
|
|
1196
1196
|
__export(generate_exports, {
|
|
1197
|
+
derivedCommands: () => derivedCommands,
|
|
1197
1198
|
planWorkflow: () => planWorkflow
|
|
1198
1199
|
});
|
|
1200
|
+
function derivedCommands(facts, existingHook) {
|
|
1201
|
+
const c = facts.commands;
|
|
1202
|
+
const base = [c.formatCheck, c.typecheck, c.lint].filter(
|
|
1203
|
+
(k) => Boolean(k) && isSafeGateCommand(c.raw[k])
|
|
1204
|
+
);
|
|
1205
|
+
if (c.test && existingHook && new RegExp(`\\b${c.test}\\b`).test(existingHook)) {
|
|
1206
|
+
base.push(c.test);
|
|
1207
|
+
}
|
|
1208
|
+
return base;
|
|
1209
|
+
}
|
|
1199
1210
|
async function planWorkflow(root, facts, opts) {
|
|
1200
1211
|
const out = [];
|
|
1201
1212
|
const add = async (rel, contents, label, executable = false) => {
|
|
@@ -1215,6 +1226,7 @@ async function planWorkflow(root, facts, opts) {
|
|
|
1215
1226
|
await add("AGENTS.md", generateAgentsMd(facts), "Minimal operating contract (scaffold)");
|
|
1216
1227
|
}
|
|
1217
1228
|
if (opts.gates) {
|
|
1229
|
+
const existingPrePush = await readText(path.join(root, ".githooks", "pre-push"));
|
|
1218
1230
|
await add(".githooks/pre-commit", generatePreCommitHook(), "Process gate (pre-commit)", true);
|
|
1219
1231
|
await add(
|
|
1220
1232
|
".githooks/commit-msg",
|
|
@@ -1222,9 +1234,15 @@ async function planWorkflow(root, facts, opts) {
|
|
|
1222
1234
|
"Content screen (commit message)",
|
|
1223
1235
|
true
|
|
1224
1236
|
);
|
|
1237
|
+
const gateConfig = opts.gateConfig?.commands?.length ? opts.gateConfig : {
|
|
1238
|
+
commands: derivedCommands(facts, existingPrePush ?? void 0),
|
|
1239
|
+
failOn: opts.gateConfig?.failOn ?? DEFAULT_CONFIG.gates.failOn,
|
|
1240
|
+
publishGate: opts.gateConfig?.publishGate,
|
|
1241
|
+
allowWriting: opts.gateConfig?.allowWriting ?? []
|
|
1242
|
+
};
|
|
1225
1243
|
await add(
|
|
1226
1244
|
".githooks/pre-push",
|
|
1227
|
-
generatePrePushHook(facts,
|
|
1245
|
+
generatePrePushHook(facts, gateConfig),
|
|
1228
1246
|
"Correctness gate (pre-push)",
|
|
1229
1247
|
true
|
|
1230
1248
|
);
|
|
@@ -1242,6 +1260,7 @@ async function planWorkflow(root, facts, opts) {
|
|
|
1242
1260
|
var init_generate = __esm({
|
|
1243
1261
|
"src/core/generate.ts"() {
|
|
1244
1262
|
init_templates();
|
|
1263
|
+
init_config();
|
|
1245
1264
|
init_util();
|
|
1246
1265
|
}
|
|
1247
1266
|
});
|
|
@@ -1787,6 +1806,7 @@ function deriveGateFindings(inv, disclosures = []) {
|
|
|
1787
1806
|
finding({
|
|
1788
1807
|
id: `${LENS_ID2}/hooks-not-wired`,
|
|
1789
1808
|
tier: "risk",
|
|
1809
|
+
kind: "truth",
|
|
1790
1810
|
claim: "Tracked .githooks/ exist but git core.hooksPath is unset \u2014 the hooks never run",
|
|
1791
1811
|
evidence: [".githooks/"],
|
|
1792
1812
|
why: "Every check in those hooks is silently skipped on this clone.",
|
|
@@ -2750,9 +2770,7 @@ async function runAudit(root, opts = {}) {
|
|
|
2750
2770
|
};
|
|
2751
2771
|
}
|
|
2752
2772
|
const profile = baseline?.profile ?? deriveProfile(facts);
|
|
2753
|
-
const selected = LENSES.filter(
|
|
2754
|
-
(lens) => (!opts.kind || lens.kind === opts.kind) && (!opts.lensIds || opts.lensIds.includes(lens.id))
|
|
2755
|
-
);
|
|
2773
|
+
const selected = LENSES.filter((lens) => !opts.lensIds || opts.lensIds.includes(lens.id));
|
|
2756
2774
|
const reports = [];
|
|
2757
2775
|
for (const lens of selected) {
|
|
2758
2776
|
try {
|
|
@@ -2770,11 +2788,12 @@ async function runAudit(root, opts = {}) {
|
|
|
2770
2788
|
});
|
|
2771
2789
|
}
|
|
2772
2790
|
}
|
|
2773
|
-
const all = reports.flatMap((r) => r.findings);
|
|
2791
|
+
const all = reports.flatMap((r) => r.findings.map((f) => ({ ...f, kind: f.kind ?? r.kind })));
|
|
2792
|
+
const visible = opts.kind ? all.filter((f) => f.kind === opts.kind) : all;
|
|
2774
2793
|
const previous = await readLedger(ledgerRoot);
|
|
2775
2794
|
const outOfScope = reports.flatMap((r) => r.outOfScope ?? []);
|
|
2776
2795
|
const { ledger, diff } = reconcileLedger(previous, all, void 0, outOfScope);
|
|
2777
|
-
const fullRun =
|
|
2796
|
+
const fullRun = !opts.kind && !opts.lensIds;
|
|
2778
2797
|
const ledgerWritable = !opts.readOnlyRoot || ledgerRoot !== root;
|
|
2779
2798
|
if ((opts.persistLedger ?? true) && fullRun && ledgerWritable) {
|
|
2780
2799
|
await writeLedger(ledgerRoot, ledger);
|
|
@@ -2785,7 +2804,7 @@ async function runAudit(root, opts = {}) {
|
|
|
2785
2804
|
baseline,
|
|
2786
2805
|
config,
|
|
2787
2806
|
reports,
|
|
2788
|
-
findings: rankFindings(visibleFindings(
|
|
2807
|
+
findings: rankFindings(visibleFindings(visible, previous)),
|
|
2789
2808
|
ledger,
|
|
2790
2809
|
diff
|
|
2791
2810
|
};
|
|
@@ -2895,6 +2914,7 @@ function loadRegistryEntries(projects, manifest, manifestFile) {
|
|
|
2895
2914
|
// An unknown value is NOT coerced to a default: trust gates content screening, so a typo
|
|
2896
2915
|
// must surface as "undeclared" (a finding) rather than quietly picking an answer.
|
|
2897
2916
|
trust: isFleetTrust(rec.trust) ? rec.trust : void 0,
|
|
2917
|
+
gates: asString(rec.gates),
|
|
2898
2918
|
trustRaw: asString(rec.trust),
|
|
2899
2919
|
staleAfterDays: typeof rec.staleAfterDays === "number" ? rec.staleAfterDays : void 0,
|
|
2900
2920
|
stateBudget: typeof rec.stateBudget === "number" ? rec.stateBudget : void 0,
|
|
@@ -3474,6 +3494,10 @@ async function checkGateDrift(manifest, findings, disclosures) {
|
|
|
3474
3494
|
const root = entry.resolvedRoot;
|
|
3475
3495
|
if (!root || !await isDirectory(root)) continue;
|
|
3476
3496
|
if (entry.profile === "corp" || entry.private) continue;
|
|
3497
|
+
if (entry.gates === "none") {
|
|
3498
|
+
disclosures.push(`${entry.name}: gates declared \`none\` \u2014 deliberately absent, not missing`);
|
|
3499
|
+
continue;
|
|
3500
|
+
}
|
|
3477
3501
|
const facts = await scanProject2(root);
|
|
3478
3502
|
if (!facts.git.isRepo) continue;
|
|
3479
3503
|
if (facts.hooks.source === "husky" || facts.hooks.source === "husky-legacy") {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { applyFiles } from './chunk-EF6BPBG6.js';
|
|
3
|
-
import { planWorkflow } from './chunk-
|
|
3
|
+
import { planWorkflow } from './chunk-VFUYQLW7.js';
|
|
4
|
+
import './chunk-NMZ3RHWW.js';
|
|
4
5
|
import { theme, renderFacts, print, renderPlan, section, glyph } from './chunk-TADKOW6P.js';
|
|
6
|
+
import { scanProject } from './chunk-7MOBQ4N5.js';
|
|
7
|
+
import { VERSION } from './chunk-B3SUTZVY.js';
|
|
5
8
|
import { writeCachedFacts, deriveProfile, writeBaseline, CACHE_DIR } from './chunk-R74SJ7HS.js';
|
|
6
|
-
import { scanProject } from './chunk-MKYPLNLH.js';
|
|
7
|
-
import { VERSION } from './chunk-NFENQ3IK.js';
|
|
8
9
|
import { PACK_VERSION } from './chunk-CRJHIXJH.js';
|
|
9
10
|
import { git, readText } from './chunk-YLNQQZ5F.js';
|
|
10
11
|
import { promises } from 'node:fs';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { print, renderFacts, theme } from './chunk-TADKOW6P.js';
|
|
3
|
+
import { scanProject } from './chunk-7MOBQ4N5.js';
|
|
4
|
+
import './chunk-B3SUTZVY.js';
|
|
3
5
|
import { writeCachedFacts } from './chunk-R74SJ7HS.js';
|
|
4
|
-
import { scanProject } from './chunk-MKYPLNLH.js';
|
|
5
|
-
import './chunk-NFENQ3IK.js';
|
|
6
6
|
import './chunk-CRJHIXJH.js';
|
|
7
7
|
import './chunk-YLNQQZ5F.js';
|
|
8
8
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "etymd",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Keep your agent instructions true — verify AGENTS.md, CLAUDE.md, rules & skills against the actual repo, with drift caught over time and a regression ledger.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"format:check": "prettier --check . && npm run guard:md",
|
|
59
59
|
"guard:md": "! grep -rnF --include=*.md --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=.git '\\*\\*' .",
|
|
60
60
|
"prepare": "npm run build",
|
|
61
|
-
"prepublishOnly": "npm run build && artifact-check",
|
|
61
|
+
"prepublishOnly": "npm run build && ./scripts/artifact-check.sh",
|
|
62
62
|
"changeset": "changeset",
|
|
63
63
|
"version:packages": "changeset version",
|
|
64
64
|
"release": "npm run build && changeset publish"
|