@sabaiway/agent-workflow-kit 1.37.0 → 1.37.1

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 CHANGED
@@ -4,6 +4,22 @@ Semantically versioned ([semver](https://semver.org)), newest first. The `versio
4
4
  is the current release. `upgrade` mode reads a project's `docs/ai/.workflow-version` and applies
5
5
  every `migrations/<version>-<slug>.md` newer than it, in semver order.
6
6
 
7
+ ## 1.37.1 — Fix: the fold-completeness probe on Node 18/20 counted pattern-filtered SKIP lines as executed tests
8
+
9
+ A **patch** release (one product fix + its pinned fixtures; no other change). On Node 18/20 —
10
+ versions the kit supports — `node --test --test-name-pattern` EMITS every non-matching test as
11
+ `ok N - <name> # SKIP test name does not match pattern` (newer Node omits them), so the 1.37.0
12
+ probe parser counted those lines as real matches: a `testId` whose pattern matches NOTHING was
13
+ reported **resolvable with a green baseline**, and the fold-completeness gate green-vouched a test
14
+ that never ran — defeating the gate's purpose on exactly those Node versions. Caught by the CI
15
+ matrix (node 18 + 20) on the 1.37.0 release commit; invisible on newer local Node.
16
+
17
+ - `parseProbeOutput` now ignores any TAP result line carrying a **SKIP/TODO directive** — a skipped
18
+ test was not executed, on any Node version; a real test name containing a literal `# skip` would
19
+ only fail CLOSED (unresolvable), never open.
20
+ - New pinned fixtures: the node-18/20 pattern-filter TAP shape (nomatch → unresolvable; a matched
21
+ test among skipped ones still resolves), a lowercase `# skip`, and a `# TODO` directive.
22
+
7
23
  ## 1.37.0 — Fold-safety completion: a fixable-bug requires its test, and a coverage gate attests the fold against the changed code (AD-046)
8
24
 
9
25
  A **feature** release (deployment-lineage head stays `1.3.0` — no migration). AD-045's ledger computed
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: agent-workflow-kit
3
3
  description: Deploy or upgrade a portable AI-agent memory-and-workflow system in any project. Use when the user wants to bootstrap `docs/ai/` + an entry-point `AGENTS.md` (+ `CLAUDE.md` alias) + cap/archive/index enforcement in a new or existing repo, set up the Memory Map and session protocols, install the docs-rotation pre-commit hook, or run `/agent-workflow-kit` / `/agent-workflow-kit upgrade`. Triggers on phrases like "set up the memory system", "deploy the AI workflow here", "bootstrap docs/ai", "upgrade the workflow".
4
4
  disable-model-invocation: true
5
5
  metadata:
6
- version: '1.37.0'
6
+ version: '1.37.1'
7
7
  ---
8
8
 
9
9
  # agent-workflow-kit
package/capability.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "schema": 1,
4
4
  "name": "agent-workflow-kit",
5
5
  "kind": "composition-root",
6
- "version": "1.37.0",
6
+ "version": "1.37.1",
7
7
  "provides": [],
8
8
  "roles": {},
9
9
  "detect": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sabaiway/agent-workflow-kit",
3
- "version": "1.37.0",
3
+ "version": "1.37.1",
4
4
  "description": "Portable, cross-agent memory & workflow for AI coding agents — Claude Code, Codex, Cursor, Devin Desktop. One command deploys an AGENTS.md entry point + docs/ai context with cap/archive/index enforcement into any repo.",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -180,15 +180,20 @@ export const computeUncoveredLines = ({ perProcessRanges, sourceText, changedLin
180
180
 
181
181
  const PROBE_RESULT_RE = /^(?:ok|not ok) \d+ - (.*)$/; // a column-0 TAP result line
182
182
  const PROBE_FAIL_RE = /^# fail (\d+)$/;
183
+ const PROBE_DIRECTIVE_RE = /#\s*(?:skip|todo)\b/i; // a TAP SKIP/TODO directive — the test did NOT run
183
184
 
184
185
  // parseProbeOutput({ stdout, code, fileArg }) → { resolvable, executed, baselineGreen }. A node:test
185
186
  // run with a pattern that matches NOTHING emits only a file-wrapper result whose description is the
186
- // file path itself (`ok N - <file>`); a real match emits the test NAME. So `resolvable` = at least one
187
- // column-0 result whose description is not the file we passed; `baselineGreen` = resolvable AND the run
188
- // was green (exit 0 and `# fail 0`). The wrapper is matched by BASENAME, not literally: node normalizes
189
- // the echoed path ('./x' 'x', or an absolute path), so a literal desc===fileArg compare would count
190
- // the wrapper as a real match and falsely report resolvable/green (codex R1). A basename compare is
191
- // invariant to ./ / abs / rel; a real test name colliding with the file's basename is absurd and would
187
+ // file path itself (`ok N - <file>`) on newer node but node 18/20 ALSO emit every pattern-FILTERED
188
+ // test as `ok N - <name> # SKIP test name does not match pattern`, so a result line carrying a TAP
189
+ // SKIP/TODO directive must never count: the test was not executed, and counting it green-vouches a
190
+ // nonexistent testId on exactly the node versions the kit supports (caught by CI's 18/20 matrix).
191
+ // So `resolvable` = at least one column-0, directive-free result whose description is not the file we
192
+ // passed; `baselineGreen` = resolvable AND the run was green (exit 0 and `# fail 0`). The wrapper is
193
+ // matched by BASENAME, not literally: node normalizes the echoed path ('./x' → 'x', or an absolute
194
+ // path), so a literal desc===fileArg compare would count the wrapper as a real match and falsely
195
+ // report resolvable/green (codex R1). A basename compare is invariant to ./ / abs / rel; a real test
196
+ // name colliding with the file's basename — or containing a literal "# skip" — is absurd and would
192
197
  // only fail CLOSED (mark unresolvable), never open.
193
198
  export const parseProbeOutput = ({ stdout, code, fileArg }) => {
194
199
  let matched = 0;
@@ -196,7 +201,7 @@ export const parseProbeOutput = ({ stdout, code, fileArg }) => {
196
201
  const wanted = basename(String(fileArg).trim());
197
202
  for (const line of String(stdout).split('\n')) {
198
203
  const m = PROBE_RESULT_RE.exec(line);
199
- if (m && basename(m[1].trim()) !== wanted) matched += 1;
204
+ if (m && !PROBE_DIRECTIVE_RE.test(m[1]) && basename(m[1].trim()) !== wanted) matched += 1;
200
205
  const f = PROBE_FAIL_RE.exec(line.trim());
201
206
  if (f) failCount = Number(f[1]);
202
207
  }