@dougharness/cli 1.0.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/LICENSE +21 -0
- package/dist/ablate.d.ts +96 -0
- package/dist/ablate.js +440 -0
- package/dist/ablate.js.map +1 -0
- package/dist/apply.d.ts +2 -0
- package/dist/apply.js +19 -0
- package/dist/apply.js.map +1 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +80 -0
- package/dist/bin.js.map +1 -0
- package/dist/board-page.d.ts +15 -0
- package/dist/board-page.js +27 -0
- package/dist/board-page.js.map +1 -0
- package/dist/board-serve-process.d.ts +24 -0
- package/dist/board-serve-process.js +227 -0
- package/dist/board-serve-process.js.map +1 -0
- package/dist/board-serve.d.ts +9 -0
- package/dist/board-serve.js +302 -0
- package/dist/board-serve.js.map +1 -0
- package/dist/board.d.ts +6 -0
- package/dist/board.js +515 -0
- package/dist/board.js.map +1 -0
- package/dist/detect/fs.d.ts +6 -0
- package/dist/detect/fs.js +50 -0
- package/dist/detect/fs.js.map +1 -0
- package/dist/detect/index.d.ts +3 -0
- package/dist/detect/index.js +13 -0
- package/dist/detect/index.js.map +1 -0
- package/dist/detect/node.d.ts +3 -0
- package/dist/detect/node.js +179 -0
- package/dist/detect/node.js.map +1 -0
- package/dist/detect/python.d.ts +2 -0
- package/dist/detect/python.js +388 -0
- package/dist/detect/python.js.map +1 -0
- package/dist/detect/repo.d.ts +2 -0
- package/dist/detect/repo.js +102 -0
- package/dist/detect/repo.js.map +1 -0
- package/dist/detect/types.d.ts +98 -0
- package/dist/detect/types.js +2 -0
- package/dist/detect/types.js.map +1 -0
- package/dist/diff.d.ts +12 -0
- package/dist/diff.js +105 -0
- package/dist/diff.js.map +1 -0
- package/dist/generate/agents.d.ts +19 -0
- package/dist/generate/agents.js +184 -0
- package/dist/generate/agents.js.map +1 -0
- package/dist/generate/claude-md.d.ts +9 -0
- package/dist/generate/claude-md.js +111 -0
- package/dist/generate/claude-md.js.map +1 -0
- package/dist/generate/config.d.ts +51 -0
- package/dist/generate/config.js +155 -0
- package/dist/generate/config.js.map +1 -0
- package/dist/generate/proposal.d.ts +11 -0
- package/dist/generate/proposal.js +175 -0
- package/dist/generate/proposal.js.map +1 -0
- package/dist/generate/settings.d.ts +35 -0
- package/dist/generate/settings.js +213 -0
- package/dist/generate/settings.js.map +1 -0
- package/dist/generate/skills.d.ts +8 -0
- package/dist/generate/skills.js +264 -0
- package/dist/generate/skills.js.map +1 -0
- package/dist/init.d.ts +10 -0
- package/dist/init.js +69 -0
- package/dist/init.js.map +1 -0
- package/dist/trace.d.ts +9 -0
- package/dist/trace.js +106 -0
- package/dist/trace.js.map +1 -0
- package/node_modules/@dougharness/flow/.claude-plugin/plugin.json +10 -0
- package/node_modules/@dougharness/flow/LICENSE +21 -0
- package/node_modules/@dougharness/flow/agents/adversary-claude.md +33 -0
- package/node_modules/@dougharness/flow/agents/adversary.md +29 -0
- package/node_modules/@dougharness/flow/agents/implementer.md +23 -0
- package/node_modules/@dougharness/flow/agents/lead.md +35 -0
- package/node_modules/@dougharness/flow/agents/planner.md +70 -0
- package/node_modules/@dougharness/flow/agents/researcher.md +31 -0
- package/node_modules/@dougharness/flow/agents/reviewer.md +26 -0
- package/node_modules/@dougharness/flow/agents/verifier.md +24 -0
- package/node_modules/@dougharness/flow/lib/board.mjs +840 -0
- package/node_modules/@dougharness/flow/lib/code-index.mjs +629 -0
- package/node_modules/@dougharness/flow/lib/cost.mjs +392 -0
- package/node_modules/@dougharness/flow/lib/decisions.mjs +314 -0
- package/node_modules/@dougharness/flow/lib/embeddings.mjs +539 -0
- package/node_modules/@dougharness/flow/lib/land.mjs +219 -0
- package/node_modules/@dougharness/flow/lib/learn.mjs +742 -0
- package/node_modules/@dougharness/flow/lib/memory-import.mjs +145 -0
- package/node_modules/@dougharness/flow/lib/memory.mjs +1641 -0
- package/node_modules/@dougharness/flow/lib/models.mjs +148 -0
- package/node_modules/@dougharness/flow/lib/plan.mjs +773 -0
- package/node_modules/@dougharness/flow/lib/rehearse.mjs +825 -0
- package/node_modules/@dougharness/flow/lib/worktrees.mjs +215 -0
- package/node_modules/@dougharness/flow/package.json +19 -0
- package/node_modules/@dougharness/flow/scripts/board.mjs +260 -0
- package/node_modules/@dougharness/flow/scripts/cost.mjs +66 -0
- package/node_modules/@dougharness/flow/scripts/learn.mjs +161 -0
- package/node_modules/@dougharness/flow/scripts/memory.mjs +1274 -0
- package/node_modules/@dougharness/flow/scripts/plan.mjs +547 -0
- package/node_modules/@dougharness/flow/scripts/rehearse.mjs +129 -0
- package/node_modules/@dougharness/flow/skills/core-next/SKILL.md +92 -0
- package/node_modules/@dougharness/flow/skills/doug-approve/SKILL.md +15 -0
- package/node_modules/@dougharness/flow/skills/doug-decide/SKILL.md +26 -0
- package/node_modules/@dougharness/flow/skills/doug-implement/SKILL.md +22 -0
- package/node_modules/@dougharness/flow/skills/doug-learn/SKILL.md +20 -0
- package/node_modules/@dougharness/flow/skills/doug-next/SKILL.md +87 -0
- package/node_modules/@dougharness/flow/skills/doug-plan/SKILL.md +22 -0
- package/node_modules/@dougharness/flow/skills/doug-swarm/SKILL.md +55 -0
- package/node_modules/@dougharness/flow/skills/harness-fix/SKILL.md +85 -0
- package/node_modules/@dougharness/flow/skills/research/SKILL.md +41 -0
- package/node_modules/@dougharness/flow/skills/run-report/SKILL.md +51 -0
- package/node_modules/@dougharness/flow/skills/swarm-launch/SKILL.md +27 -0
- package/node_modules/@dougharness/flow/workflows/doug-implement.js +2687 -0
- package/node_modules/@dougharness/gates/.claude-plugin/plugin.json +10 -0
- package/node_modules/@dougharness/gates/LICENSE +21 -0
- package/node_modules/@dougharness/gates/hooks/hooks.json +184 -0
- package/node_modules/@dougharness/gates/lib/agent-context.mjs +111 -0
- package/node_modules/@dougharness/gates/lib/anchor.mjs +110 -0
- package/node_modules/@dougharness/gates/lib/baseline.mjs +160 -0
- package/node_modules/@dougharness/gates/lib/bash-rules.mjs +1522 -0
- package/node_modules/@dougharness/gates/lib/block-ledger.mjs +127 -0
- package/node_modules/@dougharness/gates/lib/checkpoint.mjs +97 -0
- package/node_modules/@dougharness/gates/lib/config.mjs +168 -0
- package/node_modules/@dougharness/gates/lib/evidence.mjs +59 -0
- package/node_modules/@dougharness/gates/lib/glob.mjs +86 -0
- package/node_modules/@dougharness/gates/lib/io.mjs +91 -0
- package/node_modules/@dougharness/gates/lib/paths.mjs +101 -0
- package/node_modules/@dougharness/gates/lib/proposals.mjs +201 -0
- package/node_modules/@dougharness/gates/lib/run.mjs +147 -0
- package/node_modules/@dougharness/gates/lib/scope.mjs +117 -0
- package/node_modules/@dougharness/gates/lib/secret-rules.mjs +268 -0
- package/node_modules/@dougharness/gates/lib/state.mjs +114 -0
- package/node_modules/@dougharness/gates/lib/trace.mjs +196 -0
- package/node_modules/@dougharness/gates/package.json +17 -0
- package/node_modules/@dougharness/gates/scripts/edit-loop.mjs +39 -0
- package/node_modules/@dougharness/gates/scripts/format-on-edit.mjs +45 -0
- package/node_modules/@dougharness/gates/scripts/guard-bash.mjs +32 -0
- package/node_modules/@dougharness/gates/scripts/protect-paths.mjs +49 -0
- package/node_modules/@dougharness/gates/scripts/reanchor.mjs +81 -0
- package/node_modules/@dougharness/gates/scripts/research-cap.mjs +295 -0
- package/node_modules/@dougharness/gates/scripts/secret-scan.mjs +26 -0
- package/node_modules/@dougharness/gates/scripts/session-start-baseline.mjs +57 -0
- package/node_modules/@dougharness/gates/scripts/statusline.mjs +133 -0
- package/node_modules/@dougharness/gates/scripts/stop-gate.mjs +1422 -0
- package/node_modules/@dougharness/gates/scripts/trace.mjs +75 -0
- package/package.json +33 -0
- package/templates/board-app.js +533 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
// Merges Doug's hooks and a minimal permission allowlist into an existing .claude/settings.json.
|
|
5
|
+
// The hook wiring itself is derived from plugins/doug-gates/hooks/hooks.json (see dougHooks below), not
|
|
6
|
+
// hardcoded here, so the two can no longer drift (card generated-settings-wiring-drift). Hook commands point
|
|
7
|
+
// at the vendored copy under .doug/hooks so the project is self-contained.
|
|
8
|
+
export const HOOK_MARK = "\"$CLAUDE_PROJECT_DIR/.doug/hooks/scripts/";
|
|
9
|
+
export const STATUSLINE_COMMAND = "node .doug/hooks/scripts/statusline.mjs";
|
|
10
|
+
// Card no-nested-agents-gate: Claude Code's per-project subagent spawn depth (settings.md, sub-agents.md).
|
|
11
|
+
export const SUBAGENT_DEPTH_ENV = "CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH";
|
|
12
|
+
function cmd(script) {
|
|
13
|
+
return `node "$CLAUDE_PROJECT_DIR/.doug/hooks/scripts/${script}.mjs"`;
|
|
14
|
+
}
|
|
15
|
+
// Locates the gates package (scripts + lib + hooks.json) to vendor into the project.
|
|
16
|
+
export function gatesSourceDir() {
|
|
17
|
+
const require = createRequire(import.meta.url);
|
|
18
|
+
const pkg = require.resolve("@dougharness/gates/package.json");
|
|
19
|
+
return dirname(pkg);
|
|
20
|
+
}
|
|
21
|
+
// The plugin's command form: node "${CLAUDE_PLUGIN_ROOT}/scripts/<name>.mjs".
|
|
22
|
+
const PLUGIN_COMMAND_RE = /^node "\$\{CLAUDE_PLUGIN_ROOT\}\/scripts\/([A-Za-z0-9_-]+)\.mjs"$/;
|
|
23
|
+
// Rewrites one plugin-form command into the vendored form a generated project actually runs (cmd()'s shape).
|
|
24
|
+
// A command that isn't the plugin form throws rather than being dropped or copied through verbatim: a literal
|
|
25
|
+
// ${CLAUDE_PLUGIN_ROOT} in a project's settings.json would be a broken hook, so a future hooks.json entry that
|
|
26
|
+
// doesn't fit this shape has to be loud, not silently absent.
|
|
27
|
+
function vendoredCommand(pluginCommand, event, index, path) {
|
|
28
|
+
const m = PLUGIN_COMMAND_RE.exec(pluginCommand);
|
|
29
|
+
if (!m) {
|
|
30
|
+
throw new Error(`doug init: the ${event} hook ${index} in ${path} command is not the plugin form ` +
|
|
31
|
+
`(node "\${CLAUDE_PLUGIN_ROOT}/scripts/<name>.mjs"): ${JSON.stringify(pluginCommand)}. ` +
|
|
32
|
+
`Fix the command in the gates package.`);
|
|
33
|
+
}
|
|
34
|
+
return cmd(m[1]);
|
|
35
|
+
}
|
|
36
|
+
// Renders a value for a "found X" error message. `undefined` reads as "absent" (JSON.stringify(undefined) is
|
|
37
|
+
// undefined, not a string, which produced the "...: undefined" gap this hardening fixes); everything else is
|
|
38
|
+
// its JSON text, so a string comes back quoted and a number or a stray object is unambiguous.
|
|
39
|
+
function describeValue(v) {
|
|
40
|
+
return v === undefined ? "absent" : JSON.stringify(v);
|
|
41
|
+
}
|
|
42
|
+
// Renders a value's shape for a "found X" message about structure (an array vs. an object vs. a primitive)
|
|
43
|
+
// rather than about one field's exact value - used where the message is about what kind of thing was found,
|
|
44
|
+
// not what it equals.
|
|
45
|
+
function describeShape(v) {
|
|
46
|
+
if (v === undefined)
|
|
47
|
+
return "undefined";
|
|
48
|
+
if (v === null)
|
|
49
|
+
return "null";
|
|
50
|
+
if (Array.isArray(v))
|
|
51
|
+
return "an array";
|
|
52
|
+
if (typeof v === "object")
|
|
53
|
+
return "an object";
|
|
54
|
+
return `${typeof v} ${JSON.stringify(v)}`;
|
|
55
|
+
}
|
|
56
|
+
// Reads and JSON-parses hooks.json, turning the two failures that aren't about the hooks shape itself (an
|
|
57
|
+
// unreadable file, invalid JSON) into a message that names the file and says what to do, instead of letting a
|
|
58
|
+
// raw fs or parser error reach bin.ts's generic "doug: <stack>" printer.
|
|
59
|
+
function readHooksJsonFile(path) {
|
|
60
|
+
let text;
|
|
61
|
+
try {
|
|
62
|
+
text = readFileSync(path, "utf8");
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
66
|
+
throw new Error(`doug init: cannot read ${path}: ${msg}. The @dougharness/gates package is incomplete; reinstall it.`);
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
return JSON.parse(text);
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
73
|
+
throw new Error(`doug init: ${path} is not valid JSON: ${msg}. Fix the file in the gates package.`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Derives the hook wiring a generated project gets from plugins/doug-gates/hooks/hooks.json, the same
|
|
77
|
+
// declaration the plugin itself runs from. Checked field by field (card generated-settings-wiring-drift): the
|
|
78
|
+
// two describe the same 8 events, the same groups in the same order, the same matchers, scripts, and timeouts.
|
|
79
|
+
// They differ in exactly one way that has to survive the derivation, plus three things that are legitimately
|
|
80
|
+
// out of its scope:
|
|
81
|
+
// 1. Command prefix: the plugin form points at "${CLAUDE_PLUGIN_ROOT}/scripts/<x>.mjs"; a generated project
|
|
82
|
+
// needs "$CLAUDE_PROJECT_DIR/.doug/hooks/scripts/<x>.mjs" (the vendored copy, so the project is
|
|
83
|
+
// self-contained). vendoredCommand() above performs this one rewrite and nothing else.
|
|
84
|
+
// 2. The status line is a settings key, not a hook. hooks.json declares no statusline hook and must not;
|
|
85
|
+
// STATUSLINE_COMMAND and the statusLine handling in mergeSettings stay outside this derivation.
|
|
86
|
+
// 3. permissions are settings-only and stay outside this derivation too.
|
|
87
|
+
// 4. No hook is excluded from a generated project today: every script hooks.json declares belongs in a
|
|
88
|
+
// generated project. If that ever stops being true, the exclusion has to be an explicit named list here,
|
|
89
|
+
// not a loosened comparison against hooks.json.
|
|
90
|
+
// 5. env (card no-nested-agents-gate: CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH) is settings-only too, like
|
|
91
|
+
// statusLine and permissions; it stays outside this derivation.
|
|
92
|
+
export function dougHooks(gatesDir = gatesSourceDir()) {
|
|
93
|
+
const path = join(gatesDir, "hooks/hooks.json");
|
|
94
|
+
const doc = readHooksJsonFile(path);
|
|
95
|
+
// The whole document not being an object (an array, a string, a number, ...) is a different problem from an
|
|
96
|
+
// object that merely lacks a "hooks" key, and needs its own message: describeShape(doc) would otherwise
|
|
97
|
+
// describe the missing property, not the document itself, and print the confusing "found undefined" this
|
|
98
|
+
// check exists to avoid.
|
|
99
|
+
if (doc === null || typeof doc !== "object" || Array.isArray(doc)) {
|
|
100
|
+
throw new Error(`doug init: ${path} is not a JSON object (found ${describeShape(doc)}); the file must have the shape ` +
|
|
101
|
+
`{ "hooks": { "<Event>": [ { "matcher"?: ..., "hooks": [ ... ] } ] } }.`);
|
|
102
|
+
}
|
|
103
|
+
const hooksVal = doc.hooks;
|
|
104
|
+
if (hooksVal === undefined || hooksVal === null || typeof hooksVal !== "object" || Array.isArray(hooksVal)) {
|
|
105
|
+
throw new Error(`doug init: ${path} has no "hooks" object (found ${describeShape(hooksVal)}); the file must have the shape ` +
|
|
106
|
+
`{ "hooks": { "<Event>": [ { "matcher"?: ..., "hooks": [ ... ] } ] } }.`);
|
|
107
|
+
}
|
|
108
|
+
const out = {};
|
|
109
|
+
for (const [event, groupsVal] of Object.entries(hooksVal)) {
|
|
110
|
+
if (!Array.isArray(groupsVal)) {
|
|
111
|
+
throw new Error(`doug init: ${path}'s "${event}" hook event is not an array (found ${describeShape(groupsVal)}); ` +
|
|
112
|
+
`each event must be an array of hook groups.`);
|
|
113
|
+
}
|
|
114
|
+
out[event] = groupsVal.map((groupVal, gi) => {
|
|
115
|
+
if (groupVal === null || typeof groupVal !== "object" || Array.isArray(groupVal)) {
|
|
116
|
+
throw new Error(`doug init: the "${event}" hook group ${gi} in ${path} is not an object (found ${describeShape(groupVal)}); ` +
|
|
117
|
+
`each group must be an object with a "hooks" array (and an optional "matcher").`);
|
|
118
|
+
}
|
|
119
|
+
const group = groupVal;
|
|
120
|
+
if (!Array.isArray(group.hooks)) {
|
|
121
|
+
throw new Error(`doug init: the "${event}" hook group ${gi} in ${path} has no "hooks" array (found ${describeShape(group.hooks)}); ` +
|
|
122
|
+
`each group must have a "hooks": [ ... ] array of hook objects.`);
|
|
123
|
+
}
|
|
124
|
+
const hooks = group.hooks.map((hookVal, hi) => {
|
|
125
|
+
if (hookVal === null || typeof hookVal !== "object" || Array.isArray(hookVal)) {
|
|
126
|
+
throw new Error(`doug init: the ${event} hook ${hi} in ${path} is not an object (found ${describeShape(hookVal)}).`);
|
|
127
|
+
}
|
|
128
|
+
const h = hookVal;
|
|
129
|
+
// Refuse rather than coerce: an absent type is not a command hook either, so a plugin field the
|
|
130
|
+
// generator doesn't know how to vendor never gets silently turned into one.
|
|
131
|
+
if (h.type !== "command") {
|
|
132
|
+
throw new Error(`doug init: the ${event} hook ${hi} in ${path} has type ${describeValue(h.type)} but only "command" hooks ` +
|
|
133
|
+
`can be vendored into a project; a prompt, agent, http, or mcp_tool hook has no script to copy. ` +
|
|
134
|
+
`Change the hook or add vendoring for that type.`);
|
|
135
|
+
}
|
|
136
|
+
if (typeof h.command !== "string") {
|
|
137
|
+
throw new Error(`doug init: the ${event} hook ${hi} in ${path} has no command string (found ${describeValue(h.command)}).`);
|
|
138
|
+
}
|
|
139
|
+
// Pass through, don't validate - this card's decision (hooks-json-read-hardening; the schema facts it's
|
|
140
|
+
// based on are in docs/research/hooks-json-read-hardening.md, promoted there on landing): every field
|
|
141
|
+
// the hook carries besides `command` rides along untouched, in hooks.json's key order, because the
|
|
142
|
+
// generator's job is translating a file the plugin already runs from, not policing it against a schema
|
|
143
|
+
// it doesn't fully know - Claude Code's handling of a key that isn't documented today is unverified,
|
|
144
|
+
// and dropping a documented optional field (timeout, if, statusMessage, once, args, async,
|
|
145
|
+
// asyncRewake, shell) would be exactly the mistranslation this card exists to remove. Spreading h
|
|
146
|
+
// before overwriting `command` keeps it at its original position rather than moving it to the end.
|
|
147
|
+
return { ...h, command: vendoredCommand(h.command, event, hi, path) };
|
|
148
|
+
});
|
|
149
|
+
// Pass through the group the same way: any extra key (e.g. `if`) survives untouched, and `hooks` is
|
|
150
|
+
// overwritten in place so it keeps hooks.json's own key order (matcher before hooks) rather than being
|
|
151
|
+
// rebuilt - which also keeps "absent stays absent": a matcher-less group here has no `matcher` key at
|
|
152
|
+
// all, never an explicit `"matcher": undefined`, because JSON has no way to declare one.
|
|
153
|
+
return { ...group, hooks };
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
function isDougEntry(e) {
|
|
159
|
+
return e.hooks.some((h) => h.command && h.command.includes(".doug/hooks/scripts/"));
|
|
160
|
+
}
|
|
161
|
+
export function permissionAllow(d, cfg) {
|
|
162
|
+
const out = new Set();
|
|
163
|
+
for (const c of Object.values(cfg.commands)) {
|
|
164
|
+
// "pnpm test" -> Bash(pnpm test *) so flags and file args are allowed.
|
|
165
|
+
out.add(`Bash(${c} *)`);
|
|
166
|
+
out.add(`Bash(${c})`);
|
|
167
|
+
}
|
|
168
|
+
if (d.node.packageManager) {
|
|
169
|
+
const pm = d.node.packageManager;
|
|
170
|
+
out.add(`Bash(${pm} exec *)`);
|
|
171
|
+
if (pm === "npm")
|
|
172
|
+
out.add("Bash(npx *)");
|
|
173
|
+
}
|
|
174
|
+
if (d.node.singleTestCommand) {
|
|
175
|
+
const bin = d.node.singleTestCommand.split(" <")[0];
|
|
176
|
+
out.add(`Bash(${bin} *)`);
|
|
177
|
+
}
|
|
178
|
+
if (d.python.present && d.python.singleTestCommand) {
|
|
179
|
+
const bin = d.python.singleTestCommand.split(" <")[0];
|
|
180
|
+
out.add(`Bash(${bin} *)`);
|
|
181
|
+
}
|
|
182
|
+
out.add("Bash(git status *)");
|
|
183
|
+
out.add("Bash(git diff *)");
|
|
184
|
+
out.add("Bash(git log *)");
|
|
185
|
+
return [...out];
|
|
186
|
+
}
|
|
187
|
+
export function mergeSettings(existing, d, cfg, gatesDir = gatesSourceDir()) {
|
|
188
|
+
const s = existing ? JSON.parse(JSON.stringify(existing)) : {};
|
|
189
|
+
s.hooks = s.hooks || {};
|
|
190
|
+
for (const [event, entries] of Object.entries(dougHooks(gatesDir))) {
|
|
191
|
+
const kept = (s.hooks[event] || []).filter((e) => !isDougEntry(e));
|
|
192
|
+
s.hooks[event] = [...kept, ...entries];
|
|
193
|
+
}
|
|
194
|
+
if (!s.statusLine || (typeof s.statusLine.command === "string" && s.statusLine.command.includes(".doug/hooks/scripts/statusline.mjs"))) {
|
|
195
|
+
s.statusLine = { type: "command", command: STATUSLINE_COMMAND };
|
|
196
|
+
}
|
|
197
|
+
s.permissions = s.permissions || {};
|
|
198
|
+
const allow = new Set(s.permissions.allow || []);
|
|
199
|
+
for (const rule of permissionAllow(d, cfg))
|
|
200
|
+
allow.add(rule);
|
|
201
|
+
s.permissions.allow = [...allow];
|
|
202
|
+
const deny = new Set(s.permissions.deny || []);
|
|
203
|
+
deny.add("Read(./.env)");
|
|
204
|
+
deny.add("Read(./.env.*)");
|
|
205
|
+
s.permissions.deny = [...deny];
|
|
206
|
+
// Treat a missing cfg.subagents (an older config.json) as the default 1.
|
|
207
|
+
const maxSpawnDepth = cfg.subagents ? cfg.subagents.maxSpawnDepth : 1;
|
|
208
|
+
if (maxSpawnDepth !== null) {
|
|
209
|
+
s.env = { ...(s.env || {}), [SUBAGENT_DEPTH_ENV]: String(maxSpawnDepth) };
|
|
210
|
+
}
|
|
211
|
+
return s;
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/generate/settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Detection } from "../detect/types.js";
|
|
2
|
+
import type { DougConfig } from "./config.js";
|
|
3
|
+
export interface SkillFile {
|
|
4
|
+
path: string;
|
|
5
|
+
content: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function generateSkills(d: Detection, cfg: DougConfig): SkillFile[];
|
|
8
|
+
export declare function isDougSkill(text: string): boolean;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { runScript } from "../detect/node.js";
|
|
2
|
+
import { AGENT_MARK } from "./agents.js";
|
|
3
|
+
const PROJECT_NOTES_HEADING = "## Project notes";
|
|
4
|
+
function bashPair(command) {
|
|
5
|
+
return [`Bash(${command} *)`, `Bash(${command})`];
|
|
6
|
+
}
|
|
7
|
+
// The permission tokens must come from the command text before its placeholder: a literal
|
|
8
|
+
// `<path/to/file.test.ts>` in a Bash rule can never match. Returns the joined prefix of tokens
|
|
9
|
+
// before the first token containing `<`, the whole command when there is no such token, or null
|
|
10
|
+
// when the command begins with the placeholder token.
|
|
11
|
+
function permissionPrefix(command) {
|
|
12
|
+
const tokens = command.split(/\s+/);
|
|
13
|
+
const idx = tokens.findIndex((t) => t.includes("<"));
|
|
14
|
+
if (idx === 0)
|
|
15
|
+
return null;
|
|
16
|
+
if (idx === -1)
|
|
17
|
+
return command;
|
|
18
|
+
return tokens.slice(0, idx).join(" ");
|
|
19
|
+
}
|
|
20
|
+
function firstScript(scripts, names) {
|
|
21
|
+
for (const name of names) {
|
|
22
|
+
if (Object.prototype.hasOwnProperty.call(scripts, name))
|
|
23
|
+
return name;
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
function renderSkill(spec) {
|
|
28
|
+
const lines = [];
|
|
29
|
+
lines.push("---");
|
|
30
|
+
lines.push(`name: ${spec.name}`);
|
|
31
|
+
lines.push(`description: ${JSON.stringify(spec.description)}`);
|
|
32
|
+
lines.push(`allowed-tools: ${spec.allowedTools}`);
|
|
33
|
+
if (spec.manualOnly)
|
|
34
|
+
lines.push("disable-model-invocation: true");
|
|
35
|
+
lines.push("metadata:");
|
|
36
|
+
lines.push(` ${AGENT_MARK}`);
|
|
37
|
+
lines.push("---");
|
|
38
|
+
lines.push("");
|
|
39
|
+
lines.push("## Commands");
|
|
40
|
+
lines.push("");
|
|
41
|
+
lines.push("```sh");
|
|
42
|
+
for (const c of spec.commands.lines)
|
|
43
|
+
lines.push(c);
|
|
44
|
+
lines.push("```");
|
|
45
|
+
lines.push("");
|
|
46
|
+
if (spec.steps) {
|
|
47
|
+
lines.push("## Steps");
|
|
48
|
+
lines.push("");
|
|
49
|
+
spec.steps.forEach((s, i) => lines.push(`${i + 1}. ${s}`));
|
|
50
|
+
lines.push("");
|
|
51
|
+
}
|
|
52
|
+
lines.push("## Rules");
|
|
53
|
+
lines.push("");
|
|
54
|
+
for (const r of spec.rules)
|
|
55
|
+
lines.push(`- ${r}`);
|
|
56
|
+
lines.push("");
|
|
57
|
+
lines.push(PROJECT_NOTES_HEADING);
|
|
58
|
+
return lines.join("\n") + "\n";
|
|
59
|
+
}
|
|
60
|
+
export function generateSkills(d, cfg) {
|
|
61
|
+
const n = d.node;
|
|
62
|
+
const pm = n.packageManager ?? "npm";
|
|
63
|
+
const files = [];
|
|
64
|
+
// 1. run
|
|
65
|
+
const runScriptName = firstScript(n.scripts, ["dev", "start", "serve"]);
|
|
66
|
+
if (runScriptName) {
|
|
67
|
+
const command = runScript(pm, runScriptName);
|
|
68
|
+
files.push({
|
|
69
|
+
path: ".claude/skills/run/SKILL.md",
|
|
70
|
+
content: renderSkill({
|
|
71
|
+
name: "run",
|
|
72
|
+
description: `Starts the project's dev server with its \`${runScriptName}\` script`,
|
|
73
|
+
allowedTools: [...bashPair(command), "Read", "Grep", "Glob"].join(" "),
|
|
74
|
+
manualOnly: false,
|
|
75
|
+
commands: { kind: "sh", lines: [command] },
|
|
76
|
+
steps: null,
|
|
77
|
+
rules: [
|
|
78
|
+
"Run the command and report what it prints.",
|
|
79
|
+
"Stop the server before finishing when it does not exit on its own.",
|
|
80
|
+
],
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// 2. test
|
|
85
|
+
if (cfg.commands.test) {
|
|
86
|
+
const command = cfg.commands.test;
|
|
87
|
+
files.push({
|
|
88
|
+
path: ".claude/skills/test/SKILL.md",
|
|
89
|
+
content: renderSkill({
|
|
90
|
+
name: "test",
|
|
91
|
+
description: "Runs the project's test suite",
|
|
92
|
+
allowedTools: [...bashPair(command), "Edit", "Write", "Read", "Grep", "Glob"].join(" "),
|
|
93
|
+
manualOnly: false,
|
|
94
|
+
commands: { kind: "sh", lines: [command] },
|
|
95
|
+
steps: null,
|
|
96
|
+
rules: [
|
|
97
|
+
"Run the full suite and report the real exit status.",
|
|
98
|
+
"Add or update a test with the change; never delete one to make it pass.",
|
|
99
|
+
],
|
|
100
|
+
}),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
// 3. migrate
|
|
104
|
+
const migrationDirs = d.python.present
|
|
105
|
+
? [...new Set([...d.repo.migrationDirs, ...d.python.migrationDirs])].sort()
|
|
106
|
+
: d.repo.migrationDirs;
|
|
107
|
+
if (migrationDirs.length) {
|
|
108
|
+
const migrateScriptName = firstScript(n.scripts, ["migrate", "db:migrate", "migrate:dev", "prisma:migrate"]);
|
|
109
|
+
const command = migrateScriptName ? runScript(pm, migrateScriptName) : null;
|
|
110
|
+
const dirs = migrationDirs.join(", ");
|
|
111
|
+
files.push({
|
|
112
|
+
path: ".claude/skills/migrate/SKILL.md",
|
|
113
|
+
content: renderSkill({
|
|
114
|
+
name: "migrate",
|
|
115
|
+
description: "Runs the project's database migrations",
|
|
116
|
+
allowedTools: (command ? [...bashPair(command), "Read", "Grep", "Glob"] : ["Read", "Grep", "Glob"]).join(" "),
|
|
117
|
+
manualOnly: true,
|
|
118
|
+
commands: command
|
|
119
|
+
? { kind: "sh", lines: [command] }
|
|
120
|
+
: {
|
|
121
|
+
kind: "sh",
|
|
122
|
+
lines: ["# No migration script was detected; use the project's own migration tool."],
|
|
123
|
+
},
|
|
124
|
+
steps: command
|
|
125
|
+
? [`List migration directories: ${dirs}.`, `Run \`${command}\`.`, "Verify the migration applied cleanly."]
|
|
126
|
+
: [
|
|
127
|
+
`List migration directories: ${dirs}.`,
|
|
128
|
+
"Use the project's own migration tool to apply pending migrations.",
|
|
129
|
+
"Verify the migration applied cleanly.",
|
|
130
|
+
],
|
|
131
|
+
rules: ["Never hand-edit a migration file already applied.", "Report what ran and its result."],
|
|
132
|
+
}),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
// 4. release
|
|
136
|
+
const releaseScriptName = firstScript(n.scripts, ["release", "publish", "version"]);
|
|
137
|
+
if (releaseScriptName) {
|
|
138
|
+
const command = runScript(pm, releaseScriptName);
|
|
139
|
+
files.push({
|
|
140
|
+
path: ".claude/skills/release/SKILL.md",
|
|
141
|
+
content: renderSkill({
|
|
142
|
+
name: "release",
|
|
143
|
+
description: `Runs the project's release with its \`${releaseScriptName}\` script`,
|
|
144
|
+
allowedTools: [...bashPair(command), "Read", "Grep", "Glob"].join(" "),
|
|
145
|
+
manualOnly: true,
|
|
146
|
+
commands: { kind: "sh", lines: [command] },
|
|
147
|
+
steps: ["Confirm the working tree is clean.", `Run \`${command}\`.`, "Verify the release published."],
|
|
148
|
+
rules: ["Never release from a dirty working tree.", "Report what ran and its result."],
|
|
149
|
+
}),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
// 5. pr
|
|
153
|
+
if (d.repo.isGit) {
|
|
154
|
+
const base = d.repo.defaultBranch;
|
|
155
|
+
const pushCmd = "git push -u origin HEAD";
|
|
156
|
+
const prCmd = base ? `gh pr create --base ${base} --fill` : "gh pr create --fill";
|
|
157
|
+
files.push({
|
|
158
|
+
path: ".claude/skills/pr/SKILL.md",
|
|
159
|
+
content: renderSkill({
|
|
160
|
+
name: "pr",
|
|
161
|
+
description: "Opens a pull request for the current branch",
|
|
162
|
+
allowedTools: [
|
|
163
|
+
...["git status", "git diff", "git log", "git add", "git commit", "git push", "gh pr create"].flatMap(bashPair),
|
|
164
|
+
"Read",
|
|
165
|
+
"Grep",
|
|
166
|
+
"Glob",
|
|
167
|
+
].join(" "),
|
|
168
|
+
manualOnly: true,
|
|
169
|
+
commands: {
|
|
170
|
+
kind: "sh",
|
|
171
|
+
lines: ["git status", "git diff", "git log", "git add <files>", 'git commit -m "<message>"', pushCmd, prCmd],
|
|
172
|
+
},
|
|
173
|
+
steps: [
|
|
174
|
+
"Check status with `git status`.",
|
|
175
|
+
"Review the diff with `git diff` and the history with `git log`.",
|
|
176
|
+
"Stage and commit with `git add` and `git commit`.",
|
|
177
|
+
`Push with \`${pushCmd}\`.`,
|
|
178
|
+
`Open the PR with \`${prCmd}\`${base ? ` against \`${base}\`` : ""}.`,
|
|
179
|
+
],
|
|
180
|
+
rules: ["Never force-push.", "Report the PR URL when it opens."],
|
|
181
|
+
}),
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
// 6. preflight
|
|
185
|
+
if (cfg.stopGate.commands.length) {
|
|
186
|
+
const gateCommands = cfg.stopGate.commands.map((name) => cfg.commands[name]);
|
|
187
|
+
const scriptInvocation = 'bash "${CLAUDE_SKILL_DIR}/scripts/preflight.sh"';
|
|
188
|
+
files.push({
|
|
189
|
+
path: ".claude/skills/preflight/SKILL.md",
|
|
190
|
+
content: renderSkill({
|
|
191
|
+
name: "preflight",
|
|
192
|
+
description: "Runs the project's gate commands in order before finishing",
|
|
193
|
+
allowedTools: [...gateCommands.flatMap(bashPair), "Bash(bash *)", "Read", "Grep", "Glob"].join(" "),
|
|
194
|
+
manualOnly: true,
|
|
195
|
+
commands: { kind: "sh", lines: [scriptInvocation] },
|
|
196
|
+
steps: gateCommands.map((c) => `Run \`${c}\`.`),
|
|
197
|
+
rules: ["Run every gate command; do not skip one to save time.", "Report each command's real exit status."],
|
|
198
|
+
}),
|
|
199
|
+
});
|
|
200
|
+
const scriptLines = ["#!/usr/bin/env bash", `# ${AGENT_MARK}`, "set -euo pipefail"];
|
|
201
|
+
for (const c of gateCommands) {
|
|
202
|
+
scriptLines.push(`echo "Running: ${c}"`);
|
|
203
|
+
scriptLines.push(c);
|
|
204
|
+
}
|
|
205
|
+
files.push({ path: ".claude/skills/preflight/scripts/preflight.sh", content: scriptLines.join("\n") + "\n" });
|
|
206
|
+
}
|
|
207
|
+
// 7. characterization-test
|
|
208
|
+
if (n.testFramework || d.python.testFramework) {
|
|
209
|
+
const pythonOnly = !n.testFramework;
|
|
210
|
+
const named = pythonOnly
|
|
211
|
+
? [d.python.singleTestCommand, d.python.present ? (cfg.commands["py:test"] ?? cfg.commands.test) : null].filter((c) => !!c)
|
|
212
|
+
: [n.singleTestCommand, cfg.commands.test].filter((c) => !!c);
|
|
213
|
+
const frameworkName = pythonOnly ? "pytest" : n.testFramework;
|
|
214
|
+
const permissionPrefixes = [...new Set(named.map(permissionPrefix).filter((p) => p !== null))];
|
|
215
|
+
files.push({
|
|
216
|
+
path: ".claude/skills/characterization-test/SKILL.md",
|
|
217
|
+
content: renderSkill({
|
|
218
|
+
name: "characterization-test",
|
|
219
|
+
description: `Writes a characterization test with ${frameworkName} that pins current behavior`,
|
|
220
|
+
allowedTools: [...permissionPrefixes.flatMap(bashPair), "Edit", "Write", "Read", "Grep", "Glob"].join(" "),
|
|
221
|
+
manualOnly: false,
|
|
222
|
+
commands: { kind: "sh", lines: named },
|
|
223
|
+
steps: null,
|
|
224
|
+
rules: [
|
|
225
|
+
"Run the single-test command after writing the test.",
|
|
226
|
+
"Never delete or weaken the test to make it pass.",
|
|
227
|
+
],
|
|
228
|
+
}),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
// 8. doug-skills (always generated, manual-only, the refresh path)
|
|
232
|
+
files.push({
|
|
233
|
+
path: ".claude/skills/doug-skills/SKILL.md",
|
|
234
|
+
content: renderSkill({
|
|
235
|
+
name: "doug-skills",
|
|
236
|
+
description: "Refreshes this project's generated skills and agents by re-running doug init",
|
|
237
|
+
allowedTools: "Bash(doug init*)",
|
|
238
|
+
manualOnly: true,
|
|
239
|
+
commands: { kind: "sh", lines: ["doug init --dry-run", "doug init --yes"] },
|
|
240
|
+
steps: [
|
|
241
|
+
"Run `doug init --dry-run` in the project directory to print the proposal.",
|
|
242
|
+
"Show the proposal to the user.",
|
|
243
|
+
"Run `doug init --yes` only after the user says yes.",
|
|
244
|
+
],
|
|
245
|
+
rules: [
|
|
246
|
+
"This is how the skills above appear once the project has code the detectors can see.",
|
|
247
|
+
"Never invent another doug init flag.",
|
|
248
|
+
],
|
|
249
|
+
}),
|
|
250
|
+
});
|
|
251
|
+
return files;
|
|
252
|
+
}
|
|
253
|
+
export function isDougSkill(text) {
|
|
254
|
+
const withoutBom = text.startsWith("") ? text.slice(1) : text;
|
|
255
|
+
const lines = withoutBom.split("\n").map((l) => (l.endsWith("\r") ? l.slice(0, -1) : l));
|
|
256
|
+
if (lines[0] === "---") {
|
|
257
|
+
const closingIdx = lines.indexOf("---", 1);
|
|
258
|
+
if (closingIdx > 0) {
|
|
259
|
+
return lines.slice(0, closingIdx).some((l) => l.trim() === AGENT_MARK);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return lines.slice(0, 5).some((l) => l.trim() === `# ${AGENT_MARK}`);
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/generate/skills.ts"],"names":[],"mappings":"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"}
|
package/dist/init.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface InitOptions {
|
|
2
|
+
dir: string;
|
|
3
|
+
yes: boolean;
|
|
4
|
+
dryRun: boolean;
|
|
5
|
+
color: boolean;
|
|
6
|
+
quiet: boolean;
|
|
7
|
+
/** Skip the vendored hook file diffs in the printout (they are long and identical every time). */
|
|
8
|
+
showHookFiles: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function runInit(opts: InitOptions): Promise<number>;
|
package/dist/init.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { detect } from "./detect/index.js";
|
|
4
|
+
import { buildProposal, summarize } from "./generate/proposal.js";
|
|
5
|
+
import { renderDiff } from "./diff.js";
|
|
6
|
+
import { applyChanges } from "./apply.js";
|
|
7
|
+
async function confirm(question) {
|
|
8
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
9
|
+
const answer = await new Promise((res) => rl.question(question, res));
|
|
10
|
+
rl.close();
|
|
11
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
12
|
+
}
|
|
13
|
+
export async function runInit(opts) {
|
|
14
|
+
const dir = resolve(opts.dir);
|
|
15
|
+
const log = (s) => {
|
|
16
|
+
if (!opts.quiet)
|
|
17
|
+
process.stdout.write(s + "\n");
|
|
18
|
+
};
|
|
19
|
+
const detection = detect(dir);
|
|
20
|
+
const proposal = buildProposal(detection);
|
|
21
|
+
log("");
|
|
22
|
+
log("Detected:");
|
|
23
|
+
log(summarize(proposal));
|
|
24
|
+
if (proposal.notes.length) {
|
|
25
|
+
log("");
|
|
26
|
+
log("Notes:");
|
|
27
|
+
for (const n of proposal.notes)
|
|
28
|
+
log(` - ${n}`);
|
|
29
|
+
}
|
|
30
|
+
log("");
|
|
31
|
+
if (proposal.changes.length === 0) {
|
|
32
|
+
log("Nothing to change. The project is already configured.");
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
const hookFiles = proposal.changes.filter((c) => c.path.startsWith(".doug/hooks/"));
|
|
36
|
+
const visible = proposal.changes.filter((c) => opts.showHookFiles || !c.path.startsWith(".doug/hooks/"));
|
|
37
|
+
log(`Proposed changes (${proposal.changes.length} files):`);
|
|
38
|
+
log("");
|
|
39
|
+
for (const c of visible) {
|
|
40
|
+
log(renderDiff(c, { color: opts.color }));
|
|
41
|
+
log("");
|
|
42
|
+
}
|
|
43
|
+
if (!opts.showHookFiles && hookFiles.length) {
|
|
44
|
+
log(`create .doug/hooks/ (${hookFiles.length} vendored hook files from @dougharness/gates; pass --show-hooks to print them)`);
|
|
45
|
+
log("");
|
|
46
|
+
}
|
|
47
|
+
if (opts.dryRun) {
|
|
48
|
+
log("Dry run. Nothing written.");
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
if (!opts.yes) {
|
|
52
|
+
if (!process.stdin.isTTY) {
|
|
53
|
+
log("Not a TTY and --yes not given. Nothing written.");
|
|
54
|
+
return 2;
|
|
55
|
+
}
|
|
56
|
+
const ok = await confirm("Apply these changes? [y/N] ");
|
|
57
|
+
if (!ok) {
|
|
58
|
+
log("Aborted. Nothing written.");
|
|
59
|
+
return 1;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const written = applyChanges(dir, proposal.changes);
|
|
63
|
+
log(`Wrote ${written.length} files.`);
|
|
64
|
+
log("");
|
|
65
|
+
log("Next: open Claude Code in this directory. Hooks are active immediately.");
|
|
66
|
+
log(" Edit CLAUDE.md's Gotchas section by hand; keep the file short.");
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
|
package/dist/trace.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type TraceLine } from "@dougharness/gates/lib/trace.mjs";
|
|
2
|
+
export interface TraceIo {
|
|
3
|
+
stdout(s: string): void;
|
|
4
|
+
stderr(s: string): void;
|
|
5
|
+
}
|
|
6
|
+
export declare const TRACE_USAGE = "Usage:\n doug trace [dir] [--session <id>] [--json]\n\nReplays the newest trace under <dir>/.doug/.state/trace (or the session named by --session) and attributes\nevents, tool calls, wall time, and tokens to each agent. Tokens come only from what Claude Code reported at\nSubagentStop; the main session and anything unreported show null.\n";
|
|
7
|
+
export declare function pickTraceFile(traceDir: string, session: string | null): string | null;
|
|
8
|
+
export declare function renderTrace(session: string, file: string, lines: TraceLine[]): string;
|
|
9
|
+
export declare function runTrace(argv: string[], io?: TraceIo): Promise<number>;
|