@gobing-ai/spur 0.3.66 → 0.3.67

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/spur.js CHANGED
@@ -71901,20 +71901,6 @@ function citedLinesNameSubject(subjectTokens, cited) {
71901
71901
  const isRowId = (t) => /^(r|ac)-?\d+$/.test(t);
71902
71902
  return subjectTokens.every(isRowId);
71903
71903
  }
71904
- function extractPathSubjectTokens(path9) {
71905
- const basename4 = path9.split("/").pop() ?? "";
71906
- const stem = basename4.replace(/\.[^.]+$/, "");
71907
- const tokens = new Set;
71908
- for (const part of stem.split(/[-_.]+/)) {
71909
- if (!/^[A-Za-z][A-Za-z0-9]*$/.test(part))
71910
- continue;
71911
- const lower = part.toLowerCase();
71912
- if (lower.length < 3)
71913
- continue;
71914
- tokens.add(lower);
71915
- }
71916
- return [...tokens];
71917
- }
71918
71904
  function hasAdjacentFileLineColumns(body) {
71919
71905
  const lines = body.split(`
71920
71906
  `);
@@ -72234,7 +72220,7 @@ var init_task_check = __esm(() => {
72234
72220
  });
72235
72221
  }
72236
72222
  }
72237
- await this.checkLineAnchors(doc2, tasksDir, findings);
72223
+ await this.checkLineAnchors(doc2, tasksDir, findings, status);
72238
72224
  const featureId2 = fm.feature_id ?? fm["feature-id"];
72239
72225
  const parentWbs = fm.parent_wbs ?? fm["parent-wbs"];
72240
72226
  const deps = fm.dependencies;
@@ -72507,8 +72493,9 @@ var init_task_check = __esm(() => {
72507
72493
  return null;
72508
72494
  }
72509
72495
  }
72510
- async checkLineAnchors(doc2, tasksDir, findings) {
72496
+ async checkLineAnchors(doc2, tasksDir, findings, status) {
72511
72497
  const projectRoot = resolveProjectRootFromTasksDir(tasksDir);
72498
+ const terminal = status === "done" || status === "cancelled";
72512
72499
  for (const section of ["Testing", "Solution"]) {
72513
72500
  const body = doc2.getSection(section);
72514
72501
  if (body === null || isPlaceholderBody(body))
@@ -72568,45 +72555,30 @@ var init_task_check = __esm(() => {
72568
72555
  message: `Stale line anchor \`${cite.raw}\` \u2014 line ${cite.startLine}${cite.endLine ? `-${cite.endLine}` : ""} outside file (${lineCount} lines)`
72569
72556
  });
72570
72557
  reported++;
72571
- } else {
72572
- const citedWindow = raw.split(`
72573
- `).slice(cite.startLine - 1, cite.endLine ?? cite.startLine).join(`
72574
- `) || "";
72575
- const citingRow = body.split(`
72558
+ continue;
72559
+ }
72560
+ if (terminal)
72561
+ continue;
72562
+ const citingRow = body.split(`
72576
72563
  `).find((l) => l.includes(`\`${cite.raw}\``)) ?? body.split(`
72577
72564
  `).find((l) => l.includes(cite.raw)) ?? "";
72578
- const tokens = extractSubjectTokens(citingRow);
72579
- const effectiveTokens = tokens.length === 0 && section === "Solution" ? extractPathSubjectTokens(cite.path) : tokens;
72580
- if (!citedLinesNameSubject(effectiveTokens, citedWindow)) {
72581
- let driftLine = -1;
72582
- const fileLines = raw.split(`
72583
- `);
72584
- for (let i2 = 0;i2 < fileLines.length; i2++) {
72585
- if (citedLinesNameSubject(effectiveTokens, fileLines[i2] ?? "")) {
72586
- driftLine = i2 + 1;
72587
- break;
72588
- }
72589
- }
72590
- if (driftLine > 0) {
72591
- findings.push({
72592
- layer: "L4",
72593
- code: FINDING_CODES.L4_STALE_LINE_ANCHOR,
72594
- severity: "warning",
72595
- section,
72596
- message: `Anchor drift \`${cite.raw}\` \u2014 subject (${effectiveTokens.join(", ")}) cited at ${cite.startLine}${cite.endLine ? `-${cite.endLine}` : ""} now sits at line ${driftLine}; re-point the citation`
72597
- });
72598
- reported++;
72599
- continue;
72600
- }
72601
- findings.push({
72602
- layer: "L4",
72603
- code: FINDING_CODES.L4_ANCHOR_SUBJECT_MISMATCH,
72604
- severity: "warning",
72605
- section,
72606
- message: `Anchor \`${cite.raw}\` subject mismatch \u2014 cited lines do not name the requirement's subject (${effectiveTokens.join(", ") || "none identifiable"}). Rewrite the citation to point at the code that implements this row.`
72607
- });
72608
- reported++;
72609
- }
72565
+ if (extractBacktickLineAnchors(citingRow).length !== 1)
72566
+ continue;
72567
+ const tokens = extractSubjectTokens(citingRow);
72568
+ if (tokens.length === 0)
72569
+ continue;
72570
+ const citedWindow = raw.split(`
72571
+ `).slice(cite.startLine - 1, cite.endLine ?? cite.startLine).join(`
72572
+ `) || "";
72573
+ if (!citedLinesNameSubject(tokens, citedWindow)) {
72574
+ findings.push({
72575
+ layer: "L4",
72576
+ code: FINDING_CODES.L4_ANCHOR_SUBJECT_MISMATCH,
72577
+ severity: "warning",
72578
+ section,
72579
+ message: `Anchor \`${cite.raw}\` subject mismatch \u2014 cited lines do not name the requirement's subject (${tokens.join(", ") || "none identifiable"}). Rewrite the citation to point at the code that implements this row.`
72580
+ });
72581
+ reported++;
72610
72582
  }
72611
72583
  } catch {}
72612
72584
  }
@@ -82504,6 +82476,11 @@ function extractRequirements(text4) {
82504
82476
  let colMap = null;
82505
82477
  for (const line of lines) {
82506
82478
  const trimmed = line.trim();
82479
+ if (inTable && /^#{1,6}\s/.test(trimmed)) {
82480
+ inTable = false;
82481
+ colMap = null;
82482
+ continue;
82483
+ }
82507
82484
  if (!trimmed.startsWith("|"))
82508
82485
  continue;
82509
82486
  const cells = splitTableCells(trimmed);
@@ -96886,7 +96863,7 @@ import { createRequire } from "module";
96886
96863
  var CLI_CONFIG = {
96887
96864
  binaryName: "spur",
96888
96865
  binaryLabel: "spur",
96889
- binaryVersion: "0.3.66",
96866
+ binaryVersion: "0.3.67",
96890
96867
  configDir: ".spur",
96891
96868
  configFile: ".spur/config.yaml",
96892
96869
  databaseFile: ".spur/spur.db"