etymd 0.15.0 → 0.17.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.
@@ -168,7 +168,7 @@ function generatePreCommitHook(selfBuild = false) {
168
168
 
169
169
  ${localHookCall("pre-commit")}
170
170
 
171
- # Content screen \u2014 staged file bytes. Refuses to commit environment, employer or identity
171
+ # Content screen \u2014 staged file bytes. Refuses to commit environment, guarded-side or identity
172
172
  # detail into a repo whose history is (or could become) public. The checker and its patterns
173
173
  # are machine-local by design, so this is a NO-OP wherever no checker is installed: safe to
174
174
  # commit anywhere, active only where you opted in.
@@ -431,9 +431,13 @@ async function planWorkflow(root, facts, opts) {
431
431
  commitFormat: opts.gateConfig?.commitFormat,
432
432
  allowWriting: opts.gateConfig?.allowWriting ?? []
433
433
  };
434
+ const tier = deriveFailOn(facts, {
435
+ failOn: gateConfig.failOn,
436
+ explicit: opts.gateFailOnPinned ?? false
437
+ });
434
438
  await add(
435
439
  ".githooks/pre-push",
436
- generatePrePushHook(facts, gateConfig, selfBuild),
440
+ generatePrePushHook(facts, { ...gateConfig, failOn: tier.failOn }, selfBuild),
437
441
  "Correctness gate (pre-push)",
438
442
  true
439
443
  );
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { stateFreshnessLens, rankFindings, listInstructionFiles, buildTruthEnv, emptyCounters, packageManagerUsage, checkDocRefs, listStateDocuments, loadDecisionLedger, checkDecisionRefs, checkTextClaims } from './chunk-IWG77WV3.js';
2
+ import { stateFreshnessLens, rankFindings, listInstructionFiles, buildTruthEnv, emptyCounters, packageManagerUsage, checkDocRefs, listStateDocuments, loadDecisionLedger, checkDecisionRefs, checkTextClaims } from './chunk-FNA4R5KT.js';
3
3
  import { readLedger, reconcileLedger, writeLedger, visibleFindings } from './chunk-3E2IPCRY.js';
4
4
  import { measureContext, contextFileLabel } from './chunk-HI7NWPRA.js';
5
- import { scanProject } from './chunk-Y6RZRED3.js';
5
+ import { scanProject } from './chunk-446EZNAQ.js';
6
6
  import { DEFAULT_CONFIG, ETYMD_DIR, writeCachedFacts, readBaseline, readConfig, deriveProfile, baselineCarriesMachinePath, BASELINE_FILE, CONFIG_FILE } from './chunk-P6ATKV2R.js';
7
7
  import { PACK_VERSION } from './chunk-YQZDYDAK.js';
8
8
  import { pathExists, readText, readJson, isCiEnvironment, isExecutable } from './chunk-4VPBP6K6.js';
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { VERSION } from './chunk-DBWDMIYO.js';
2
+ import { VERSION } from './chunk-BUMOGHQA.js';
3
3
  import path from '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-YSALDC2L.js');
34
+ const { run } = await import('./audit-PHAK5HEW.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 asked").option("-y, --yes", "accept defaults without prompting (never overwrites)").option("--with-agents", "also scaffold a minimal AGENTS.md where none exists (off by default)").action(
46
46
  (opts, cmd) => action(async () => {
47
- const { run } = await import('./init-H57H2JBE.js');
47
+ const { run } = await import('./init-6RULX5JZ.js');
48
48
  await run({ cwd: resolveCwd(cmd), yes: opts.yes, withAgents: opts.withAgents });
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-MA4Z3TBT.js');
55
+ const { run } = await import('./approve-VN4EDBR5.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-XBOHDXAH.js');
61
+ const { run } = await import('./scan-LLWW4YOU.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-Y3DWDEBT.js');
67
+ const { run } = await import('./doctor-R4QDCAN5.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-DPZYSAMC.js');
79
+ const { run } = await import('./brief-7MWP35UI.js');
80
80
  await run({ cwd: resolveCwd(cmd), human: opts.human });
81
81
  })
82
82
  );
