etymd 0.4.2 → 0.6.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/README.md +47 -23
  3. package/dist/{approve-FISVPFL2.js → approve-ZLOW4A7R.js} +6 -6
  4. package/dist/audit-ICT2JK7A.js +12 -0
  5. package/dist/{brief-UF6KV7SG.js → brief-PDUGGMLI.js} +6 -6
  6. package/dist/{chunk-TADKOW6P.js → chunk-5BVKFJWM.js} +7 -3
  7. package/dist/{chunk-IGHES6AK.js → chunk-6DUDIVIC.js} +1 -1
  8. package/dist/{chunk-4AEYMVZK.js → chunk-BQGCLPHS.js} +2 -2
  9. package/dist/{chunk-R74SJ7HS.js → chunk-C7LBUFNU.js} +1 -1
  10. package/dist/{chunk-WWV5W2MM.js → chunk-HLWCODYX.js} +1 -1
  11. package/dist/{chunk-YLNQQZ5F.js → chunk-IV3FYVTS.js} +11 -1
  12. package/dist/{chunk-NMZ3RHWW.js → chunk-K7QBTANO.js} +2 -2
  13. package/dist/{chunk-OX3LUOZR.js → chunk-KTIEYKFK.js} +46 -22
  14. package/dist/{chunk-WWBF4Y7K.js → chunk-OAFYLBVG.js} +1 -1
  15. package/dist/{chunk-6G3JJMZ3.js → chunk-OESQNO2J.js} +77 -9
  16. package/dist/{chunk-LT67FU2Y.js → chunk-OKU3HXIH.js} +2 -2
  17. package/dist/{chunk-HX5IYDCU.js → chunk-ULEWJ3ZK.js} +3 -3
  18. package/dist/{chunk-MMPV67FW.js → chunk-V2SOHPXF.js} +2 -2
  19. package/dist/cli.js +18 -18
  20. package/dist/config-UJRSCDMD.js +4 -0
  21. package/dist/{context-4DGXO7JR.js → context-ZEUI5ESZ.js} +5 -5
  22. package/dist/doctor-PORXFSYT.js +19 -0
  23. package/dist/{fleet-UTFZKYNH.js → fleet-JHNQOLSY.js} +71 -22
  24. package/dist/{gates-YUUV7YI4.js → gates-KHC7HPIF.js} +21 -13
  25. package/dist/generate-UTKQ4GE6.js +6 -0
  26. package/dist/index.d.ts +21 -2
  27. package/dist/index.js +138 -31
  28. package/dist/{init-Q5Q7IGZS.js → init-IPUPP4GB.js} +8 -8
  29. package/dist/ledger-B2XGANTH.js +5 -0
  30. package/dist/{scan-UVNX52J5.js → scan-6L4L2GXT.js} +6 -6
  31. package/dist/scan-D4M7JXE3.js +5 -0
  32. package/dist/{screen-U7JMWZPS.js → screen-6R6NXDSY.js} +2 -2
  33. package/package.json +3 -4
  34. package/dist/audit-GUG2QFZM.js +0 -12
  35. package/dist/config-MX7OYI7F.js +0 -4
  36. package/dist/doctor-SOLNC37X.js +0 -19
  37. package/dist/generate-CBMTNN7P.js +0 -6
  38. package/dist/ledger-TMIV45AA.js +0 -5
  39. package/dist/scan-NWZ65YWB.js +0 -5
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ import { execFile } from 'node:child_process';
2
2
  import { promises } from 'node:fs';
3
3
  import { promisify } from 'node:util';
4
4
  import path from 'node:path';
5
+ import { createHash } from 'node:crypto';
5
6
  import YAML from 'yaml';
6
7
  import os from 'node:os';
7
8
 
