@drawbridge/drawbridge-agents 0.1.0 → 0.1.2

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,15 @@ 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 writes the merged graph to the committed, shared
91
+ location `drawbridge-docs/knowledge/graphs/global.json`. Agents query it with the `graphify` CLI
92
+ (e.g. `graphify query "…" --graph ../drawbridge-docs/knowledge/graphs/global.json`) instead of
93
+ grepping; refreshing is rebuild + commit in docs + `git pull` (no npm/publish cycle). The
94
+ runtime is a per-machine Python tool `npm run sync` installs it
95
+ (`bin/preflight-graphify.js`); set `DRAWBRIDGE_SKIP_GRAPHIFY=1` to skip in CI/headless. We
96
+ deliberately do **not** run `graphify install` (it would rewrite `CLAUDE.md`); the optional
97
+ `graphify-mcp` server is available if you prefer MCP.
95
98
  - **Docs linkage + validator.** Feature code carries `@story <domain>/<slug>` / `@doc
96
99
  reference/<file>#<anchor>` anchors (see `conventions/docs-linkage.md`).
97
100
  `npx drawbridge-agents-check-docs` scans every repo and fails if any anchor no longer resolves
@@ -107,7 +110,8 @@ reaches consumers without committing anything to them (see "Isolation").
107
110
  ### Isolation (nothing ships to DigitalOcean)
108
111
 
109
112
  - The package is a **devDependency** → not installed in production.
110
- - The graphify MCP is delivered via the consumer's `.mcp.json` (already gitignored).
113
+ - The graph and CLI are per-machine (`~/.graphify/`); nothing graph-related is written into the
114
+ consumer repo, and `graphify install` (which edits `CLAUDE.md`) is never run.
111
115
  - The Stop hook is merged into `.claude/settings.local.json` (gitignored).
112
116
  - Skills install to `~/.claude/skills/` (per-machine, outside any repo).
113
117
  - The only in-repo footprint in consumers is inert `@story`/`@doc` source comments.
package/bin/graph.js CHANGED
@@ -1,18 +1,35 @@
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) into graphify's
4
+ // global graph, then copies it to drawbridge-docs/knowledge/graphs/global.json the committed,
5
+ // shared graph agents 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
- const familyRoot = path.resolve(packageRoot, '..')
15
+ const buildDir = path.join(os.homedir(), '.graphify', 'build')
16
+ const globalGraph = path.join(os.homedir(), '.graphify', 'global-graph.json')
17
+
18
+ // The family root is the directory that contains drawbridge-docs. Walk up from cwd so this works
19
+ // whether run from the agents repo or via npx from inside a consumer's node_modules.
20
+ const findFamilyRoot = () => {
21
+ let dir = process.env.INIT_CWD || process.cwd()
22
+ for (let i = 0; i < 8; i++) {
23
+ if (fs.existsSync(path.join(dir, 'drawbridge-docs'))) return dir
24
+ const parent = path.dirname(dir)
25
+ if (parent === dir) break
26
+ dir = parent
27
+ }
28
+ return path.resolve(packageRoot, '..')
29
+ }
30
+
31
+ const familyRoot = findFamilyRoot()
32
+ const docsGraph = path.join(familyRoot, 'drawbridge-docs', 'knowledge', 'graphs', 'global.json')
16
33
 
17
34
  // The canonical family list lives in the shared settings template — single source of truth.
18
35
  const settings = JSON.parse(fs.readFileSync(path.join(packageRoot, '.claude-template', 'settings.json'), 'utf8'))
@@ -34,7 +51,7 @@ if (!hasGraphify()) {
34
51
  process.exit(1)
35
52
  }
36
53
 
37
- fs.mkdirSync(graphDir, { recursive: true })
54
+ fs.mkdirSync(buildDir, { recursive: true })
38
55
 
39
56
  const built = []
