@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 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` extracts every
90
- `drawbridge-*` repo plus `drawbridge-docs` and the shared packages into one queryable graph.
91
- Agents query it (via the graphify MCP) instead of grepping. The runtime is a per-machine
92
- Python tool — `npm run sync` installs it automatically (`bin/preflight-graphify.js`); set
93
- `DRAWBRIDGE_SKIP_GRAPHIFY=1` to skip in CI/headless. First-run note: confirm graphify's exact
94
- `extract` / `merge-graphs` / `install` flags against the installed tool (see `bin/graph.js`).
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 graphify MCP is delivered via the consumer's `.mcp.json` (already gitignored).
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: extracts every drawbridge-* repo (plus drawbridge-docs and
3
- // the shared @drawbridge/* packages) into graphify's registry, merges them into
4
- // graph/merged.json, and writes graph/manifest.json (which the drift hook reads for staleness).
5
- // Requires the graphify runtime (npm run sync installs it). See conventions/graphify.md.
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
- // NOTE: the exact graphify subcommand flags (extract/merge-graphs) should be confirmed against
8
- // the installed tool the first time this runs; adjust if graphify's CLI differs.
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(graphDir, { recursive: true })
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
- execFileSync('graphify', [ 'extract', repoPath, '--global', '--as', name ], { stdio: 'inherit' })
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 mergedPath = path.join(graphDir, 'merged.json')
52
- console.log(' merge -> graph/merged.json')
53
- execFileSync('graphify', [ 'merge-graphs', '--global', '--out', mergedPath ], { stdio: 'inherit' })
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
- // Register the MCP server with the local assistant (idempotent).
52
- try {
53
- execFileSync('graphify', [ 'install' ], { stdio: 'inherit' })
54
- } catch (error) {
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)')
@@ -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**. It
10
- is exposed as an MCP server; you can also use the CLI:
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 plus `drawbridge-docs` and the `@drawbridge/*` packages, so a
19
- query resolves across the code **and** the specs/contracts layer.
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 rebuilds the merged graph. The drift-check hook will remind you
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). If it is ever missing, the drift hook blocks with install instructions — the runtime
37
- is required, not optional (set `DRAWBRIDGE_SKIP_GRAPHIFY=1` only in CI/headless environments).
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
- Generated artifacts do not edit by hand. Produced by `npx drawbridge-agents-graph`
4
- (`bin/graph.js`), which extracts every `drawbridge-*` repo plus `drawbridge-docs` and the shared
5
- `@drawbridge/*` packages into a single [Graphify](https://github.com/Graphify-Labs/graphify)
6
- knowledge graph.
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
- - `merged.json` the merged, queryable graph (served via the graphify MCP).
9
- - `manifest.json` `{ builtAt, repos }`; the drift-check hook reads `builtAt` to tell when the
10
- graph is stale relative to changed source.
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.
@@ -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 manifestPath = path.join(packageRoot, 'graph', 'manifest.json')
73
+ const globalGraph = path.join(os.homedir(), '.graphify', 'global-graph.json')
73
74
  let builtAt = 0
74
- if (fs.existsSync(manifestPath)) {
75
- try {
76
- builtAt = Date.parse(JSON.parse(fs.readFileSync(manifestPath, 'utf8')).builtAt) || 0
77
- } catch (error) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawbridge/drawbridge-agents",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Shared agent-instruction content (rules, code style, conventions) for the drawbridge-* monorepo.",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {