@sporhq/spor 0.2.6 → 0.2.7
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/README.md +21 -28
- package/bin/spor.js +62 -4
- package/package.json +1 -1
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"name": "spor",
|
|
3
3
|
"displayName": "Spor Context Compiler",
|
|
4
4
|
"description": "Maintains a typed, versioned knowledge graph and compiles compact briefings from it: session-start injection, per-prompt relevance digests, capture at discovery, end-of-session distillation, decision queue.",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.7",
|
|
6
6
|
"author": { "name": "losthammer" }
|
|
7
7
|
}
|
package/README.md
CHANGED
|
@@ -24,21 +24,8 @@ Requires Node 20+ and nothing else — the client is zero-dependency. To run
|
|
|
24
24
|
from a checkout instead (e.g. to hack on it), clone the repo and `npm link`
|
|
25
25
|
from its root; that symlinks the same two commands onto your PATH.
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
spor init # creates ~/.spor/nodes, git-inits it, writes .gitignore
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
`spor init` is idempotent. `spor status` then tells you the resolved mode,
|
|
34
|
-
graph, project, and (in remote mode) server health and identity — run it any
|
|
35
|
-
time you're unsure whether Spor is active or which graph you're on. (Without
|
|
36
|
-
the `spor` CLI on your PATH the equivalent is
|
|
37
|
-
`mkdir -p ~/.spor/nodes && git -C ~/.spor init && printf 'journal/\n' > ~/.spor/.gitignore`.)
|
|
38
|
-
|
|
39
|
-
Then install for your agent. One verb wires up any supported host — it
|
|
40
|
-
resolves the adapter manifest to this checkout and drops it into the host's
|
|
41
|
-
config:
|
|
27
|
+
Wire Spor into your agent. One verb resolves the adapter manifest to this
|
|
28
|
+
install and drops it into the host's config:
|
|
42
29
|
|
|
43
30
|
```bash
|
|
44
31
|
spor install claude # Claude Code (via its plugin CLI — no marketplace browsing)
|
|
@@ -50,27 +37,33 @@ spor install # no host => list the hosts detected on this machine
|
|
|
50
37
|
per-repo config. `--all` installs every detected host, `--print` is a dry run,
|
|
51
38
|
and `--server <url> --token <tok>` also points the client at a team graph in
|
|
52
39
|
the same step. Re-running is idempotent — it refreshes the path and never
|
|
53
|
-
duplicates your other hooks.
|
|
40
|
+
duplicates your other hooks. (In Claude Code you can also install by hand:
|
|
41
|
+
`/plugin marketplace add sporhq/spor` then `/plugin install spor@spor`.)
|
|
54
42
|
|
|
55
|
-
|
|
56
|
-
prefer:
|
|
43
|
+
Then onboard a repo — one command, from inside it:
|
|
57
44
|
|
|
45
|
+
```bash
|
|
46
|
+
cd ~/my-repo && spor dispatch --backfill
|
|
58
47
|
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
|
|
49
|
+
That does the whole setup in one step: creates your graph home if it doesn't
|
|
50
|
+
exist yet (`~/.spor/nodes`, git-initialised), registers the repo so Spor knows
|
|
51
|
+
where it lives on this machine, makes sure Spor is enabled for it, and launches
|
|
52
|
+
the `/spor:backfill` agent in a Claude Code background session — it mines git
|
|
53
|
+
history, design docs, and issue trackers (edges first) and proposes how to
|
|
54
|
+
group your repos into projects. Watch or attach to it with `claude agents`.
|
|
55
|
+
Re-run it whenever you add a repo, or skip it entirely and just work —
|
|
56
|
+
distillation grows the graph one session at a time.
|
|
57
|
+
|
|
58
|
+
`spor status` tells you the resolved mode, graph, project, and (on a team
|
|
59
|
+
graph) server health and identity — run it any time you're unsure whether Spor
|
|
60
|
+
is active or which graph you're on. `spor init` does the graph-home setup on
|
|
61
|
+
its own if you'd rather not dispatch anything yet.
|
|
62
62
|
|
|
63
63
|
For the per-host event mapping, fidelity notes, distiller backend, and the
|
|
64
64
|
`AGENTS.md` fallback for hosts with no hook support, see
|
|
65
65
|
[adapters/](adapters/).
|
|
66
66
|
|
|
67
|
-
To start with a populated graph, run `/spor:backfill` — the onboarding door. It
|
|
68
|
-
dispatches the heavy mining (git history, design docs, issue trackers, edges
|
|
69
|
-
first) to the bundled `spor-backfill` **subagent**, which runs in its own
|
|
70
|
-
context, and then proposes how to group your repos into projects (re-run it as
|
|
71
|
-
you add repos). Or skip it and just work — distillation grows the graph one
|
|
72
|
-
session at a time.
|
|
73
|
-
|
|
74
67
|
## Dispatching background agents
|
|
75
68
|
|
|
76
69
|
`spor dispatch` hands a task to Claude Code's background-agent machinery
|
package/bin/spor.js
CHANGED
|
@@ -101,7 +101,10 @@ function nodeCount(nodesDir) {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
// Idempotently create the local graph home (nodes/, git, .gitignore). Returns
|
|
105
|
+
// { home, nodesDir, created } and prints nothing — callers do their own UX.
|
|
106
|
+
// Shared by `spor init` and the `spor dispatch --backfill` onboarding path.
|
|
107
|
+
function ensureGraphHome(cfg) {
|
|
105
108
|
const home = cfg.graphHome();
|
|
106
109
|
const nodesDir = path.join(home, "nodes");
|
|
107
110
|
let created = false;
|
|
@@ -122,6 +125,11 @@ function cmdInit(cfg) {
|
|
|
122
125
|
/* non-fatal */
|
|
123
126
|
}
|
|
124
127
|
}
|
|
128
|
+
return { home, nodesDir, created };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function cmdInit(cfg) {
|
|
132
|
+
const { home, nodesDir, created } = ensureGraphHome(cfg);
|
|
125
133
|
out(`${created ? "Created" : "Graph already present at"} ${home}`);
|
|
126
134
|
out(` nodes: ${nodesDir} (${nodeCount(nodesDir) ?? 0} nodes)`);
|
|
127
135
|
out(` mode: ${cfg.mode()}`);
|
|
@@ -1004,6 +1012,45 @@ function shellQuote(s) {
|
|
|
1004
1012
|
return /[^\w./:-]/.test(s) ? `'${String(s).replace(/'/g, "'\\''")}'` : s;
|
|
1005
1013
|
}
|
|
1006
1014
|
|
|
1015
|
+
// Re-enable Spor for a repo by merging { enabled: true } into its committable
|
|
1016
|
+
// .spor.json (and clearing a `mode: off`, which also disables). Used by the
|
|
1017
|
+
// --backfill onboarding to repair a repo a prior `spor disable` turned off.
|
|
1018
|
+
function enableRepoAt(dir) {
|
|
1019
|
+
const file = path.join(dir, ".spor.json");
|
|
1020
|
+
let data = {};
|
|
1021
|
+
try {
|
|
1022
|
+
data = JSON.parse(fs.readFileSync(file, "utf8")) || {};
|
|
1023
|
+
} catch {
|
|
1024
|
+
/* absent or malformed — start fresh */
|
|
1025
|
+
}
|
|
1026
|
+
data.enabled = true;
|
|
1027
|
+
if (data.mode === "off") delete data.mode;
|
|
1028
|
+
try {
|
|
1029
|
+
fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
|
|
1030
|
+
} catch {
|
|
1031
|
+
/* non-fatal */
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// `spor dispatch --backfill` is the onboarding door (task-spor-cli-dispatch-
|
|
1036
|
+
// background-agents): set the repo up before launching its backfill agent.
|
|
1037
|
+
// Idempotent; prints what it did. The dir-registration happens in cmdDispatch
|
|
1038
|
+
// (it applies to every dispatch), this adds the init + enable steps.
|
|
1039
|
+
function onboardRepo(cfg, dir) {
|
|
1040
|
+
// Init the local graph home — but only in local mode; remote mode keeps the
|
|
1041
|
+
// graph on the server, so there is nothing to create locally.
|
|
1042
|
+
if (cfg.mode() !== "remote") {
|
|
1043
|
+
const r = ensureGraphHome(cfg);
|
|
1044
|
+
out(r.created ? `initialized graph home at ${r.home}` : `graph home ready: ${r.home}`);
|
|
1045
|
+
}
|
|
1046
|
+
// Re-enable the repo if a prior `spor disable` turned it off, so onboarding a
|
|
1047
|
+
// disabled repo actually works instead of silently launching into a no-op.
|
|
1048
|
+
if (!cfg.enabled()) {
|
|
1049
|
+
enableRepoAt(dir);
|
|
1050
|
+
out(`re-enabled Spor for ${dir}`);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1007
1054
|
async function cmdDispatch(cfg, args) {
|
|
1008
1055
|
const dryRun = args.includes("--print") || args.includes("--dry-run");
|
|
1009
1056
|
const full = args.includes("--full");
|
|
@@ -1089,9 +1136,6 @@ async function cmdDispatch(cfg, args) {
|
|
|
1089
1136
|
err(`target dir does not exist: ${res.dir}`);
|
|
1090
1137
|
return 1;
|
|
1091
1138
|
}
|
|
1092
|
-
// Learn the mapping from this CLI use too.
|
|
1093
|
-
u.registerRepo(cfg.graphHome(), res.slug, res.dir);
|
|
1094
|
-
|
|
1095
1139
|
const prompt = brief
|
|
1096
1140
|
? `# Spor briefing (compiled for this task — your standing context)\n\n${brief}\n\n---\n\n# Task\n\n${instruction}\n`
|
|
1097
1141
|
: instruction;
|
|
@@ -1106,12 +1150,26 @@ async function cmdDispatch(cfg, args) {
|
|
|
1106
1150
|
|
|
1107
1151
|
if (dryRun) {
|
|
1108
1152
|
out(`dir: ${res.dir} (slug: ${res.slug}, via ${res.source})`);
|
|
1153
|
+
if (backfill) {
|
|
1154
|
+
const steps = [];
|
|
1155
|
+
if (cfg.mode() !== "remote") steps.push(fs.existsSync(cfg.nodesDir()) ? "graph home ready" : "init graph home");
|
|
1156
|
+
steps.push(`register ${res.slug} → ${res.dir}`);
|
|
1157
|
+
if (!cfg.enabled()) steps.push("re-enable repo (currently disabled)");
|
|
1158
|
+
out(`onboard: ${steps.join("; ")}`);
|
|
1159
|
+
}
|
|
1109
1160
|
out(`brief: ${brief ? `${brief.length} bytes` : "(none — graph had nothing relevant, or --no-brief/--backfill)"}`);
|
|
1110
1161
|
out(`run: ${claudeBin} ${claudeArgs.slice(0, -1).map(shellQuote).join(" ")} <prompt>`);
|
|
1111
1162
|
out(`\n--- prompt ---\n${prompt}`);
|
|
1112
1163
|
return 0;
|
|
1113
1164
|
}
|
|
1114
1165
|
|
|
1166
|
+
// Side effects (real run only — --print writes nothing). --backfill is the
|
|
1167
|
+
// onboarding door, so it sets the repo up (init + enable) first; every
|
|
1168
|
+
// dispatch self-registers the dir it resolved.
|
|
1169
|
+
if (backfill) onboardRepo(cfg, res.dir);
|
|
1170
|
+
u.registerRepo(cfg.graphHome(), res.slug, res.dir);
|
|
1171
|
+
if (backfill) out(`registered ${res.slug} → ${res.dir}; launching the backfill agent…`);
|
|
1172
|
+
|
|
1115
1173
|
if (claudeBin === "claude" && !hasCmd("claude")) {
|
|
1116
1174
|
err("claude CLI not on PATH — install Claude Code, then re-run (or 'spor dispatch … --print' to see the prompt).");
|
|
1117
1175
|
return 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sporhq/spor",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Spor — a shared memory substrate for teams and agents. Decisions, their reasons, and the traces they leave. Knowledge-graph context compiler: session-start briefings, per-prompt digests, capture at discovery, end-of-session distillation, decision queue.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Anthony Allen",
|