40
57
  for (const name of repos) {
@@ -44,17 +61,24 @@ for (const name of repos) {
44
61
  continue
45
62
  }
46
63
  console.log(` extract ${ name }`)
47
- execFileSync('graphify', [ 'extract', repoPath, '--global', '--as', name ], { stdio: 'inherit' })
64
+ // --out redirects the per-repo graphify-out/ away from the repo (keeps it clean);
65
+ // --global merges the result into ~/.graphify/global-graph.json under the --as tag.
66
+ execFileSync(
67
+ 'graphify',
68
+ [ 'extract', repoPath, '--out', path.join(buildDir, name), '--global', '--as', name, '--code-only' ],
69
+ { stdio: 'inherit' }
70
+ )
71
+ // graphify still drops a graphify-out/ in the target repo despite --out; remove it so the
72
+ // build never dirties a source repo (the incremental cache lives under ~/.graphify/build).
73
+ fs.rmSync(path.join(repoPath, 'graphify-out'), { recursive: true, force: true })
48
74
  built.push(name)
49
75
  }
50
76
 
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' })
77
+ // Publish the merged global graph to the committed, shared location in drawbridge-docs.
78
+ fs.mkdirSync(path.dirname(docsGraph), { recursive: true })
79
+ fs.copyFileSync(globalGraph, docsGraph)
54
80
 
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)`)
81
+ console.log(`drawbridge-agents-graph: built cross-repo graph from ${ built.length } repo(s)`)
82
+ console.log(` written to: ${ docsGraph }`)
83
+ console.log(' commit it in drawbridge-docs so the team shares one graph, then: git pull')
84
+ console.log(' query it: graphify query "<question>" --graph ' + docsGraph)
@@ -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)')
package/claude/CLAUDE.md CHANGED
@@ -13,4 +13,6 @@
13
13
  @../conventions/sentry-sdk.md
14
14
  @../conventions/app-web-forms.md
15
15
  @../conventions/docs-linkage.md
16
+ @../conventions/superpowers-docs.md
17
+ @../conventions/git-branching.md
16
18
  @../conventions/graphify.md
@@ -0,0 +1,19 @@
1
+ # Branch naming (gitflow)
2
+
3
+ Branches use the **full gitflow prefixes, always spelled out**. Never use abbreviations.
4
+
5
+ | Prefix | Use |
6
+ | --- | --- |
7
+ | `feature/<name>` | New features / changes (branched from `develop`) |
8
+ | `bugfix/<name>` | Non-urgent bug fixes |
9
+ | `hotfix/<name>` | Urgent production fixes (branched from `main`) |
10
+ | `release/<version>` | Release preparation |
11
+ | `chore/<name>` | Maintenance — dependency bumps, config, cleanup |
12
+ | `support/<name>` | Long-lived support branches |
13
+
14
+ - **Never** abbreviate: no `feat/`, `fix/`, `ci/`, `docs/`, `refactor/`, etc. Use the full word
15
+ (`feature/`, `bugfix/`, `chore/`, …).
16
+ - `<name>` is a short kebab-case description (e.g. `feature/ecosystem-knowledge-graphify`,
17
+ `chore/agents-devdep`).
18
+ - Branch from `develop` for normal work (see the integration-branch convention); `main`-only
19
+ repos like `drawbridge-docs` branch from `main`.
@@ -6,32 +6,40 @@ 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 is committed in drawbridge-docs at
11
+ `drawbridge-docs/knowledge/graphs/global.json` — a sibling of every repo, so point the CLI at it:
11
12
 
12
13
  ```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"
14
+ graphify query "what connects sync change streams to the billing meter?" --graph ../drawbridge-docs/knowledge/graphs/global.json
15
+ graphify path "drawbridge-app-web" "drawbridge-stripe" --graph ../drawbridge-docs/knowledge/graphs/global.json
16
+ graphify explain "closeDraw" --graph ../drawbridge-docs/knowledge/graphs/global.json
17
+ graphify affected "closeDraw" --graph ../drawbridge-docs/knowledge/graphs/global.json
16
18
  ```
17
19
 
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.
20
+ `git pull` in drawbridge-docs gets you the current shared graph. It spans all sibling repos
21
+ (code, via local AST); a semantic build additionally pulls in doc prose and richer INFERRED
22
+ edges — see "Refreshing it".
20
23
 
21
24
  ## Refreshing it
22
25
 
23
- The graph is as fresh as the last build. After a change that alters cross-repo structure,
24
- rebuild it:
26
+ The graph is as fresh as the last committed build. After a change that alters cross-repo
27
+ structure, rebuild and commit it:
25
28
 
26
29
  ```sh