@@ -90,7 +90,7 @@ program.command("premise").argument("[task]", "the task you are about to hand an
90
90
  "exit non-zero when findings at/above this tier exist (risk|gap|polish)"
91
91
  ).action(
92
92
  (task, opts, cmd) => action(async () => {
93
- const { run } = await import('./premise-VMC3UUIB.js');
93
+ const { run } = await import('./premise-GFWHSR3K.js');
94
94
  await run({
95
95
  cwd: resolveCwd(cmd),
96
96
  task,
@@ -124,15 +124,15 @@ var fleet = program.command("fleet").description(
124
124
  ).option(
125
125
  "--manifest <file>",
126
126
  "the fleet manifest (registry.json / legacy sources.json) \u2014 required unless the cwd holds registry.json"
127
- ).option("--only <names...>", "sweep only these registered names").option("--profile <profile>", "sweep only entries with this profile (personal|corp)").option("--truth", "truth lenses only per repo (the doctor subset)").option(
127
+ ).option("--only <names...>", "sweep only these registered names").option("--profile <profile>", "sweep only entries with this profile (personal|guarded)").option("--truth", "truth lenses only per repo (the doctor subset)").option(
128
128
  "--persist-ledgers",
129
- "persist per-repo ledgers \u2014 personal-profile entries that already carry .etymd only; corp worktrees are never written"
129
+ "persist per-repo ledgers \u2014 personal-profile entries that already carry .etymd only; guarded worktrees are never written"
130
130
  ).option("--json", "print the machine schema (EXPERIMENTAL through 0.2.x, local-only)").option(
131
131
  "--fail-on <tier>",
132
132
  "exit non-zero when findings at/above this tier exist (risk|gap|polish)"
133
133
  ).action(
134
134
  (opts, cmd) => action(async () => {
135
- const { sweep } = await import('./fleet-4FYZ3GBK.js');
135
+ const { sweep } = await import('./fleet-WPYEVHVL.js');
136
136
  await sweep({
137
137
  cwd: resolveCwd(cmd),
138
138
  manifest: opts.manifest,
@@ -147,17 +147,32 @@ var fleet = program.command("fleet").description(
147
147
  );
148
148
  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(
149
149
  (_opts, cmd) => action(async () => {
150
- const { check } = await import('./fleet-4FYZ3GBK.js');
150
+ const { check } = await import('./fleet-WPYEVHVL.js');
151
151
  const opts = cmd.optsWithGlobals();
152
152
  await check({ cwd: resolveCwd(cmd), manifest: opts.manifest, json: opts.json });
153
153
  })
154
154
  );
155
- fleet.command("add").argument("<dir>", "directory of the project to register").description("Register a project \u2014 refuses to write an entry missing a mandatory field").option("--name <name>", "registered name (defaults to the directory's basename)").option("--kind <kind>", "entry kind (defaults to a value derived from the scan)").option("--profile <profile>", "personal | corp (default: personal)").option(
155
+ fleet.command("board").description(
156
+ "Render the fleet board: every project's milestones (contract key `milestones`) plus a ranked initiatives table"
157
+ ).option("--manifest <file>", "the fleet manifest \u2014 required unless the cwd holds registry.json").option("--initiatives <file>", "the hand-edited initiatives table (rank | id | initiative | \u2026)").option("--out <file>", "write the Markdown board here instead of printing it").option("--json", "print the board as JSON (EXPERIMENTAL)").action(
158
+ (opts, cmd) => action(async () => {
159
+ const { board } = await import('./fleet-WPYEVHVL.js');
160
+ const shared = cmd.optsWithGlobals();
161
+ await board({
162
+ cwd: resolveCwd(cmd),
163
+ manifest: shared.manifest,
164
+ initiatives: opts.initiatives,
165
+ out: opts.out,
166
+ json: opts.json ?? shared.json
167
+ });
168
+ })
169
+ );
170
+ fleet.command("add").argument("<dir>", "directory of the project to register").description("Register a project \u2014 refuses to write an entry missing a mandatory field").option("--name <name>", "registered name (defaults to the directory's basename)").option("--kind <kind>", "entry kind (defaults to a value derived from the scan)").option("--profile <profile>", "personal | guarded (default: personal)").option(
156
171
  "--trust <level>",
157
172
  "public-repo | public-bound | private \u2014 mandatory for personal entries"
158
173
  ).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(
159
174
  (dir, opts, cmd) => action(async () => {
160
- const { add } = await import('./fleet-4FYZ3GBK.js');
175
+ const { add } = await import('./fleet-WPYEVHVL.js');
161
176
  const shared = cmd.optsWithGlobals();
162
177
  await add({
163
178
  cwd: resolveCwd(cmd),
@@ -167,9 +182,9 @@ fleet.command("add").argument("<dir>", "directory of the project to register").d
167
182
  kind: opts.kind,
168
183
  // `fleet` declares its own --profile (the sweep filter), and commander hands a
169
184
  // parent-declared option the value even when it is typed AFTER the subcommand — so
170
- // `fleet add <dir> --profile corp` left opts.profile undefined and the flag silently
171
- // did nothing, registering employer repos as personal. Reading the merged view is what
172
- // makes the flag work; the corp-remote guard in add() is what makes forgetting it safe.
185
+ // `fleet add <dir> --profile guarded` left opts.profile undefined and the flag silently
186
+ // did nothing, registering guarded repos as personal. Reading the merged view is what
187
+ // makes the flag work; the guarded-remote guard in add() is what makes forgetting it safe.
173
188
  profile: opts.profile ?? shared.profile,
174
189
  trust: opts.trust,
175
190
  yes: opts.yes
@@ -177,10 +192,10 @@ fleet.command("add").argument("<dir>", "directory of the project to register").d
177
192
  })
178
193
  );
179
194
  fleet.command("dismiss").argument("<name>", "the registered project name").argument("<finding-id>", "the finding id (from `etymd fleet`) to dismiss").description(
180
- "Dismiss a project's finding from any cwd \u2014 corp ledgers persist beside the manifest"
195
+ "Dismiss a project's finding from any cwd \u2014 guarded ledgers persist beside the manifest"
181
196
  ).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(
182
197
  (name, id, _opts, cmd) => action(async () => {
183
- const { dismiss } = await import('./fleet-4FYZ3GBK.js');
198
+ const { dismiss } = await import('./fleet-WPYEVHVL.js');
184
199
  const opts = cmd.optsWithGlobals();
185
200
  await dismiss({
186
201
  cwd: resolveCwd(cmd),
@@ -192,14 +207,34 @@ fleet.command("dismiss").argument("<name>", "the registered project name").argum
192
207
  })
193
208
  );
194
209
  fleet.command("accept").argument("<name>", "the registered project name").argument("<finding-id>", "the finding id (from `etymd fleet`) to accept").description(
195
- "Accept a project's finding as a known trade-off \u2014 corp ledgers persist beside the manifest"
210
+ "Accept a project's finding as a known trade-off \u2014 guarded ledgers persist beside the manifest"
196
211
  ).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(
197
212
  (name, id, _opts, cmd) => action(async () => {
198
- const { accept } = await import('./fleet-4FYZ3GBK.js');
213
+ const { accept } = await import('./fleet-WPYEVHVL.js');
199
214
  const opts = cmd.optsWithGlobals();
200
215
  await accept({ cwd: resolveCwd(cmd), manifest: opts.manifest, name, id, reason: opts.reason });
201
216
  })
202
217
  );
218
+ program.command("propose").description(
219
+ "Score improvement findings + recurring classes against a fleet rubric \u2014 proposal records, read-only (schema proposal/1, EXPERIMENTAL)"
220
+ ).requiredOption(
221
+ "--rubric <file>",
222
+ "the rubric file \u2014 one `criterion: <weight>` line per criterion; etymd ships none"
223
+ ).option(
224
+ "--manifest <file>",
225
+ "the fleet manifest \u2014 runs a read-only sweep now (no delta baseline move)"
226
+ ).option("--from <file>", "read a stored `etymd fleet --json` output instead of sweeping").option("--json", "print the proposal/1 records as JSON (EXPERIMENTAL)").action(
227
+ (opts, cmd) => action(async () => {
228
+ const { run } = await import('./propose-IYNOIWAO.js');
229
+ await run({
230
+ cwd: resolveCwd(cmd),
231
+ manifest: opts.manifest,
232
+ from: opts.from,
233
+ rubric: opts.rubric,
234
+ json: opts.json
235
+ });
236
+ })
237
+ );
203
238
  program.command("screen").description(
204
239
  "Content screen: check for text that must never be published. Bring your own patterns \u2014 etymd ships none."
205
240
  ).option("--staged", "screen what a commit is about to add (default)").option("--tree", "screen every tracked file \u2014 what is about to leave the machine").option("--message <file>", "screen a commit message (the commit-msg hook's $1)").option("--dir <dir>", "screen an unpacked build artifact \u2014 what actually ships").option("--patterns <file>", "pattern file (default: ~/.config/etymd/screen-patterns)").option("--advisory", "report without failing").option(
@@ -207,7 +242,7 @@ program.command("screen").description(
207
242
  "fork's upstream remote: files byte-identical to its refs skip vocabulary-class patterns (secret patterns stay absolute)"
208
243
  ).action(
209
244
  (opts, cmd) => action(async () => {
210
- const { run } = await import('./screen-E4FC7W5N.js');
245
+ const { run } = await import('./screen-S736DXQ5.js');
211
246
  const scope = opts.message ? "message" : opts.dir ? "dir" : opts.tree ? "tree" : "staged";
212
247
  await run({
213
248
  cwd: resolveCwd(cmd),
@@ -221,7 +256,7 @@ program.command("screen").description(
221
256
  );
222
257
  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(
223
258
  (opts, cmd) => action(async () => {
224
- const { run } = await import('./gates-IBQ7HCAN.js');
259
+ const { run } = await import('./gates-3HRGYCYY.js');
225
260
  await run({ cwd: resolveCwd(cmd), ci: opts.ci, yes: opts.yes });
226
261
  })
227
262
  );
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { run } from './chunk-CEO3BXQB.js';
3
- import './chunk-2RNQ6OLV.js';
4
- import './chunk-IWG77WV3.js';
2
+ import { run } from './chunk-ANFNXFRI.js';
3
+ import './chunk-WKP7M2B3.js';
4
+ import './chunk-FNA4R5KT.js';
5
5
  import './chunk-3E2IPCRY.js';
6
6
  import './chunk-HI7NWPRA.js';
7
- import './chunk-Y6RZRED3.js';
8
- import './chunk-DBWDMIYO.js';
7
+ import './chunk-446EZNAQ.js';
8
+ import './chunk-BUMOGHQA.js';
9
9
  import './chunk-P6ATKV2R.js';
10
10
  import './chunk-YQZDYDAK.js';
11
11
  import './chunk-4VPBP6K6.js';