@sporhq/spor 0.2.8 → 0.2.9
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/.claude-plugin/plugin.json +1 -1
- package/API.md +102 -11
- package/GRAPH.md +67 -4
- package/QUEUE.md +81 -15
- package/README.md +109 -3
- package/adapters/README.md +32 -0
- package/adapters/codex/README.md +7 -3
- package/adapters/copilot/README.md +3 -2
- package/adapters/cursor/README.md +3 -2
- package/adapters/gemini/README.md +3 -0
- package/adapters/opencode/README.md +3 -0
- package/bin/spor-hook +26 -2
- package/bin/spor-hook.js +18 -0
- package/bin/spor.js +534 -20
- package/lib/config.js +113 -5
- package/lib/graph.js +3 -0
- package/lib/kernel/graph.js +45 -33
- package/lib/kernel/queue.js +199 -29
- package/lib/kernel/registry.js +80 -1
- package/lib/queue.js +64 -2
- package/lib/seed/schema-edge-assigned.md +3 -1
- package/lib/seed/schema-edge-stewards.md +3 -1
- package/lib/seed/schema-person.md +10 -1
- package/package.json +5 -1
- package/scripts/engines/debounce-watcher.js +13 -0
- package/scripts/engines/distill.js +45 -8
- package/scripts/engines/doctor.js +188 -0
- package/scripts/engines/post-tool.js +166 -4
- package/scripts/engines/session-start.js +70 -6
- package/scripts/engines/util.js +109 -4
- package/skills/next/SKILL.md +5 -2
|
@@ -20,8 +20,9 @@ sed "s|__SPOR_ROOT__|$SPOR_ROOT|g" \
|
|
|
20
20
|
(Per-repo installs go in `.github/hooks/spor.json` — that is also the
|
|
21
21
|
only location the Copilot cloud coding agent loads.) Environment is the
|
|
22
22
|
usual set: `SPOR_SERVER`, `SPOR_TOKEN`, and `SPOR_DISTILL_CMD`
|
|
23
|
-
(e.g. `copilot -p "$(cat)"`) if the claude CLI isn't installed
|
|
24
|
-
`
|
|
23
|
+
(e.g. `copilot -p "$(cat)"`) if the claude CLI isn't installed — set
|
|
24
|
+
`SPOR_NUDGE_CMD` to the same value for the capture nudge, or `SPOR_NUDGE=0`
|
|
25
|
+
to skip it; legacy `SUBSTRATE_*` names are still read.
|
|
25
26
|
|
|
26
27
|
## Event mapping
|
|
27
28
|
|
|
@@ -17,8 +17,9 @@ sed "s|__SPOR_ROOT__|$SPOR_ROOT|g" \
|
|
|
17
17
|
(Or merge into an existing `~/.cursor/hooks.json` / project
|
|
18
18
|
`.cursor/hooks.json`.) Environment is the usual set: `SPOR_SERVER`,
|
|
19
19
|
`SPOR_TOKEN`, and `SPOR_DISTILL_CMD` if the claude CLI isn't installed
|
|
20
|
-
(`cursor-agent -p` works: prompt on stdin, response on stdout)
|
|
21
|
-
`
|
|
20
|
+
(`cursor-agent -p` works: prompt on stdin, response on stdout) — set
|
|
21
|
+
`SPOR_NUDGE_CMD` to the same value for the capture nudge, or `SPOR_NUDGE=0`
|
|
22
|
+
to skip it; legacy `SUBSTRATE_*` names are still read.
|
|
22
23
|
|
|
23
24
|
## Event mapping
|
|
24
25
|
|
|
@@ -31,6 +31,9 @@ export SPOR_SERVER=https://spor.example.com # remote mode
|
|
|
31
31
|
export SPOR_TOKEN=spor_pat_...
|
|
32
32
|
# Distiller backend (prompt on stdin, response on stdout):
|
|
33
33
|
export SPOR_DISTILL_CMD='gemini --model gemini-2.5-flash'
|
|
34
|
+
# Capture-nudge backend (same contract; runs synchronously, so pick a fast
|
|
35
|
+
# model). SPOR_NUDGE=0 disables it; see adapters/README.md for the bounds.
|
|
36
|
+
export SPOR_NUDGE_CMD='gemini --model gemini-2.5-flash'
|
|
34
37
|
```
|
|
35
38
|
|
|
36
39
|
(Legacy `SUBSTRATE_*` names are still read.)
|
|
@@ -24,6 +24,9 @@ export SPOR_TOKEN=spor_pat_...
|
|
|
24
24
|
# Distiller backend (prompt on stdin -> response on stdout); without the
|
|
25
25
|
# claude CLI installed, route through opencode itself:
|
|
26
26
|
export SPOR_DISTILL_CMD='opencode run "$(cat)"'
|
|
27
|
+
# Capture-nudge backend — same contract, runs synchronously, so prefer a fast
|
|
28
|
+
# model. SPOR_NUDGE=0 disables it; see adapters/README.md for the bounds.
|
|
29
|
+
export SPOR_NUDGE_CMD='opencode run "$(cat)"'
|
|
27
30
|
```
|
|
28
31
|
|
|
29
32
|
## Behavior mapping
|
package/bin/spor-hook
CHANGED
|
@@ -3,5 +3,29 @@
|
|
|
3
3
|
# kept so existing hooks configs and adapter manifests that exec this path
|
|
4
4
|
# keep working unchanged. Windows hosts invoke spor-hook.js via node
|
|
5
5
|
# (or spor-hook.cmd) instead. Fail-open: no node, no output, exit 0.
|
|
6
|
-
command -v node >/dev/null 2>&1
|
|
7
|
-
exec node "$(dirname "$0")/spor-hook.js" "$@"
|
|
6
|
+
if command -v node >/dev/null 2>&1; then
|
|
7
|
+
exec node "$(dirname "$0")/spor-hook.js" "$@"
|
|
8
|
+
fi
|
|
9
|
+
# No Node interpreter — the hook can do nothing (the client is zero-dep *Node*).
|
|
10
|
+
# Stay fail-open (exit 0, no output, no latency on the working path above), but
|
|
11
|
+
# drop a ONE-TIME greppable breadcrumb so the silence is diagnosable instead of
|
|
12
|
+
# invisible (issue-spor-onboarding-no-node-silent-fail-open). Best-effort: every
|
|
13
|
+
# step is guarded and we exit 0 regardless, so this can never break fail-open.
|
|
14
|
+
# Resolve the graph home the way lib/shell/home.js does: $SPOR_HOME, then the
|
|
15
|
+
# legacy $SUBSTRATE_HOME, else ~/.spor (or ~/.substrate if that legacy dir
|
|
16
|
+
# exists). The breadcrumb is written at most once (guarded by its own marker).
|
|
17
|
+
_spor_home="${SPOR_HOME:-${SUBSTRATE_HOME:-}}"
|
|
18
|
+
if [ -z "$_spor_home" ]; then
|
|
19
|
+
if [ -d "$HOME/.spor" ]; then _spor_home="$HOME/.spor"
|
|
20
|
+
elif [ -d "$HOME/.substrate" ]; then _spor_home="$HOME/.substrate"
|
|
21
|
+
else _spor_home="$HOME/.spor"
|
|
22
|
+
fi
|
|
23
|
+
fi
|
|
24
|
+
_spor_warn="$_spor_home/journal/no-node.warn"
|
|
25
|
+
if [ -n "$HOME" ] && [ ! -f "$_spor_warn" ]; then
|
|
26
|
+
if mkdir -p "$_spor_home/journal" 2>/dev/null; then
|
|
27
|
+
printf '%s spor-hook: node not found on PATH — every hook is a silent no-op. Spor needs a Node interpreter (see package.json engines; `spor status` reports the floor). Install Node, then restart your session.\n' \
|
|
28
|
+
"$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo now)" >"$_spor_warn" 2>/dev/null || true
|
|
29
|
+
fi
|
|
30
|
+
fi
|
|
31
|
+
exit 0
|
package/bin/spor-hook.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
// spor-hook post-tool [--host ...]
|
|
16
16
|
// spor-hook distill [--host ...] [--debounce SECONDS]
|
|
17
17
|
// spor-hook agents-md [--cwd DIR] # AGENTS.md floor; no stdin
|
|
18
|
+
// spor-hook doctor [--cwd DIR] # client health report; no stdin
|
|
18
19
|
//
|
|
19
20
|
// Fail-open contract (dec-cc-fail-open-hooks): any failure exits 0 with no
|
|
20
21
|
// output — a Spor problem never costs the user their session.
|
|
@@ -114,6 +115,23 @@ async function main() {
|
|
|
114
115
|
return;
|
|
115
116
|
}
|
|
116
117
|
|
|
118
|
+
// `spor-hook doctor` (task-cc-client-hook-operability-diagnostics piece 3):
|
|
119
|
+
// an operator-run diagnostic, not a host hook — it takes no stdin and prints a
|
|
120
|
+
// human-readable health report. It runs even when the plugin is disabled for
|
|
121
|
+
// the repo (a disabled plugin is exactly what you'd want doctor to tell you).
|
|
122
|
+
// Write the report with fs.writeSync(1) so the full body flushes before the
|
|
123
|
+
// crash handler's process.exit(0) can truncate a piped stdout.
|
|
124
|
+
if (event === "doctor") {
|
|
125
|
+
const { doctor } = require("../scripts/engines/doctor");
|
|
126
|
+
let dCwd = process.cwd();
|
|
127
|
+
const ci = args.indexOf("--cwd");
|
|
128
|
+
if (ci >= 0 && args[ci + 1]) dCwd = args[ci + 1];
|
|
129
|
+
u.useConfig({ cwd: dCwd });
|
|
130
|
+
const report = await doctor();
|
|
131
|
+
fs.writeSync(1, report);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
117
135
|
if (!(event in ENGINES)) {
|
|
118
136
|
process.stderr.write(`spor-hook: unknown event '${event}'\n`);
|
|
119
137
|
return;
|