@drawbridge/drawbridge-agents 0.1.2 → 0.1.4
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-template/settings.json +14 -0
- package/.root-template/.mcp.json +4 -0
- package/README.md +32 -29
- package/bin/graph.js +5 -1
- package/bin/sync-claude.js +33 -45
- package/conventions/superpowers-docs.md +5 -5
- package/package.json +1 -2
- /package/{skills → .claude-template/skills}/drawbridge-asana-ship-handoff/SKILL.md +0 -0
- /package/{skills → .claude-template/skills}/drawbridge-explore-ecosystem/SKILL.md +0 -0
- /package/{skills → .claude-template/skills}/drawbridge-record-contract/SKILL.md +0 -0
- /package/{skills → .claude-template/skills}/drawbridge-ship-feature/SKILL.md +0 -0
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"../drawbridge-redis",
|
|
26
26
|
"../drawbridge-share",
|
|
27
27
|
"../drawbridge-shopify",
|
|
28
|
+
"../drawbridge-shopify-app",
|
|
28
29
|
"../drawbridge-stripe",
|
|
29
30
|
"../drawbridge-sync",
|
|
30
31
|
"../drawbridge-telemetry",
|
|
@@ -32,5 +33,18 @@
|
|
|
32
33
|
"../drawbridge-webhooks",
|
|
33
34
|
"../drawbridge-website"
|
|
34
35
|
]
|
|
36
|
+
},
|
|
37
|
+
"hooks": {
|
|
38
|
+
"Stop": [
|
|
39
|
+
{
|
|
40
|
+
"matcher": "",
|
|
41
|
+
"hooks": [
|
|
42
|
+
{
|
|
43
|
+
"type": "command",
|
|
44
|
+
"command": "node ./node_modules/@drawbridge/drawbridge-agents/hooks/drift-check.js"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
]
|
|
35
49
|
}
|
|
36
50
|
}
|
package/.root-template/.mcp.json
CHANGED
package/README.md
CHANGED
|
@@ -19,16 +19,17 @@ conventions/ ← canonical, agent-neutral content (@-imported int
|
|
|
19
19
|
claude/
|
|
20
20
|
CLAUDE.md ← aggregator — @-imports every conventions/*.md
|
|
21
21
|
|
|
22
|
-
.claude-template/ ← mirrored into each consumer repo
|
|
23
|
-
settings.json ←
|
|
22
|
+
.claude-template/ ← the complete shared .claude/, mirrored into each consumer repo
|
|
23
|
+
settings.json ← permissions, additionalDirectories, drift-check Stop hook
|
|
24
|
+
skills/ ← shared skills (drawbridge-ship-feature, -asana-ship-handoff, ...)
|
|
24
25
|
hooks/ agents/ commands/
|
|
25
26
|
|
|
26
27
|
.root-template/ ← mirrored into each consumer repo's root
|
|
27
|
-
.mcp.json ← project-level MCP servers (
|
|
28
|
+
.mcp.json ← project-level MCP servers (Sentry, Asana)
|
|
28
29
|
.editorconfig ← family-wide editor defaults (tabs, lf, utf-8)
|
|
29
30
|
|
|
30
31
|
bin/
|
|
31
|
-
sync-claude.js ← drawbridge-agents-sync — mirrors templates +
|
|
32
|
+
sync-claude.js ← drawbridge-agents-sync — mirrors templates + graphify preflight
|
|
32
33
|
graph.js ← drawbridge-agents-graph — builds the merged family knowledge graph
|
|
33
34
|
preflight-graphify.js ← ensures the graphify runtime is installed (called by sync)
|
|
34
35
|
|
|
@@ -36,13 +37,7 @@ scripts/
|
|
|
36
37
|
check-doc-links.js ← drawbridge-agents-check-docs — validates @story/@doc tags resolve
|
|
37
38
|
|
|
38
39
|
hooks/
|
|
39
|
-
drift-check.js ← Stop hook
|
|
40
|
-
|
|
41
|
-
skills/ ← shared skills, installed to user-level ~/.claude/skills on sync
|
|
42
|
-
drawbridge-asana-ship-handoff/ drawbridge-ship-feature/
|
|
43
|
-
drawbridge-explore-ecosystem/ drawbridge-record-contract/
|
|
44
|
-
|
|
45
|
-
graph/ ← generated (gitignored) merged.json + manifest.json; see graph/README.md
|
|
40
|
+
drift-check.js ← Stop hook (wired via .claude-template/settings.json)
|
|
46
41
|
```
|
|
47
42
|
|
|
48
43
|
## Consuming from a drawbridge-* repo
|
|
@@ -72,19 +67,23 @@ graph/ ← generated (gitignored) merged.json + manifest.js
|
|
|
72
67
|
"sync": ". \"$HOME/.nvm/nvm.sh\" && nvm use && npm prune && npm install && npx drawbridge-agents-sync"
|
|
73
68
|
```
|
|
74
69
|
|
|
75
|
-
On every `npm run sync`, this package mirrors:
|
|
76
|
-
- `.claude-template/` → consumer's `.claude/`
|
|
70
|
+
On every `npm run sync`, this package mirrors the single source of truth into the consumer:
|
|
71
|
+
- `.claude-template/` → consumer's `.claude/` — the **complete** shared setup: `settings.json`
|
|
72
|
+
(permissions, `additionalDirectories`, the drift-check Stop hook), plus `skills/`,
|
|
73
|
+
`agents/`, `commands/`, `hooks/`.
|
|
77
74
|
- `.root-template/` → consumer's repo root (`.mcp.json`, `.editorconfig`)
|
|
78
75
|
|
|
79
|
-
Paths that exist in the templates are **managed** (overwritten on each sync)
|
|
76
|
+
Paths that exist in the templates are **managed** (overwritten on each sync) — every repo ends
|
|
77
|
+
up with an identical `.claude/`. Only `settings.local.json` (each dev's personal overrides) and
|
|
78
|
+
any consumer-only files are left untouched.
|
|
80
79
|
|
|
81
80
|
Claude Code's `@` imports cascade — one import line resolves the whole tree under `claude/CLAUDE.md`.
|
|
82
81
|
|
|
83
82
|
## Ecosystem knowledge, graph, and drift checks
|
|
84
83
|
|
|
85
84
|
Beyond the conventions, this package gives agents cross-repo visibility and keeps code, docs,
|
|
86
|
-
and the knowledge graph from drifting.
|
|
87
|
-
|
|
85
|
+
and the knowledge graph from drifting. This package is the single source; each repo gets an
|
|
86
|
+
identical copy via the sync mirror (see "Delivery model").
|
|
88
87
|
|
|
89
88
|
- **Family knowledge graph (Graphify).** `npx drawbridge-agents-graph` runs code-only AST
|
|
90
89
|
extraction over every `drawbridge-*` repo and writes the merged graph to the committed, shared
|
|
@@ -99,24 +98,28 @@ reaches consumers without committing anything to them (see "Isolation").
|
|
|
99
98
|
reference/<file>#<anchor>` anchors (see `conventions/docs-linkage.md`).
|
|
100
99
|
`npx drawbridge-agents-check-docs` scans every repo and fails if any anchor no longer resolves
|
|
101
100
|
against `drawbridge-docs`.
|
|
102
|
-
- **Drift-check Stop hook.** `hooks/drift-check.js` runs at each task-turn end
|
|
103
|
-
|
|
104
|
-
anchor, and **nudges** (non-blocking) when the graph looks stale or docs may need updating.
|
|
105
|
-
skips plan-mode and turns with no source changes.
|
|
106
|
-
- **Shared skills.**
|
|
101
|
+
- **Drift-check Stop hook.** `hooks/drift-check.js` runs at each task-turn end, wired via the
|
|
102
|
+
drift-check `Stop` hook in the mirrored `.claude/settings.json`. It **blocks** on an unresolved
|
|
103
|
+
doc anchor, and **nudges** (non-blocking) when the graph looks stale or docs may need updating.
|
|
104
|
+
It skips plan-mode and turns with no source changes.
|
|
105
|
+
- **Shared skills.** Mirrored into every repo's `.claude/skills/` (from `.claude-template/skills/`):
|
|
107
106
|
`drawbridge-ship-feature` (verify → docs → graph → handoff), `drawbridge-asana-ship-handoff`,
|
|
108
107
|
`drawbridge-explore-ecosystem`, `drawbridge-record-contract`.
|
|
109
108
|
|
|
110
|
-
###
|
|
109
|
+
### Delivery model
|
|
111
110
|
|
|
112
|
-
|
|
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.
|
|
115
|
-
- The Stop hook is merged into `.claude/settings.local.json` (gitignored).
|
|
116
|
-
- Skills install to `~/.claude/skills/` (per-machine, outside any repo).
|
|
117
|
-
- The only in-repo footprint in consumers is inert `@story`/`@doc` source comments.
|
|
111
|
+
Every repo has an **identical, normalized** agent setup, all sourced from this one package:
|
|
118
112
|
|
|
119
|
-
|
|
113
|
+
- **`CLAUDE.md`** → one-line `@import` (live from `node_modules`).
|
|
114
|
+
- **`.claude/`** (settings.json + permissions + hook, skills, agents/commands/hooks) → **mirrored**
|
|
115
|
+
from `.claude-template/` and committed per repo.
|
|
116
|
+
- **`.mcp.json`, `.editorconfig`** → mirrored from `.root-template/` and committed per repo.
|
|
117
|
+
- Config files (`.claude/`, `.mcp.json`) are copied rather than imported because only markdown
|
|
118
|
+
(`CLAUDE.md`) supports `@import`; the mirror keeps the copies identical from one source.
|
|
119
|
+
- The package is a **devDependency** → never installed in production / on DigitalOcean.
|
|
120
|
+
- The knowledge graph is committed once in `drawbridge-docs/knowledge/graphs/`; the graphify
|
|
121
|
+
runtime + build cache are per-machine under `~/.graphify/` (gitignored). `graphify install`
|
|
122
|
+
(which edits `CLAUDE.md`) is never run.
|
|
120
123
|
|
|
121
124
|
## Updating a rule or shared `.claude/` file
|
|
122
125
|
|
package/bin/graph.js
CHANGED
|
@@ -70,7 +70,11 @@ for (const name of repos) {
|
|
|
70
70
|
)
|
|
71
71
|
// graphify still drops a graphify-out/ in the target repo despite --out; remove it so the
|
|
72
72
|
// build never dirties a source repo (the incremental cache lives under ~/.graphify/build).
|
|
73
|
-
|
|
73
|
+
const stray = path.join(repoPath, 'graphify-out')
|
|
74
|
+
if (fs.existsSync(stray)) {
|
|
75
|
+
if (fs.rmSync) fs.rmSync(stray, { recursive: true, force: true })
|
|
76
|
+
else fs.rmdirSync(stray, { recursive: true })
|
|
77
|
+
}
|
|
74
78
|
built.push(name)
|
|
75
79
|
}
|
|
76
80
|
|
package/bin/sync-claude.js
CHANGED
|
@@ -7,6 +7,13 @@ const { execFileSync } = require('child_process')
|
|
|
7
7
|
const consumerRoot = process.env.INIT_CWD || process.cwd()
|
|
8
8
|
const packageRoot = path.resolve(__dirname, '..')
|
|
9
9
|
|
|
10
|
+
// Recursive remove that works on Node 12+ (fs.rmSync is 14.14+).
|
|
11
|
+
const rmrf = (p) => {
|
|
12
|
+
if (!fs.existsSync(p)) return
|
|
13
|
+
if (fs.rmSync) fs.rmSync(p, { recursive: true, force: true })
|
|
14
|
+
else fs.rmdirSync(p, { recursive: true })
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
const copied = []
|
|
11
18
|
|
|
12
19
|
const mirror = (src, dst) => {
|
|
@@ -23,7 +30,9 @@ const mirror = (src, dst) => {
|
|
|
23
30
|
}
|
|
24
31
|
}
|
|
25
32
|
|
|
26
|
-
// 1. Mirror the
|
|
33
|
+
// 1. Mirror the single source of truth into the consumer. .claude-template holds the entire
|
|
34
|
+
// shared .claude/ setup (settings.json incl. permissions + the drift-check Stop hook, plus
|
|
35
|
+
// agents/commands/hooks/skills); .root-template holds root files (.mcp.json, .editorconfig).
|
|
27
36
|
const mirrorTemplates = () => {
|
|
28
37
|
const targets = [
|
|
29
38
|
{ src: path.join(packageRoot, '.claude-template'), dst: path.join(consumerRoot, '.claude'), required: true },
|
|
@@ -40,63 +49,42 @@ const mirrorTemplates = () => {
|
|
|
40
49
|
mirror(src, dst)
|
|
41
50
|
}
|
|
42
51
|
console.log(`drawbridge-agents-sync: ${ copied.length } file(s) mirrored`)
|
|
43
|
-
for (const p of copied) console.log(` ${ p }`)
|
|
44
52
|
}
|
|
45
53
|
|
|
46
|
-
// 2.
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
let settings = {}
|
|
53
|
-
if (fs.existsSync(settingsPath)) {
|
|
54
|
+
// 2. Migration cleanup from the previous delivery model: the drift hook used to be merged into
|
|
55
|
+
// the gitignored settings.local.json and skills installed to user-level ~/.claude/skills.
|
|
56
|
+
// Both now ship via the mirror above, so remove the old copies to avoid duplicates.
|
|
57
|
+
const migrateOldDelivery = () => {
|
|
58
|
+
const localSettings = path.join(consumerRoot, '.claude', 'settings.local.json')
|
|
59
|
+
if (fs.existsSync(localSettings)) {
|
|
54
60
|
try {
|
|
55
|
-
settings = JSON.parse(fs.readFileSync(
|
|
61
|
+
const settings = JSON.parse(fs.readFileSync(localSettings, 'utf8'))
|
|
62
|
+
if (settings.hooks && Array.isArray(settings.hooks.Stop)) {
|
|
63
|
+
settings.hooks.Stop = settings.hooks.Stop.filter((entry) =>
|
|
64
|
+
!(entry.hooks || []).some((hook) => typeof hook.command === 'string' && hook.command.includes('drawbridge-agents/hooks/drift-check.js'))
|
|
65
|
+
)
|
|
66
|
+
if (settings.hooks.Stop.length === 0) delete settings.hooks.Stop
|
|
67
|
+
if (Object.keys(settings.hooks).length === 0) delete settings.hooks
|
|
68
|
+
fs.writeFileSync(localSettings, JSON.stringify(settings, null, 2) + '\n')
|
|
69
|
+
}
|
|
56
70
|
} catch (error) {
|
|
57
|
-
|
|
58
|
-
return
|
|
71
|
+
// leave settings.local.json untouched on parse trouble
|
|
59
72
|
}
|
|
60
73
|
}
|
|
61
74
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
)
|
|
68
|
-
if (already) return
|
|
69
|
-
|
|
70
|
-
settings.hooks.Stop.push({
|
|
71
|
-
matcher: '',
|
|
72
|
-
hooks: [ { type: 'command', command } ]
|
|
73
|
-
})
|
|
74
|
-
fs.mkdirSync(path.dirname(settingsPath), { recursive: true })
|
|
75
|
-
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n')
|
|
76
|
-
console.log('drawbridge-agents-sync: drift-check Stop hook installed in .claude/settings.local.json')
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// 3. Install the shared skills to the user-level ~/.claude/skills/ (per-machine, so nothing is
|
|
80
|
-
// committed to any consumer repo). Only drawbridge-* skills are managed.
|
|
81
|
-
const installSkills = () => {
|
|
82
|
-
const src = path.join(packageRoot, 'skills')
|
|
83
|
-
if (!fs.existsSync(src)) return
|
|
84
|
-
const dst = path.join(os.homedir(), '.claude', 'skills')
|
|
85
|
-
let count = 0
|
|
86
|
-
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
87
|
-
if (!entry.isDirectory() || !entry.name.startsWith('drawbridge-')) continue
|
|
88
|
-
mirror(path.join(src, entry.name), path.join(dst, entry.name))
|
|
89
|
-
count += 1
|
|
75
|
+
const userSkills = path.join(os.homedir(), '.claude', 'skills')
|
|
76
|
+
if (fs.existsSync(userSkills)) {
|
|
77
|
+
for (const name of fs.readdirSync(userSkills)) {
|
|
78
|
+
if (name.startsWith('drawbridge-')) rmrf(path.join(userSkills, name))
|
|
79
|
+
}
|
|
90
80
|
}
|
|
91
|
-
if (count > 0) console.log(`drawbridge-agents-sync: ${ count } shared skill(s) installed to ~/.claude/skills/`)
|
|
92
81
|
}
|
|
93
82
|
|
|
94
|
-
//
|
|
83
|
+
// 3. Ensure the graphify runtime is present + reachable (hard-fails if it can't be).
|
|
95
84
|
const graphifyPreflight = () => {
|
|
96
85
|
execFileSync('node', [ path.join(packageRoot, 'bin', 'preflight-graphify.js') ], { stdio: 'inherit' })
|
|
97
86
|
}
|
|
98
87
|
|
|
99
88
|
mirrorTemplates()
|
|
100
|
-
|
|
101
|
-
installSkills()
|
|
89
|
+
migrateOldDelivery()
|
|
102
90
|
graphifyPreflight()
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# Superpowers working docs live in drawbridge-docs
|
|
2
2
|
|
|
3
3
|
All superpowers **plans** and **specs** — the outputs of the brainstorming / writing-plans /
|
|
4
|
-
spec workflows — live in one canonical place:
|
|
4
|
+
spec workflows — live in one canonical place, at the **root** of drawbridge-docs:
|
|
5
5
|
|
|
6
6
|
```
|
|
7
|
-
drawbridge-docs/
|
|
8
|
-
drawbridge-docs/
|
|
7
|
+
drawbridge-docs/superpowers/plans/YYYY-MM-DD-<slug>.md
|
|
8
|
+
drawbridge-docs/superpowers/specs/YYYY-MM-DD-<slug>.md
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
This is the **only** allowed home for these working docs. Rules:
|
|
12
12
|
|
|
13
|
-
- Do **not** create or keep `docs/superpowers/`, `docs/plans
|
|
13
|
+
- Do **not** create or keep superpowers plans/specs (or `docs/superpowers/`, `docs/plans/`)
|
|
14
14
|
inside any other repo. When you finalize a plan or spec, write it under
|
|
15
|
-
`../drawbridge-docs/
|
|
15
|
+
`../drawbridge-docs/superpowers/{plans,specs}/`, not the repo you're working in.
|
|
16
16
|
- When plan mode or a superpowers skill produces a plan/spec, the finalized document goes into
|
|
17
17
|
drawbridge-docs — regardless of which repo the work targets. Note the target repo in the doc.
|
|
18
18
|
- `.superpowers/` (brainstorm scratch — server state, HTML mockups) is ephemeral. **Never commit
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drawbridge/drawbridge-agents",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Shared agent-instruction content (rules, code style, conventions) for the drawbridge-* monorepo.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"publishConfig": {
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"bin",
|
|
24
24
|
"hooks",
|
|
25
25
|
"scripts",
|
|
26
|
-
"skills",
|
|
27
26
|
"graph",
|
|
28
27
|
"README.md"
|
|
29
28
|
],
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|