@drawbridge/drawbridge-agents 0.1.0 → 0.1.1
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/README.md +10 -7
- package/bin/graph.js +20 -19
- package/bin/preflight-graphify.js +4 -8
- package/conventions/graphify.md +16 -11
- package/graph/README.md +7 -10
- package/hooks/drift-check.js +6 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,12 +86,14 @@ Beyond the conventions, this package gives agents cross-repo visibility and keep
|
|
|
86
86
|
and the knowledge graph from drifting. Everything below is committed **only in this repo** and
|
|
87
87
|
reaches consumers without committing anything to them (see "Isolation").
|
|
88
88
|
|
|
89
|
-
- **Family knowledge graph (Graphify).** `npx drawbridge-agents-graph`
|
|
90
|
-
`drawbridge-*` repo
|
|
91
|
-
Agents query it
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
`
|
|
89
|
+
- **Family knowledge graph (Graphify).** `npx drawbridge-agents-graph` runs code-only AST
|
|
90
|
+
extraction over every `drawbridge-*` repo and merges them into the cross-repo graph at
|
|
91
|
+
`~/.graphify/global-graph.json`. Agents query it with the `graphify` CLI (e.g.
|
|
92
|
+
`graphify query "…" --graph ~/.graphify/global-graph.json`) instead of grepping. The runtime is
|
|
93
|
+
a per-machine Python tool — `npm run sync` installs it (`bin/preflight-graphify.js`); set
|
|
94
|
+
`DRAWBRIDGE_SKIP_GRAPHIFY=1` to skip in CI/headless. We deliberately do **not** run
|
|
95
|
+
`graphify install` (it would rewrite `CLAUDE.md`); the optional `graphify-mcp` server is
|
|
96
|
+
available if you prefer MCP.
|
|
95
97
|
- **Docs linkage + validator.** Feature code carries `@story <domain>/<slug>` / `@doc
|
|
96
98
|
reference/<file>#<anchor>` anchors (see `conventions/docs-linkage.md`).
|
|
97
99
|
`npx drawbridge-agents-check-docs` scans every repo and fails if any anchor no longer resolves
|
|
@@ -107,7 +109,8 @@ reaches consumers without committing anything to them (see "Isolation").
|
|
|
107
109
|
### Isolation (nothing ships to DigitalOcean)
|
|
108
110
|
|
|
109
111
|
- The package is a **devDependency** → not installed in production.
|
|
110
|
-
- The
|
|
112
|
+
- The graph and CLI are per-machine (`~/.graphify/`); nothing graph-related is written into the
|
|
113
|
+
consumer repo, and `graphify install` (which edits `CLAUDE.md`) is never run.
|
|
111
114
|
- The Stop hook is merged into `.claude/settings.local.json` (gitignored).
|
|
112
115
|
- Skills install to `~/.claude/skills/` (per-machine, outside any repo).
|
|
113
116
|
- The only in-repo footprint in consumers is inert `@story`/`@doc` source comments.
|
package/bin/graph.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Builds the family knowledge graph:
|
|
3
|
-
// the shared @drawbridge/* packages)
|
|
4
|
-
//
|
|
5
|
-
//
|
|
2
|
+
// Builds the family knowledge graph: runs graphify's headless AST extraction over every
|
|
3
|
+
// drawbridge-* repo (plus drawbridge-docs and the shared @drawbridge/* packages) and merges
|
|
4
|
+
// each into the global cross-repo graph at ~/.graphify/global-graph.json — which is what agents
|
|
5
|
+
// query. Code-only (local AST, no API key). See conventions/graphify.md.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
7
|
+
// A semantic build (adds doc/paper content + INFERRED edges) needs an LLM backend: drop
|
|
8
|
+
// --code-only and set an API key (e.g. ANTHROPIC_API_KEY) — slower and costs LLM calls.
|
|
9
9
|
const fs = require('fs')
|
|
10
|
+
const os = require('os')
|
|
10
11
|
const path = require('path')
|
|
11
12
|
const { execFileSync } = require('child_process')
|
|
12
13
|
|
|
13
14
|
const packageRoot = path.resolve(__dirname, '..')
|
|
14
|
-
const graphDir = path.join(packageRoot, 'graph')
|
|
15
15
|
const familyRoot = path.resolve(packageRoot, '..')
|
|
16
|
+
const buildDir = path.join(os.homedir(), '.graphify', 'build')
|
|
16
17
|
|
|
17
18
|
// The canonical family list lives in the shared settings template — single source of truth.
|
|
18
19
|
const settings = JSON.parse(fs.readFileSync(path.join(packageRoot, '.claude-template', 'settings.json'), 'utf8'))
|
|
@@ -34,7 +35,7 @@ if (!hasGraphify()) {
|
|
|
34
35
|
process.exit(1)
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
fs.mkdirSync(
|
|
38
|
+
fs.mkdirSync(buildDir, { recursive: true })
|
|
38
39
|
|
|
39
40
|
const built = []
|
|
40
41
|
for (const name of repos) {
|
|
@@ -44,17 +45,17 @@ for (const name of repos) {
|
|
|
44
45
|
continue
|
|
45
46
|
}
|
|
46
47
|
console.log(` extract ${ name }`)
|
|
47
|
-
|
|
48
|
+
// --out redirects the per-repo graphify-out/ away from the repo (keeps it clean);
|
|
49
|
+
// --global merges the result into ~/.graphify/global-graph.json under the --as tag.
|
|
50
|
+
execFileSync(
|
|
51
|
+
'graphify',
|
|
52
|
+
[ 'extract', repoPath, '--out', path.join(buildDir, name), '--global', '--as', name, '--code-only' ],
|
|
53
|
+
{ stdio: 'inherit' }
|
|
54
|
+
)
|
|
48
55
|
built.push(name)
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
const
|
|
52
|
-
console.log(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const manifest = {
|
|
56
|
-
builtAt: new Date().toISOString(),
|
|
57
|
-
repos: built
|
|
58
|
-
}
|
|
59
|
-
fs.writeFileSync(path.join(graphDir, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\n')
|
|
60
|
-
console.log(`drawbridge-agents-graph: built graph from ${ built.length } repo(s)`)
|
|
58
|
+
const globalGraph = path.join(os.homedir(), '.graphify', 'global-graph.json')
|
|
59
|
+
console.log(`drawbridge-agents-graph: built cross-repo graph from ${ built.length } repo(s)`)
|
|
60
|
+
console.log(` global graph: ${ globalGraph }`)
|
|
61
|
+
console.log(' query it: graphify query "<question>" --graph ' + globalGraph)
|
|
@@ -48,11 +48,7 @@ if (!has('graphify')) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
console.warn('drawbridge-agents-sync: `graphify install` (MCP registration) failed — run it manually.')
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
console.log('drawbridge-agents-sync: graphify runtime ready')
|
|
51
|
+
// Note: we deliberately do NOT run `graphify install` — it writes a graphify section into the
|
|
52
|
+
// repo's CLAUDE.md and a PreToolUse hook, which would mutate a committed file and clash with the
|
|
53
|
+
// shared CLAUDE.md. Agents use the graphify CLI directly (see conventions/graphify.md).
|
|
54
|
+
console.log('drawbridge-agents-sync: graphify runtime ready (run `npx drawbridge-agents-graph` to build the graph)')
|
package/conventions/graphify.md
CHANGED
|
@@ -6,17 +6,18 @@ shared packages — built by [Graphify](https://github.com/Graphify-Labs/graphif
|
|
|
6
6
|
## Query the graph before grepping across repos
|
|
7
7
|
|
|
8
8
|
When you need to trace behaviour that spans repos (api ↔ sync ↔ stripe ↔ app-web, who emits an
|
|
9
|
-
event, what depends on a package), **query the graph instead of grepping 16 directories**.
|
|
10
|
-
|
|
9
|
+
event, what depends on a package), **query the graph instead of grepping 16 directories**. The
|
|
10
|
+
cross-repo graph lives at `~/.graphify/global-graph.json`; point the CLI at it with `--graph`:
|
|
11
11
|
|
|
12
12
|
```sh
|
|
13
|
-
graphify query "what connects sync change streams to the billing meter?"
|
|
14
|
-
graphify path "drawbridge-app-web" "drawbridge-stripe"
|
|
15
|
-
graphify explain "closeDraw"
|
|
13
|
+
graphify query "what connects sync change streams to the billing meter?" --graph ~/.graphify/global-graph.json
|
|
14
|
+
graphify path "drawbridge-app-web" "drawbridge-stripe" --graph ~/.graphify/global-graph.json
|
|
15
|
+
graphify explain "closeDraw" --graph ~/.graphify/global-graph.json
|
|
16
|
+
graphify affected "closeDraw" --graph ~/.graphify/global-graph.json
|
|
16
17
|
```
|
|
17
18
|
|
|
18
|
-
The graph spans all sibling repos
|
|
19
|
-
|
|
19
|
+
The graph spans all sibling repos (code, via local AST). A semantic build additionally pulls in
|
|
20
|
+
`drawbridge-docs` and richer INFERRED edges — see "Refreshing it".
|
|
20
21
|
|
|
21
22
|
## Refreshing it
|
|
22
23
|
|
|
@@ -27,11 +28,15 @@ rebuild it:
|
|
|
27
28
|
npx drawbridge-agents-graph
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
This re-extracts every repo and
|
|
31
|
-
when tracked source has changed since the last build.
|
|
31
|
+
This re-extracts every repo (code-only, no API key) and merges them into the global graph. The
|
|
32
|
+
drift-check hook nudges when tracked source has changed since the last build. For a semantic
|
|
33
|
+
build that also indexes docs, run `graphify extract <repo> --global --as <repo>` with an LLM
|
|
34
|
+
backend / API key set (slower, costs LLM calls).
|
|
32
35
|
|
|
33
36
|
## Runtime
|
|
34
37
|
|
|
35
38
|
Graphify is a per-machine Python tool; `npm run sync` installs it automatically (see the sync
|
|
36
|
-
preflight
|
|
37
|
-
|
|
39
|
+
preflight — `uv tool install graphifyy`). Set `DRAWBRIDGE_SKIP_GRAPHIFY=1` to skip in CI/headless
|
|
40
|
+
environments. The MCP server (`graphify-mcp <graph.json>`) is available if you prefer it, but is
|
|
41
|
+
**not** auto-registered — `graphify install` would rewrite CLAUDE.md, which we keep managed by
|
|
42
|
+
this package.
|
package/graph/README.md
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
# Family knowledge graph
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
(
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
The cross-repo knowledge graph is built by `npx drawbridge-agents-graph` (`bin/graph.js`), which
|
|
4
|
+
runs [Graphify](https://github.com/Graphify-Labs/graphify) headless AST extraction over every
|
|
5
|
+
`drawbridge-*` repo and merges each into the **global** graph at
|
|
6
|
+
`~/.graphify/global-graph.json` (per machine, not committed).
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Both are regenerated by the build script; they are gitignored until the first build populates
|
|
13
|
-
them. See `conventions/graphify.md` for how agents query and refresh the graph.
|
|
8
|
+
That global graph is what agents query — see `conventions/graphify.md`. There are no committed
|
|
9
|
+
artifacts in this directory; it holds this README only. Per-repo extraction output is redirected
|
|
10
|
+
to `~/.graphify/build/` so it never litters the source repos.
|
package/hooks/drift-check.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// Blocks (must fix) on unresolved @story/@doc tags; nudges (non-blocking) on a stale graph or
|
|
4
4
|
// likely doc drift. Gated so it never fires on trivial turns. See conventions/docs-linkage.md.
|
|
5
5
|
const fs = require('fs')
|
|
6
|
+
const os = require('os')
|
|
6
7
|
const path = require('path')
|
|
7
8
|
const { execFileSync } = require('child_process')
|
|
8
9
|
|
|
@@ -69,14 +70,12 @@ const run = () => {
|
|
|
69
70
|
// 2. Graph freshness (non-blocking nudge) — a full re-extract is expensive, so alert rather
|
|
70
71
|
// than block on every edit turn. Flip to block() if you want it enforced hard.
|
|
71
72
|
if (!skipGraph) {
|
|
72
|
-
const
|
|
73
|
+
const globalGraph = path.join(os.homedir(), '.graphify', 'global-graph.json')
|
|
73
74
|
let builtAt = 0
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
builtAt = 0
|
|
79
|
-
}
|
|
75
|
+
try {
|
|
76
|
+
builtAt = fs.statSync(globalGraph).mtimeMs
|
|
77
|
+
} catch (error) {
|
|
78
|
+
builtAt = 0
|
|
80
79
|
}
|
|
81
80
|
const stale = changedSource.some((file) => {
|
|
82
81
|
try {
|
package/package.json
CHANGED