@@ -19,7 +20,7 @@ var __export = (target, all) => {
19
20
  var PACK_VERSION;
20
21
  var init_version = __esm({
21
22
  "src/pack/version.ts"() {
22
- PACK_VERSION = "5";
23
+ PACK_VERSION = "6";
23
24
  }
24
25
  });
25
26
 
@@ -29,7 +30,7 @@ var init_package = __esm({
29
30
  "package.json"() {
30
31
  package_default = {
31
32
  name: "etymd",
32
- version: "0.4.2",
33
+ version: "0.6.0",
33
34
  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
35
  keywords: [
35
36
  "cli",
@@ -89,14 +90,13 @@ var init_package = __esm({
89
90
  prepare: "npm run build",
90
91
  prepublishOnly: "npm run build && ./scripts/artifact-check.sh",
91
92
  changeset: "changeset",
92
- "version:packages": "changeset version",
93
- release: "npm run build && changeset publish"
93
+ "version:packages": "changeset version"
94
94
  },
95
95
  dependencies: {
96
96
  "@clack/prompts": "0.7.0",
97
97
  commander: "12.1.0",
98
98
  picocolors: "1.1.1",
99
- yaml: "2.7.0"
99
+ yaml: "2.9.0"
100
100
  },
101
101
  devDependencies: {
102
102
  "@changesets/cli": "2.27.11",
@@ -152,6 +152,16 @@ async function isDirectory(p) {
152
152
  return false;
153
153
  }
154
154
  }
155
+ async function isExecutable(p) {
156
+ try {
157
+ const stat = await promises.stat(p);
158
+ if (!stat.isFile()) return false;
159
+ if (process.platform === "win32") return null;
160
+ return (stat.mode & 73) !== 0;
161
+ } catch {
162
+ return false;
163
+ }
164
+ }
155
165
  async function git(root, args) {
156
166
  try {
157
167
  const { stdout } = await pExecFile("git", args, { cwd: root, timeout: 4e3 });
@@ -990,8 +1000,24 @@ var init_config = __esm({
990
1000
  };
991
1001
  }
992
1002
  });
993
-
994
- // src/pack/templates.ts
1003
+ function digestOf(body) {
1004
+ return createHash("sha256").update(body).digest("hex").slice(0, 16);
1005
+ }
1006
+ function stampGenerated(body, comment = "sh") {
1007
+ const marker = `etymd:generated pack-v${PACK_VERSION} ${digestOf(body)}`;
1008
+ return `${body}${comment === "md" ? `<!-- ${marker} -->` : `# ${marker}`}
1009
+ `;
1010
+ }
1011
+ function fileOrigin(text) {
1012
+ const lines = text.split("\n");
1013
+ for (let i = lines.length - 1; i >= 0; i--) {
1014
+ const match = GENERATION_MARKER_RE.exec(lines[i]);
1015
+ if (!match) continue;
1016
+ const body = [...lines.slice(0, i), ...lines.slice(i + 1)].join("\n");
1017
+ return digestOf(body) === match[1] ? "pack" : "edited";
1018
+ }
1019
+ return "unstamped";
1020
+ }
995
1021
  function runPrefix(pm) {
996
1022
  switch (pm) {
997
1023
  case "pnpm":
@@ -1044,7 +1070,8 @@ function generateAgentsMd(facts) {
1044
1070
  const frameworks = facts.frameworks.length ? facts.frameworks.join(", ") : "none detected";
1045
1071
  const workspace = facts.workspace.kind === "none" ? "single package" : `${facts.workspace.kind} workspace`;
1046
1072
  const topDirs = facts.tree.dirs.slice(0, 14);
1047
- return `# AGENTS.md
1073
+ return stampGenerated(
1074
+ `# AGENTS.md
1048
1075
 
1049
1076
  Operating contract for AI agents working in **${facts.name}**. One source of truth \u2014 most agents
1050
1077
  (Claude Code, Codex, Cursor, Copilot, Gemini, \u2026) read this file natively. Kept true by
@@ -1087,16 +1114,17 @@ ${done.map((d) => `- ${d}`).join("\n")}` : `Define the check commands that gate
1087
1114
 
1088
1115
  \`\`\`bash
1089
1116
  ${[
1090
- facts.commands.dev && `${run} ${facts.commands.dev}`,
1091
- facts.commands.build && `${run} ${facts.commands.build}`,
1092
- facts.commands.test && `${run} ${facts.commands.test}`,
1093
- facts.commands.lint && `${run} ${facts.commands.lint}`,
1094
- facts.commands.typecheck && `${run} ${facts.commands.typecheck}`
1095
- ].filter(Boolean).join("\n") || "# add the project's key commands"}
1117
+ facts.commands.dev && `${run} ${facts.commands.dev}`,
1118
+ facts.commands.build && `${run} ${facts.commands.build}`,
1119
+ facts.commands.test && `${run} ${facts.commands.test}`,
1120
+ facts.commands.lint && `${run} ${facts.commands.lint}`,
1121
+ facts.commands.typecheck && `${run} ${facts.commands.typecheck}`
1122
+ ].filter(Boolean).join("\n") || "# add the project's key commands"}
1096
1123
  \`\`\`
1097
1124
 
1098
- <!-- etymd pack v${PACK_VERSION} -->
1099
- `;
1125
+ `,
1126
+ "md"
1127
+ );
1100
1128
  }
1101
1129
  function localHookCall(hook) {
1102
1130
  return `# Repo-owned checks. This file is generated and will be overwritten; \`.githooks/${hook}.local\`
@@ -1107,7 +1135,7 @@ if [ -x "$LOCAL" ]; then
1107
1135
  fi`;
1108
1136
  }
1109
1137
  function generatePreCommitHook() {
1110
- return `#!/usr/bin/env sh
1138
+ return stampGenerated(`#!/usr/bin/env sh
1111
1139
  # etymd: process gate. Cheap, locally-knowable checks belong here (fast, blocks the commit).
1112
1140
 
1113
1141
  ${localHookCall("pre-commit")}
@@ -1124,10 +1152,10 @@ if [ -x "$GATE" ]; then
1124
1152
  fi
1125
1153
 
1126
1154
  exit 0
1127
- `;
1155
+ `);
1128
1156
  }
1129
1157
  function generateCommitMsgHook() {
1130
- return `#!/usr/bin/env sh
1158
+ return stampGenerated(`#!/usr/bin/env sh
1131
1159
  # etymd: content screen \u2014 the commit message itself.
1132
1160
  #
1133
1161
  # The staged-content gate reads file bytes and never sees the message, yet a message is as
@@ -1142,7 +1170,7 @@ fi
1142
1170
  ${localHookCall("commit-msg")}
1143
1171
 
1144
1172
  exit 0
1145
- `;
1173
+ `);
1146
1174
  }
1147
1175
  function shellcheckStep() {
1148
1176
  return `
@@ -1195,7 +1223,7 @@ if command -v etymd >/dev/null 2>&1; then
1195
1223
  else
1196
1224
  echo "\u203A etymd audit skipped (not on PATH)"
1197
1225
  fi`;
1198
- return `#!/usr/bin/env sh
1226
+ return stampGenerated(`#!/usr/bin/env sh
1199
1227
  # etymd: correctness gate. Mirrors CI cheapest-first; blocks the push on any failure.
1200
1228
 
1201
1229
  ${localHookCall("pre-push")}
@@ -1211,10 +1239,10 @@ if [ -x "$GATE" ] && [ "\${CONTENT_GATE_PREPUSH:-1}" = "1" ]; then
1211
1239
  fi
1212
1240
 
1213
1241
  exit 0
1214
- `;
1242
+ `);
1215
1243
  }
1216
1244
  function generateArtifactCheckScript() {
1217
- return `#!/usr/bin/env sh
1245
+ return stampGenerated(`#!/usr/bin/env sh
1218
1246
  # etymd: content screen \u2014 the published ARTIFACT, not the repository.
1219
1247
  #
1220
1248
  # Wire it into the irreversible moment:
@@ -1243,12 +1271,13 @@ fi
1243
1271
 
1244
1272
  "$GATE" screen --dir "$WORK" || exit 1
1245
1273
  exit 0
1246
- `;
1274
+ `);
1247
1275
  }
1248
- var CONTENT_GATE_RESOLUTION;
1276
+ var GENERATION_MARKER_RE, CONTENT_GATE_RESOLUTION;
1249
1277
  var init_templates = __esm({
1250
1278
  "src/pack/templates.ts"() {
1251
1279
  init_version();
1280
+ GENERATION_MARKER_RE = /^(?:# |<!-- )etymd:generated pack-v\S+ ([0-9a-f]{16})(?: -->)?$/;
1252
1281
  CONTENT_GATE_RESOLUTION = `GATE="\${CONTENT_GATE:-$(command -v etymd || true)}"`;
1253
1282
  }
1254
1283
  });
@@ -1275,11 +1304,14 @@ async function planWorkflow(root, facts, opts) {
1275
1304
  const abs = path.join(root, rel);
1276
1305
  const exists = await pathExists(abs);
1277
1306
  const existing = exists ? await readText(abs) : null;
1307
+ const differs = exists ? existing !== contents : void 0;
1308
+ const origin = differs && existing !== null ? fileOrigin(existing) : void 0;
1278
1309
  out.push({
1279
1310
  path: rel,
1280
1311
  contents,
1281
1312
  exists,
1282
- differs: exists ? existing !== contents : void 0,
1313
+ differs,
1314
+ drift: origin === "pack" ? "stale" : origin,
1283
1315
  executable,
1284
1316
  label
1285
1317
  });
@@ -1696,13 +1728,43 @@ function parseGithubWorkflow(text, file, scripts) {
1696
1728
  }
1697
1729
  return { jobs, parseErrors };
1698
1730
  }
1731
+ async function companionOf(root, hooksDir, hook, hookText, scripts) {
1732
+ const rel = path.posix.join(hooksDir.split(path.sep).join("/"), `${hook}.local`);
1733
+ if (!hookText.includes(`${hook}.local`)) return null;
1734
+ const abs = path.join(root, hooksDir, `${hook}.local`);
1735
+ const text = await readText(abs);
1736
+ if (text === null) return null;
1737
+ const [executable, hookExecutable] = await Promise.all([
1738
+ isExecutable(abs),
1739
+ isExecutable(path.join(root, hooksDir, hook))
1740
+ ]);
1741
+ if (executable === false && hookExecutable === true) return { rel, tools: [], state: "inert" };
1742
+ return {
1743
+ rel,
1744
+ tools: matchTools(text, scripts),
1745
+ state: executable === true ? "counted" : "unverified"
1746
+ };
1747
+ }
1699
1748
  async function localHookTools(root, facts, scripts) {
1700
1749
  const hooks = facts.hooks;
1701
1750
  const empty = [];
1751
+ const companions = [];
1752
+ const unverifiedCompanions = [];
1753
+ const inertCompanions = [];
1702
1754
  const readHook = async (name) => {
1703
1755
  if (!hooks.dir) return empty;
1704
1756
  const text = await readText(path.join(root, hooks.dir, name));
1705
- return text ? matchTools(text, scripts) : empty;
1757
+ if (!text) return empty;
1758
+ const tools = new Set(matchTools(text, scripts));
1759
+ const companion = await companionOf(root, hooks.dir, name, text, scripts);
1760
+ if (companion) {
1761
+ if (companion.state === "inert") inertCompanions.push(companion.rel);
1762
+ else {
1763
+ (companion.state === "counted" ? companions : unverifiedCompanions).push(companion.rel);
1764
+ for (const t of companion.tools) tools.add(t);
1765
+ }
1766
+ }
1767
+ return [...tools];
1706
1768
  };
1707
1769
  let preCommit = [];
1708
1770
  let prePush = [];
@@ -1746,7 +1808,17 @@ async function localHookTools(root, facts, scripts) {
1746
1808
  }
1747
1809
  }
1748
1810
  const wired = hooks.source === "custom" || hooks.source === "husky" || hooks.source === "husky-legacy" ? true : hooks.source === "githooks" ? facts.git.hooksPath === hooks.dir : false;
1749
- return { source: hooks.source, wired, preCommit, prePush, commitMsg, lintStaged };
1811
+ return {
1812
+ source: hooks.source,
1813
+ wired,
1814
+ preCommit,
1815
+ prePush,
1816
+ commitMsg,
1817
+ lintStaged,
1818
+ companions,
1819
+ unverifiedCompanions,
1820
+ inertCompanions
1821
+ };
1750
1822
  }
1751
1823
  async function detectThresholds(root, scripts, ciJobs) {
1752
1824
  const sonarConfigured = await pathExists(path.join(root, "sonar-project.properties")) || ciJobs.some((j) => j.tools.includes("sonar"));
@@ -1879,6 +1951,24 @@ function deriveGateFindings(inv, disclosures = []) {
1879
1951
  );
1880
1952
  }
1881
1953
  }
1954
+ if (inv.local.inertCompanions?.length) {
1955
+ const files = inv.local.inertCompanions;
1956
+ findings.push(
1957
+ finding({
1958
+ id: `${LENS_ID2}/companion-not-executable`,
1959
+ tier: "gap",
1960
+ kind: "truth",
1961
+ claim: `${files.join(", ")} ${files.length === 1 ? "is" : "are"} called by a hook but not executable \u2014 the checks inside never run`,
1962
+ evidence: files,
1963
+ why: "The hook guards the call with `[ -x ]`, so it skips the file in silence \u2014 the repo looks guarded and is not, on every clone that carries the same mode bit.",
1964
+ // chmod alone does not survive a fresh clone: git tracks exactly one permission bit, so
1965
+ // the fix has to reach the index or the dead gate propagates to everyone else.
1966
+ action: `Run \`chmod +x ${files[0]}\` and commit the mode with \`git update-index --chmod=+x ${files[0]}\`.`,
1967
+ effort: "S",
1968
+ confidence: "high"
1969
+ })
1970
+ );
1971
+ }
1882
1972
  for (const tool of CORRECTNESS_TOOLS) {
1883
1973
  if (!enforcedCiTools.has(tool) || localTools.has(tool)) continue;
1884
1974
  const jobs = enforcedCiJobs.filter((j) => j.tools.includes(tool));
@@ -1979,6 +2069,16 @@ var gateIntegrityLens = {
1979
2069
  }
1980
2070
  if (inv.ci.parseErrors.length)
1981
2071
  disclosures.push(...inv.ci.parseErrors.map((e) => `CI parse: ${e}`));
2072
+ if (inv.local.companions.length) {
2073
+ disclosures.push(
2074
+ `Checks in ${inv.local.companions.join(", ")} are counted as locally enforced \u2014 the generated hook calls the companion, and etymd reads it without owning it.`
2075
+ );
2076
+ }
2077
+ if (inv.local.unverifiedCompanions.length) {
2078
+ disclosures.push(
2079
+ `Checks in ${inv.local.unverifiedCompanions.join(", ")} are counted as locally enforced, but the execute bit could not be judged here (no POSIX mode bits, or the hook beside it is not executable either) \u2014 whether ${inv.local.unverifiedCompanions.length === 1 ? "it runs" : "they run"} was not verified.`
2080
+ );
2081
+ }
1982
2082
  if (inv.ci.system === "none")
1983
2083
  disclosures.push("No CI configuration found \u2014 CI\u2194local comparisons skipped.");
1984
2084
  const findings = deriveGateFindings(inv, disclosures);
@@ -3571,7 +3671,14 @@ async function checkGateDrift(manifest, findings, disclosures) {
3571
3671
  const { config } = await readConfig2(root);
3572
3672
  const planned = (await planWorkflow2(root, facts, { agents: false, gates: true, gateConfig: config.gates })).filter((f) => f.executable);
3573
3673
  const missing = planned.filter((f) => !f.exists).map((f) => f.path);
3574
- const stale = planned.filter((f) => f.exists && f.differs).map((f) => f.path);
3674
+ const differing = planned.filter((f) => f.exists && f.differs);
3675
+ const stale = differing.filter((f) => f.drift !== "edited").map((f) => f.path);
3676
+ const edited = differing.filter((f) => f.drift === "edited").map((f) => f.path);
3677
+ if (edited.length) {
3678
+ disclosures.push(
3679
+ `${entry.name}: ${edited.join(", ")} edited since etymd generated ${edited.length === 1 ? "it" : "them"} \u2014 a customisation, not drift; etymd will not overwrite ${edited.length === 1 ? "it" : "them"}`
3680
+ );
3681
+ }
3575
3682
  if (missing.length) {
3576
3683
  findings.push(
3577
3684
  finding3(
@@ -3591,8 +3698,8 @@ async function checkGateDrift(manifest, findings, disclosures) {
3591
3698
  "polish",
3592
3699
  `\`${entry.name}\` has ${stale.length} gate${stale.length === 1 ? "" : "s"} that differ from what its own inputs generate`,
3593
3700
  stale.map((s) => `${entry.name}: ${s}`),
3594
- "A hand-edited or outdated hook drifts from the pack silently \u2014 the repo believes it runs checks the file no longer contains.",
3595
- "Re-run `etymd gates` (it asks before overwriting), or record the intent in .etymd/config.json."
3701
+ "An outdated hook drifts from the pack silently \u2014 the repo believes it runs checks the file no longer contains.",
3702
+ "Re-run `etymd gates` in that repo \u2014 it regenerates a gate it provably wrote and asks before touching anything else."
3596
3703
  )
3597
3704
  );
3598
3705
  }
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { applyFiles } from './chunk-EF6BPBG6.js';
3
- import { planWorkflow } from './chunk-OX3LUOZR.js';
4
- import './chunk-NMZ3RHWW.js';
5
- import { theme, renderFacts, print, renderPlan, section, glyph } from './chunk-TADKOW6P.js';
6
- import { scanProject } from './chunk-HX5IYDCU.js';
7
- import { VERSION } from './chunk-WWV5W2MM.js';
8
- import { writeCachedFacts, deriveProfile, writeBaseline, CACHE_DIR } from './chunk-R74SJ7HS.js';
9
- import { PACK_VERSION } from './chunk-IGHES6AK.js';
10
- import { git, readText } from './chunk-YLNQQZ5F.js';
3
+ import { planWorkflow } from './chunk-KTIEYKFK.js';
4
+ import './chunk-K7QBTANO.js';
5
+ import { theme, renderFacts, print, renderPlan, section, glyph } from './chunk-5BVKFJWM.js';
6
+ import { scanProject } from './chunk-ULEWJ3ZK.js';
7
+ import { VERSION } from './chunk-HLWCODYX.js';
8
+ import { writeCachedFacts, deriveProfile, writeBaseline, CACHE_DIR } from './chunk-C7LBUFNU.js';
9
+ import { PACK_VERSION } from './chunk-6DUDIVIC.js';
10
+ import { git, readText } from './chunk-IV3FYVTS.js';
11
11
  import { promises } from 'node:fs';
12
12
  import path from 'node:path';
13
13
  import { intro, spinner, select, confirm, outro, isCancel, cancel } from '@clack/prompts';
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ export { accept, dismiss, list } from './chunk-V2SOHPXF.js';
3
+ import './chunk-OAFYLBVG.js';
4
+ import './chunk-5BVKFJWM.js';
5
+ import './chunk-IV3FYVTS.js';
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { print, renderFacts, theme } from './chunk-TADKOW6P.js';
3
- import { scanProject } from './chunk-HX5IYDCU.js';
4
- import './chunk-WWV5W2MM.js';
5
- import { writeCachedFacts } from './chunk-R74SJ7HS.js';
6
- import './chunk-IGHES6AK.js';
7
- import './chunk-YLNQQZ5F.js';
2
+ import { print, renderFacts, theme } from './chunk-5BVKFJWM.js';
3
+ import { scanProject } from './chunk-ULEWJ3ZK.js';
4
+ import './chunk-HLWCODYX.js';
5
+ import { writeCachedFacts } from './chunk-C7LBUFNU.js';
6
+ import './chunk-6DUDIVIC.js';
7
+ import './chunk-IV3FYVTS.js';
8
8
 
9
9
  // src/commands/scan.ts
10
10
  async function run(opts) {
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ export { scanProject } from './chunk-ULEWJ3ZK.js';
3
+ import './chunk-HLWCODYX.js';
4
+ import './chunk-6DUDIVIC.js';
5
+ import './chunk-IV3FYVTS.js';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { print, glyph, theme, section } from './chunk-TADKOW6P.js';
3
- import { readText, git, pathExists } from './chunk-YLNQQZ5F.js';
2
+ import { print, glyph, theme, section } from './chunk-5BVKFJWM.js';
3
+ import { readText, git, pathExists } from './chunk-IV3FYVTS.js';
4
4
  import { promises } from 'node:fs';
5
5
  import path from 'node:path';
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "etymd",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
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",
@@ -60,14 +60,13 @@
60
60
  "prepare": "npm run build",
61
61
  "prepublishOnly": "npm run build && ./scripts/artifact-check.sh",
62
62
  "changeset": "changeset",
63
- "version:packages": "changeset version",
64
- "release": "npm run build && changeset publish"
63
+ "version:packages": "changeset version"
65
64
  },
66
65
  "dependencies": {
67
66
  "@clack/prompts": "0.7.0",
68
67
  "commander": "12.1.0",
69
68
  "picocolors": "1.1.1",
70
- "yaml": "2.7.0"
69
+ "yaml": "2.9.0"
71
70
  },
72
71
  "devDependencies": {
73
72
  "@changesets/cli": "2.27.11",
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env node
2
- export { run } from './chunk-4AEYMVZK.js';
3
- import './chunk-6G3JJMZ3.js';
4
- import './chunk-LT67FU2Y.js';
5
- import './chunk-WWBF4Y7K.js';
6
- import './chunk-NMZ3RHWW.js';
7
- import './chunk-TADKOW6P.js';
8
- import './chunk-HX5IYDCU.js';
9
- import './chunk-WWV5W2MM.js';
10
- import './chunk-R74SJ7HS.js';
11
- import './chunk-IGHES6AK.js';
12
- import './chunk-YLNQQZ5F.js';
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- export { CONFIG_FILE, DEFAULT_CONFIG, configPath, readConfig } from './chunk-NMZ3RHWW.js';
3
- import './chunk-R74SJ7HS.js';
4
- import './chunk-YLNQQZ5F.js';
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env node
2
- import { run } from './chunk-4AEYMVZK.js';
3
- import './chunk-6G3JJMZ3.js';
4
- import './chunk-LT67FU2Y.js';
5
- import './chunk-WWBF4Y7K.js';
6
- import './chunk-NMZ3RHWW.js';
7
- import './chunk-TADKOW6P.js';
8
- import './chunk-HX5IYDCU.js';
9
- import './chunk-WWV5W2MM.js';
10
- import './chunk-R74SJ7HS.js';
11
- import './chunk-IGHES6AK.js';
12
- import './chunk-YLNQQZ5F.js';
13
-
14
- // src/commands/doctor.ts
15
- async function run2(opts) {
16
- await run({ cwd: opts.cwd, json: opts.json, truth: true });
17
- }
18
-
19
- export { run2 as run };
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env node
2
- export { derivedCommands, planWorkflow } from './chunk-OX3LUOZR.js';
3
- import './chunk-NMZ3RHWW.js';
4
- import './chunk-R74SJ7HS.js';
5
- import './chunk-IGHES6AK.js';
6
- import './chunk-YLNQQZ5F.js';
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- export { accept, dismiss, list } from './chunk-MMPV67FW.js';
3
- import './chunk-WWBF4Y7K.js';
4
- import './chunk-TADKOW6P.js';
5
- import './chunk-YLNQQZ5F.js';
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- export { scanProject } from './chunk-HX5IYDCU.js';
3
- import './chunk-WWV5W2MM.js';
4
- import './chunk-IGHES6AK.js';
5
- import './chunk-YLNQQZ5F.js';