@esneiderbravo/speclaw 2.0.23 → 2.0.24

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.
@@ -115,6 +115,18 @@ function runGate(projectPath, command) {
115
115
  tail: combined.slice(-GATE_TAIL_LINES).join("\n"),
116
116
  };
117
117
  }
118
+ /**
119
+ * What the lawbook writes itself: change folders and reports, the canonical
120
+ * specs an archive promotes, the anchors it seals, and the local index. None
121
+ * of it is the agent's work, so none of it may trigger, size or re-run a ship
122
+ * — archiving used to read as new work and re-run every gate.
123
+ */
124
+ const OWN_OUTPUT = ["lawbook/changes/", "lawbook/specs/", "lawbook/anchors/", ".speclaw/"];
125
+ function isOwnOutput(file) {
126
+ return OWN_OUTPUT.some((dir) => file.startsWith(dir));
127
+ }
128
+ /** The same paths as git pathspecs, for commands that list or log the work. */
129
+ const OWN_OUTPUT_EXCLUDES = OWN_OUTPUT.map((dir) => `:(exclude)${dir.replace(/\/$/, "")}`);
118
130
  function branchFiles(projectPath) {
119
131
  if (!isGitRepo(projectPath))
120
132
  return [];
@@ -127,7 +139,7 @@ function branchFiles(projectPath) {
127
139
  ...untrackedFiles(projectPath),
128
140
  ]),
129
141
  ]
130
- .filter((f) => !f.startsWith("lawbook/changes/"))
142
+ .filter((f) => !isOwnOutput(f))
131
143
  .filter((f) => f !== COMPASS_DOC || !onlyMapChanged(projectPath, base))
132
144
  .sort();
133
145
  }
@@ -150,7 +162,7 @@ function onlyMapChanged(projectPath, base) {
150
162
  return false;
151
163
  }
152
164
  }
153
- /** New files not yet added, outside ship's own output (`lawbook/changes/`, `.speclaw/`). */
165
+ /** New files not yet added, outside the lawbook's own output ({@link OWN_OUTPUT}). */
154
166
  function untrackedFiles(projectPath) {
155
167
  return git(projectPath, [
156
168
  "-c",
@@ -160,7 +172,7 @@ function untrackedFiles(projectPath) {
160
172
  "--exclude-standard",
161
173
  ])
162
174
  .split("\n")
163
- .filter((f) => f && !f.startsWith("lawbook/changes/") && !f.startsWith(".speclaw/"));
175
+ .filter((f) => f && !isOwnOutput(f));
164
176
  }
165
177
  function secs(ms) {
166
178
  return `${(ms / 1000).toFixed(1)} s`;
@@ -243,8 +255,7 @@ function commitSummary(projectPath) {
243
255
  `${base}..HEAD`,
244
256
  "--",
245
257
  ".",
246
- ":(exclude)lawbook/changes",
247
- ":(exclude).speclaw",
258
+ ...OWN_OUTPUT_EXCLUDES,
248
259
  ])
249
260
  .split("\n")
250
261
  .filter((l) => !/^[\w-]+-by:/i.test(l))
@@ -712,7 +723,7 @@ export function docHint(projectPath) {
712
723
  return null;
713
724
  const quick = status
714
725
  .split("\n")
715
- .filter((l) => !l.includes(" lawbook/changes/") && !l.includes(" .speclaw/"))
726
+ .filter((l) => !OWN_OUTPUT.some((dir) => l.includes(` ${dir}`)))
716
727
  .join("\n");
717
728
  const statePath = path.join(projectPath, DOC_HINT_STATE);
718
729
  let prev = {};
@@ -865,11 +876,11 @@ function readMarker(projectPath) {
865
876
  return { branch: "", change: "", fingerprint: raw };
866
877
  }
867
878
  /**
868
- * Fingerprint of the branch's work outside `lawbook/changes/` and `.speclaw/`: every path that
879
+ * Fingerprint of the branch's work outside the lawbook's own output: every path that
869
880
  * differs from the merge base with `main`/`master` or is untracked, with its
870
881
  * working-tree contents. A file hashes the same whether it is untracked, staged
871
882
  * or committed, so committing work — new files included — is not new work; ship
872
- * writes under `lawbook/changes/`, so its own output never changes it either.
883
+ * and archive write only {@link OWN_OUTPUT}, so their output never changes it either.
873
884
  * Without a merge base it falls back to the paths changed against HEAD plus HEAD itself.
874
885
  */
875
886
  function workFingerprint(projectPath) {
@@ -882,8 +893,7 @@ function workFingerprint(projectPath) {
882
893
  base ?? "HEAD",
883
894
  "--",
884
895
  ".",
885
- ":(exclude)lawbook/changes",
886
- ":(exclude).speclaw",
896
+ ...OWN_OUTPUT_EXCLUDES,
887
897
  ]).split("\n");
888
898
  const hash = createHash("sha256");
889
899
  const files = [...new Set([...tracked, ...untrackedFiles(projectPath)])]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esneiderbravo/speclaw",
3
- "version": "2.0.23",
3
+ "version": "2.0.24",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -43,8 +43,10 @@
43
43
  "check": "prettier --check . && eslint .",
44
44
  "budget:calibrate": "node scripts/budget-calibrate.mjs",
45
45
  "pretest": "tsc -p tsconfig.test.json && node scripts/prep-test-assets.mjs",
46
- "test": "node --test --test-concurrency=1 --experimental-test-coverage --test-coverage-lines=80 --test-coverage-functions=80 --test-coverage-branches=80 --test-coverage-exclude='dist-test/test/**' --test-coverage-exclude='dist/**' 'dist-test/test/**/*.test.js'",
47
- "prepublishOnly": "npm run build"
46
+ "test": "node --test 'dist-test/test/**/*.test.js'",
47
+ "prepublishOnly": "npm run build",
48
+ "test:ci": "node --test --test-concurrency=1 --experimental-test-coverage --test-coverage-lines=80 --test-coverage-functions=80 --test-coverage-branches=80 --test-coverage-exclude='dist-test/test/**' --test-coverage-exclude='dist/**' 'dist-test/test/**/*.test.js'",
49
+ "pretest:ci": "npm run pretest"
48
50
  },
49
51
  "engines": {
50
52
  "node": ">=22.16"