27
- npx drawbridge-agents-graph
30
+ npx drawbridge-agents-graph # rebuilds -> drawbridge-docs/knowledge/graphs/global.json
31
+ cd ../drawbridge-docs && git add knowledge/graphs && git commit -m "chore: refresh knowledge graph"
28
32
  ```
29
33
 
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.
34
+ Other developers just `git pull` drawbridge-docs. The drift-check hook nudges when tracked
35
+ source has changed since the committed graph was last built. For a semantic build that also
36
+ indexes docs, run `graphify extract <repo> --global --as <repo>` with an LLM backend / API key
37
+ set (slower, costs LLM calls).
32
38
 
33
39
  ## Runtime
34
40
 
35
41
  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).
42
+ preflight `uv tool install graphifyy`). Set `DRAWBRIDGE_SKIP_GRAPHIFY=1` to skip in CI/headless
43
+ environments. The MCP server (`graphify-mcp <graph.json>`) is available if you prefer it, but is
44
+ **not** auto-registered — `graphify install` would rewrite CLAUDE.md, which we keep managed by
45
+ this package.
@@ -0,0 +1,19 @@
1
+ # Superpowers working docs live in drawbridge-docs
2
+
3
+ All superpowers **plans** and **specs** — the outputs of the brainstorming / writing-plans /
4
+ spec workflows — live in one canonical place:
5
+
6
+ ```
7
+ drawbridge-docs/docs/superpowers/plans/YYYY-MM-DD-<slug>.md
8
+ drawbridge-docs/docs/superpowers/specs/YYYY-MM-DD-<slug>.md
9
+ ```
10
+
11
+ This is the **only** allowed home for these working docs. Rules:
12
+
13
+ - Do **not** create or keep `docs/superpowers/`, `docs/plans/`, or any plan/spec working docs
14
+ inside any other repo. When you finalize a plan or spec, write it under
15
+ `../drawbridge-docs/docs/superpowers/{plans,specs}/`, not the repo you're working in.
16
+ - When plan mode or a superpowers skill produces a plan/spec, the finalized document goes into
17
+ drawbridge-docs — regardless of which repo the work targets. Note the target repo in the doc.
18
+ - `.superpowers/` (brainstorm scratch — server state, HTML mockups) is ephemeral. **Never commit
19
+ it**; it belongs in `.gitignore`.
package/graph/README.md CHANGED
@@ -1,13 +1,14 @@
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 writes the merged graph to the **committed, shared** location:
7
6
 
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.
7
+ ```
8
+ drawbridge-docs/knowledge/graphs/global.json
9
+ ```
11
10
 
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.
11
+ That committed file is what agents query (`--graph ../drawbridge-docs/knowledge/graphs/global.json`)
12
+ and is shared via `git pull` — see `conventions/graphify.md`. There are no graph artifacts in
13
+ this package directory; per-repo extraction output is redirected to `~/.graphify/build/` so it
14
+ never litters the source repos.
@@ -69,14 +69,13 @@ const run = () => {
69
69
  // 2. Graph freshness (non-blocking nudge) — a full re-extract is expensive, so alert rather
70
70
  // than block on every edit turn. Flip to block() if you want it enforced hard.
71
71
  if (!skipGraph) {
72
- const manifestPath = path.join(packageRoot, 'graph', 'manifest.json')
72
+ // The shared graph is committed in drawbridge-docs (a sibling of this repo).
73
+ const docsGraph = path.join(path.dirname(cwd), 'drawbridge-docs', 'knowledge', 'graphs', 'global.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(docsGraph).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.2",
4
4
  "description": "Shared agent-instruction content (rules, code style, conventions) for the drawbridge-* monorepo.",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {