@gobing-ai/spur 0.3.2 → 0.3.3
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.
|
|
3
|
+
"version": "0.3.3",
|
|
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",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "https://gobing.ai/spur/schemas/section-matrix.schema.json",
|
|
4
4
|
"title": "Section-Status-Matrix Schema",
|
|
5
|
-
"description": "Validates
|
|
5
|
+
"description": "Validates the shipped section-matrix.yaml — which sections are required/optional/forbidden per task status. Design §3.2. Authored for ts-runtime's loadStructuredConfig validator (supports properties/required/additionalProperties + $defs/$ref/enum; NOT patternProperties/uniqueItems).",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["variants"],
|
|
8
8
|
"additionalProperties": false,
|
|
@@ -15,7 +15,7 @@ bootstrap:
|
|
|
15
15
|
console: false
|
|
16
16
|
json: false
|
|
17
17
|
file: true
|
|
18
|
-
filePath: .spur/spur.log # relative to project root
|
|
18
|
+
filePath: .spur/logs/spur.log # relative to project root
|
|
19
19
|
telemetry:
|
|
20
20
|
enabled: false # OFF by default for CLI (per-invocation latency)
|
|
21
21
|
serviceName: spur
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
$schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
|
|
2
|
+
# Runtime-path boundary rule (task 0217, R6) — zero `config/(plugins|rules|tasks|templates|workflows)`
|
|
3
|
+
# references in agent-facing instructions and runtime source code. `config/` is the build-time
|
|
4
|
+
# bundled-asset source-of-truth (ADR-015); `.spur/` is the runtime configuration directory that
|
|
5
|
+
# agents and runtime code MUST reference. A `config/...` literal in scope teaches the wrong
|
|
6
|
+
# convention and propagates confusion into every project created via `/sp:spur-init`.
|
|
7
|
+
#
|
|
8
|
+
# Blanket scope (all file types across apps/packages/plugins/sp) chosen deliberately:
|
|
9
|
+
# even build-time JSDoc and test-fixture `config/` literals are caught, forcing rephrase rather
|
|
10
|
+
# than false-positive triage. See task 0217 Design "Standing enforcement (R6)" for rationale.
|
|
11
|
+
#
|
|
12
|
+
# This is a STANDING gate (not transitional like rg-migration.yaml) — it runs on every pre-check.
|
|
13
|
+
include:
|
|
14
|
+
- "apps/**"
|
|
15
|
+
- "packages/**"
|
|
16
|
+
- "plugins/sp/**"
|
|
17
|
+
exclude:
|
|
18
|
+
- "**/node_modules/**"
|
|
19
|
+
- "**/dist/**"
|
|
20
|
+
rules:
|
|
21
|
+
- id: sp-runtime-path
|
|
22
|
+
description: >
|
|
23
|
+
Use `.spur/` paths for runtime configuration references, not `config/`. `config/` is the
|
|
24
|
+
build-time bundled-asset source-of-truth (ADR-015); `.spur/` is the runtime directory.
|
|
25
|
+
Agent-facing instructions (`plugins/sp/`) and runtime code (`apps/`, `packages/`) MUST NOT
|
|
26
|
+
contain literal `config/plugins`, `config/rules`, `config/tasks`, `config/templates`, or
|
|
27
|
+
`config/workflows` path references.
|
|
28
|
+
severity: error
|
|
29
|
+
evaluator:
|
|
30
|
+
type: rg
|
|
31
|
+
config:
|
|
32
|
+
pattern: "config/(plugins|rules|tasks|templates|workflows)"
|
package/spur.js
CHANGED
|
@@ -59693,7 +59693,7 @@ function gitDiffU0(cwd) {
|
|
|
59693
59693
|
var init_task_record = () => {};
|
|
59694
59694
|
|
|
59695
59695
|
// ../../packages/app/src/services/task-service.ts
|
|
59696
|
-
import {
|
|
59696
|
+
import { isAbsolute, relative as relative2, resolve as resolve2 } from "path";
|
|
59697
59697
|
function patchFrontmatterField(rendered, key, value) {
|
|
59698
59698
|
const existingRe = new RegExp(`^(?=\\s*${escapeRegex2(key)}:)`, "m");
|
|
59699
59699
|
if (existingRe.test(rendered)) {
|
|
@@ -60276,8 +60276,8 @@ ${block}` : block);
|
|
|
60276
60276
|
resolveListDir(folder) {
|
|
60277
60277
|
if (folder === undefined)
|
|
60278
60278
|
return this.ctx.tasksDir;
|
|
60279
|
-
const root =
|
|
60280
|
-
const candidate =
|
|
60279
|
+
const root = this.ctx.fs.resolve(".");
|
|
60280
|
+
const candidate = this.ctx.fs.resolve(folder);
|
|
60281
60281
|
const rel = relative2(root, candidate);
|
|
60282
60282
|
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
60283
60283
|
throw new Error(`Invalid folder: ${folder} escapes the planning workspace`);
|
|
@@ -60687,7 +60687,7 @@ var init_team_service = __esm(() => {
|
|
|
60687
60687
|
import { execFile } from "child_process";
|
|
60688
60688
|
import { existsSync as existsSync4 } from "fs";
|
|
60689
60689
|
import { mkdir, writeFile } from "fs/promises";
|
|
60690
|
-
import { dirname as
|
|
60690
|
+
import { dirname as dirname8, isAbsolute as isAbsolute2, join as join10 } from "path";
|
|
60691
60691
|
import { promisify as promisify3 } from "util";
|
|
60692
60692
|
|
|
60693
60693
|
class AgentRunActionRunner {
|
|
@@ -60742,7 +60742,7 @@ class AgentRunActionRunner {
|
|
|
60742
60742
|
const ok2 = exitCode2 === 0;
|
|
60743
60743
|
if (answerFile !== undefined) {
|
|
60744
60744
|
const target = isAbsolute2(answerFile) ? answerFile : join10(cwd, answerFile);
|
|
60745
|
-
await mkdir(
|
|
60745
|
+
await mkdir(dirname8(target), { recursive: true });
|
|
60746
60746
|
await writeFile(target, answer, "utf8");
|
|
60747
60747
|
}
|
|
60748
60748
|
if (ok2 && expectFile !== undefined) {
|
|
@@ -60844,7 +60844,7 @@ async function writePartialWorkArtifact(context3, agentLabel, captured, cwd) {
|
|
|
60844
60844
|
].join(`
|
|
60845
60845
|
`);
|
|
60846
60846
|
const target = join10(cwd, ".spur", "run", `${context3.runId}-${context3.stateOrNodeId}-partial.md`);
|
|
60847
|
-
await mkdir(
|
|
60847
|
+
await mkdir(dirname8(target), { recursive: true });
|
|
60848
60848
|
await writeFile(target, body, "utf8");
|
|
60849
60849
|
} catch {}
|
|
60850
60850
|
}
|
|
@@ -69925,7 +69925,7 @@ import { join as join13, resolve as resolve5 } from "path";
|
|
|
69925
69925
|
var CLI_CONFIG = {
|
|
69926
69926
|
binaryName: "spur",
|
|
69927
69927
|
binaryLabel: "spur",
|
|
69928
|
-
binaryVersion: "0.3.
|
|
69928
|
+
binaryVersion: "0.3.3",
|
|
69929
69929
|
configDir: ".spur",
|
|
69930
69930
|
configFile: ".spur/config.yaml",
|
|
69931
69931
|
databaseFile: ".spur/spur.db"
|
|
@@ -70059,7 +70059,7 @@ function registerInitCommand(program2, context3) {
|
|
|
70059
70059
|
" logging:",
|
|
70060
70060
|
" enabled: true",
|
|
70061
70061
|
" level: info",
|
|
70062
|
-
" console:
|
|
70062
|
+
" console: false",
|
|
70063
70063
|
" json: true",
|
|
70064
70064
|
" file: true",
|
|
70065
70065
|
` filePath: ${CLI_CONFIG.configDir}/logs/spur.log`,
|
|
@@ -70526,8 +70526,9 @@ init_src();
|
|
|
70526
70526
|
|
|
70527
70527
|
// ../server/src/serve.ts
|
|
70528
70528
|
init_src3();
|
|
70529
|
+
init_loader();
|
|
70529
70530
|
init_src2();
|
|
70530
|
-
import { dirname as
|
|
70531
|
+
import { dirname as dirname9, isAbsolute as isAbsolute3, join as join16 } from "path";
|
|
70531
70532
|
init_dist3();
|
|
70532
70533
|
|
|
70533
70534
|
// ../server/src/bootstrap.ts
|
|
@@ -78682,7 +78683,7 @@ function serverBootstrapConfig(env) {
|
|
|
78682
78683
|
const raw2 = env.SPUR_TEAM_AUTOSTART;
|
|
78683
78684
|
const teamAutostart = raw2 ? raw2.split(",").map((s) => s.trim()).filter((s) => s.length > 0) : [];
|
|
78684
78685
|
return {
|
|
78685
|
-
logging: { enabled: !isTest, level: env.SPUR_LOG_LEVEL ?? "info" },
|
|
78686
|
+
logging: { enabled: !isTest, level: env.SPUR_LOG_LEVEL ?? "info", console: false },
|
|
78686
78687
|
telemetry: { enabled: false },
|
|
78687
78688
|
events: { enabled: true },
|
|
78688
78689
|
jobqueue: { enabled: !isTest },
|
|
@@ -78964,7 +78965,8 @@ var defaultDeps = {
|
|
|
78964
78965
|
const { NodeSchedulerAdapter: NodeSchedulerAdapter2 } = await Promise.resolve().then(() => (init_scheduler_node(), exports_scheduler_node));
|
|
78965
78966
|
return new NodeSchedulerAdapter2;
|
|
78966
78967
|
},
|
|
78967
|
-
openUrl
|
|
78968
|
+
openUrl,
|
|
78969
|
+
resolveConfigFile
|
|
78968
78970
|
};
|
|
78969
78971
|
function registerSchedulerEntries(scheduler3, ctx) {
|
|
78970
78972
|
scheduler3.register(SYSTEM_EVENTS_PRUNE_CRON, async () => {
|
|
@@ -79021,7 +79023,7 @@ async function runTaskActionJob(ctx, env, payload, createAgentService = createTa
|
|
|
79021
79023
|
async function resolveWebDistPath(configuredPath) {
|
|
79022
79024
|
const candidates = configuredPath && configuredPath.trim() !== "" ? [isAbsolute3(configuredPath) ? configuredPath : join16(process.cwd(), configuredPath)] : [
|
|
79023
79025
|
join16(process.cwd(), "dist/web"),
|
|
79024
|
-
join16(
|
|
79026
|
+
join16(dirname9(process.execPath), "../web"),
|
|
79025
79027
|
join16(import.meta.dir, "../../../dist/web")
|
|
79026
79028
|
];
|
|
79027
79029
|
for (const candidate of candidates) {
|
|
@@ -79034,8 +79036,10 @@ async function resolveWebDistPath(configuredPath) {
|
|
|
79034
79036
|
async function startServer(options, deps = defaultDeps) {
|
|
79035
79037
|
const env = process.env;
|
|
79036
79038
|
const bootConfig = deps.serverBootstrapConfig(env);
|
|
79039
|
+
const configFile = deps.resolveConfigFile();
|
|
79037
79040
|
await deps.runNodeApplication({
|
|
79038
79041
|
config: bootConfig,
|
|
79042
|
+
configLoader: configFile ? { configFile, bootstrapSection: "bootstrap" } : undefined,
|
|
79039
79043
|
async start(appRt) {
|
|
79040
79044
|
const fs3 = deps.createNodeFileSystem(process.cwd());
|
|
79041
79045
|
let scheduler3;
|
|
@@ -79287,7 +79291,7 @@ var section_matrix_schema_default = {
|
|
|
79287
79291
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
79288
79292
|
$id: "https://gobing.ai/spur/schemas/section-matrix.schema.json",
|
|
79289
79293
|
title: "Section-Status-Matrix Schema",
|
|
79290
|
-
description: "Validates
|
|
79294
|
+
description: "Validates the shipped section-matrix.yaml \u2014 which sections are required/optional/forbidden per task status. Design \xA73.2. Authored for ts-runtime's loadStructuredConfig validator (supports properties/required/additionalProperties + $defs/$ref/enum; NOT patternProperties/uniqueItems).",
|
|
79291
79295
|
type: "object",
|
|
79292
79296
|
required: ["variants"],
|
|
79293
79297
|
additionalProperties: false,
|
|
@@ -80671,7 +80675,7 @@ init_src3();
|
|
|
80671
80675
|
init_src();
|
|
80672
80676
|
init_src2();
|
|
80673
80677
|
init_dist3();
|
|
80674
|
-
import { dirname as
|
|
80678
|
+
import { dirname as dirname10, join as join19, resolve as resolve7 } from "path";
|
|
80675
80679
|
import { isatty as isatty3 } from "tty";
|
|
80676
80680
|
|
|
80677
80681
|
// ../../node_modules/.bun/@clack+core@1.4.1/node_modules/@clack/core/dist/index.mjs
|
|
@@ -82083,7 +82087,7 @@ async function createMigratedDbAdapter(cwd = process.cwd(), env = process.env, d
|
|
|
82083
82087
|
const configuredUrl = env.DATABASE_URL === undefined ? join19(cwd, CLI_CONFIG.databaseFile) : config3.database.url;
|
|
82084
82088
|
const url2 = dbUrl ?? configuredUrl;
|
|
82085
82089
|
if (url2 !== ":memory:") {
|
|
82086
|
-
await createNodeFileSystem().ensureDir(
|
|
82090
|
+
await createNodeFileSystem().ensureDir(dirname10(url2));
|
|
82087
82091
|
}
|
|
82088
82092
|
return createMigratedDb({ url: url2 });
|
|
82089
82093
|
}
|
|
@@ -82103,7 +82107,7 @@ async function main(argv = process.argv.slice(2), options = {}) {
|
|
|
82103
82107
|
bootstrapSection: "bootstrap",
|
|
82104
82108
|
appConfig: { safeParse: (raw2) => spurConfigSchema.safeParse(raw2) }
|
|
82105
82109
|
},
|
|
82106
|
-
config:
|
|
82110
|
+
config: { logging: { console: false } },
|
|
82107
82111
|
services: { db: db2 },
|
|
82108
82112
|
async start(appRt) {
|
|
82109
82113
|
const context3 = createCliContext({
|