@gobing-ai/spur 0.3.5 → 0.3.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
5
5
  "keywords": [
6
6
  "spur",
@@ -55,6 +55,13 @@ rules:
55
55
  evaluator:
56
56
  type: rg
57
57
  config:
58
- # Match imports from modules with known module-eval side effects.
59
- # Add new patterns here as alternations (|) when new cases are discovered.
60
- pattern: "from ['\"].*task-kanban/useTasks['\"]"
58
+ # Match imports from modules with KNOWN, ACTIVE module-eval side effects.
59
+ # IMPORTANT: this rule is INERT unless a pattern is present. When a new
60
+ # side-effect module is discovered (CI-only ordering failure traced to
61
+ # an import-time call), add its import pattern here as a string. Remove
62
+ # the pattern once the source module is fixed (side effects made lazy).
63
+ #
64
+ # RESOLVED modules (patterns removed after fix — kept as history):
65
+ # - task-kanban/useTasks — fixed 2026-07-08, commit 3937d31
66
+ # (resolveApiUrl/api.task.list converted to lazy dynamic imports)
67
+ pattern: "__no_active_side_effect_modules__"
@@ -0,0 +1,40 @@
1
+ # AGENTS.md
2
+
3
+ Guidance for AI coding agents working in this repository.
4
+
5
+ ## Project
6
+
7
+ <!-- Replace the line below with your project name and a one-line description. -->
8
+ **{project-name}** — (one-line description).
9
+
10
+ ## Commands
11
+
12
+ <!-- Fill in the build/test/lint commands for this project. Examples: -->
13
+ ```bash
14
+ # build
15
+ # test
16
+ # lint
17
+ ```
18
+
19
+ ## Conventions & boundaries
20
+
21
+ - Conventional Commits required (`feat:`, `fix:`, `docs:`, `chore:`, ...). Breaking changes in a `BREAKING CHANGE:` footer.
22
+ - Never commit secrets, `.env*`, or credentials.
23
+ - Surgical changes only: touch what the task needs; no drive-by refactors, no speculative abstractions,
24
+ no comments that restate what the code already says.
25
+
26
+ ---
27
+
28
+ ## Indexed context
29
+
30
+ Project context lives in `.spur/context/` (gitignored) and is surfaced by the `sp:indexed-context` skill.
31
+ Check it before re-reading files you may already have indexed:
32
+
33
+ 1. `.spur/context/anatomy.md` — one-line description + token estimate per file. Read before opening a file.
34
+ 2. `.spur/context/learnings.md` — project conventions, decisions, preferences. Read before generating code.
35
+ 3. `.spur/context/pitfalls.md` — dated "do-not-repeat" entries. Read before generating code.
36
+ 4. `.spur/context/buglog.md` — historical bug log. Read before fixing a bug.
37
+ 5. `.spur/context/memory.md` — session log. Append one line per significant action.
38
+ 6. `.spur/context/token-ledger.jsonl` — auto-tracked by hooks; never hand-edit.
39
+
40
+ If `.spur/context/` is absent, proceed normally. Never block work on its absence.
@@ -12,6 +12,9 @@ updated_at: 1970-01-01T00:00:00.000Z
12
12
 
13
13
  > Authoritative on **decisions**. Lower number wins — this doc overrides all others on decisions.
14
14
  > Each entry is append-only; supersession is by a new dated entry, never by editing an old one.
15
+ > Only real cross-cutting decisions belong here — not implementation notes, not feature status, not
16
+ > how-to guidance. Entries that grow past decision + reason are carrying mechanism that belongs in
17
+ > `03`/`04`; link it instead of inlining it.
15
18
 
16
19
  ## ADR-001 — (example) Adopt this doc structure
17
20
 
@@ -24,4 +27,6 @@ updated_at: 1970-01-01T00:00:00.000Z
24
27
  <!--
25
28
  Add new ADRs here. Copy the entry shape above (Date, Status, Context, Decision, Reason).
26
29
  A decision that reverses a prior ADR adds a new entry that says "supersedes ADR-NNN".
30
+ An Amendment records the decision delta + one-line reason — not the mechanism. Implementation
31
+ paths, detailed semantics, and multi-paragraph rationale belong in 03/04, not in the amendment.
27
32
  -->
@@ -53,7 +53,7 @@ When a change touches one of these, the listed doc MUST be updated in the **same
53
53
 
54
54
  | ID | Trigger | Doc(s) |
55
55
  |----|---------|--------|
56
- | T1 | New cross-cutting decision | `00` first, then `03` mechanism |
56
+ | T1 | New cross-cutting decision (entry = decision + one-line reason; amendment = decision delta only — mechanism goes in `03`/`04`, not the amendment) | `00` first, then `03` mechanism |
57
57
  | T3 | Command/flag/config/schema/DTO added/changed | `04` + `AGENTS.md` |
58
58
  | T4 | Feature ships or changes state | `05` row |
59
59
  | T6 | Scope added / cut / deferred | `01` |
package/spur.js CHANGED
@@ -70181,7 +70181,7 @@ import { join as join13, resolve as resolve5 } from "path";
70181
70181
  var CLI_CONFIG = {
70182
70182
  binaryName: "spur",
70183
70183
  binaryLabel: "spur",
70184
- binaryVersion: "0.3.5",
70184
+ binaryVersion: "0.3.6",
70185
70185
  configDir: ".spur",
70186
70186
  configFile: ".spur/config.yaml",
70187
70187
  databaseFile: ".spur/spur.db"
@@ -70227,7 +70227,8 @@ var SCAFFOLD_MANIFEST = [
70227
70227
  { source: "templates/docs/02_ROADMAP.md", target: "templates/docs/02_ROADMAP.md" },
70228
70228
  { source: "templates/docs/03_ARCHITECTURE.md", target: "templates/docs/03_ARCHITECTURE.md" },
70229
70229
  { source: "templates/docs/04_DESIGN.md", target: "templates/docs/04_DESIGN.md" },
70230
- { source: "templates/docs/05_FEATURES.md", target: "templates/docs/05_FEATURES.md" }
70230
+ { source: "templates/docs/05_FEATURES.md", target: "templates/docs/05_FEATURES.md" },
70231
+ { source: "templates/AGENTS.md", target: "AGENTS.md", root: true, preserve: true }
70231
70232
  ];
70232
70233
 
70233
70234
  // src/commands/init.ts
@@ -70235,6 +70236,24 @@ var GLOBAL_CONFIG_DIR2 = join13(".config", "spur");
70235
70236
  var GLOBAL_RULES_DIR2 = join13(GLOBAL_CONFIG_DIR2, "rules");
70236
70237
  var GLOBAL_CONFIG_EXAMPLE = "config.example.yaml";
70237
70238
  var GLOBAL_CONFIG_FILE2 = "config.yaml";
70239
+ var INDEXED_CONTEXT_MARKER = "## Indexed context";
70240
+ var INDEXED_CONTEXT_BLOCK = `
70241
+ ---
70242
+
70243
+ ## Indexed context
70244
+
70245
+ Project context lives in \`.spur/context/\` (gitignored) and is surfaced by the \`sp:indexed-context\` skill.
70246
+ Check it before re-reading files you may already have indexed:
70247
+
70248
+ 1. \`.spur/context/anatomy.md\` \u2014 one-line description + token estimate per file. Read before opening a file.
70249
+ 2. \`.spur/context/learnings.md\` \u2014 project conventions, decisions, preferences. Read before generating code.
70250
+ 3. \`.spur/context/pitfalls.md\` \u2014 dated "do-not-repeat" entries. Read before generating code.
70251
+ 4. \`.spur/context/buglog.md\` \u2014 historical bug log. Read before fixing a bug.
70252
+ 5. \`.spur/context/memory.md\` \u2014 session log. Append one line per significant action.
70253
+ 6. \`.spur/context/token-ledger.jsonl\` \u2014 auto-tracked by hooks; never hand-edit.
70254
+
70255
+ If \`.spur/context/\` is absent, proceed normally. Never block work on its absence.
70256
+ `;
70238
70257
  function globalRulesRoot(context3) {
70239
70258
  const override = context3.env.SPUR_GLOBAL_RULES_DIR;
70240
70259
  return override !== undefined && override.length > 0 ? resolve5(context3.cwd, override) : join13(homedir5(), GLOBAL_RULES_DIR2);
@@ -70336,6 +70355,22 @@ function registerInitCommand(program2, context3) {
70336
70355
  const agentsDir = join13(context3.cwd, CLI_CONFIG.configDir, "agents");
70337
70356
  await context3.fs.ensureDir(agentsDir);
70338
70357
  await writeIfNew(context3, join13(agentsDir, ".gitkeep"), "", force, result);
70358
+ const gitignorePath = join13(context3.cwd, ".gitignore");
70359
+ const contextEntry = ".spur/context/";
70360
+ if (await context3.fs.exists(gitignorePath)) {
70361
+ const existing = await context3.fs.readFile(gitignorePath);
70362
+ if (!existing.includes(contextEntry)) {
70363
+ await context3.fs.writeFile(gitignorePath, `${existing.trimEnd()}
70364
+
70365
+ # Spur indexed-context (machine-generated)
70366
+ ${contextEntry}
70367
+ `);
70368
+ }
70369
+ } else {
70370
+ await context3.fs.writeFile(gitignorePath, `# Spur indexed-context (machine-generated)
70371
+ ${contextEntry}
70372
+ `);
70373
+ }
70339
70374
  if (!minimal) {
70340
70375
  const configRoot = bundledConfigRoot();
70341
70376
  if (configRoot !== null) {
@@ -70351,6 +70386,14 @@ function registerInitCommand(program2, context3) {
70351
70386
  }
70352
70387
  }
70353
70388
  }
70389
+ const agentsMdPath = join13(context3.cwd, "AGENTS.md");
70390
+ if (await context3.fs.exists(agentsMdPath)) {
70391
+ const existing = await context3.fs.readFile(agentsMdPath);
70392
+ if (!existing.includes(INDEXED_CONTEXT_MARKER)) {
70393
+ await context3.fs.writeFile(agentsMdPath, `${existing.trimEnd()}${INDEXED_CONTEXT_BLOCK}`);
70394
+ result.created.push(agentsMdPath);
70395
+ }
70396
+ }
70354
70397
  const db2 = await context3.getDb();
70355
70398
  await new ArtifactDao(db2).record({ path: configPath, kind: "config" });
70356
70399
  const rulesSeeded = await seedGlobalRules(context3);