@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.
Files changed (144) hide show
  1. package/LICENSE +21 -0
  2. package/dist/ablate.d.ts +96 -0
  3. package/dist/ablate.js +440 -0
  4. package/dist/ablate.js.map +1 -0
  5. package/dist/apply.d.ts +2 -0
  6. package/dist/apply.js +19 -0
  7. package/dist/apply.js.map +1 -0
  8. package/dist/bin.d.ts +2 -0
  9. package/dist/bin.js +80 -0
  10. package/dist/bin.js.map +1 -0
  11. package/dist/board-page.d.ts +15 -0
  12. package/dist/board-page.js +27 -0
  13. package/dist/board-page.js.map +1 -0
  14. package/dist/board-serve-process.d.ts +24 -0
  15. package/dist/board-serve-process.js +227 -0
  16. package/dist/board-serve-process.js.map +1 -0
  17. package/dist/board-serve.d.ts +9 -0
  18. package/dist/board-serve.js +302 -0
  19. package/dist/board-serve.js.map +1 -0
  20. package/dist/board.d.ts +6 -0
  21. package/dist/board.js +515 -0
  22. package/dist/board.js.map +1 -0
  23. package/dist/detect/fs.d.ts +6 -0
  24. package/dist/detect/fs.js +50 -0
  25. package/dist/detect/fs.js.map +1 -0
  26. package/dist/detect/index.d.ts +3 -0
  27. package/dist/detect/index.js +13 -0
  28. package/dist/detect/index.js.map +1 -0
  29. package/dist/detect/node.d.ts +3 -0
  30. package/dist/detect/node.js +179 -0
  31. package/dist/detect/node.js.map +1 -0
  32. package/dist/detect/python.d.ts +2 -0
  33. package/dist/detect/python.js +388 -0
  34. package/dist/detect/python.js.map +1 -0
  35. package/dist/detect/repo.d.ts +2 -0
  36. package/dist/detect/repo.js +102 -0
  37. package/dist/detect/repo.js.map +1 -0
  38. package/dist/detect/types.d.ts +98 -0
  39. package/dist/detect/types.js +2 -0
  40. package/dist/detect/types.js.map +1 -0
  41. package/dist/diff.d.ts +12 -0
  42. package/dist/diff.js +105 -0
  43. package/dist/diff.js.map +1 -0
  44. package/dist/generate/agents.d.ts +19 -0
  45. package/dist/generate/agents.js +184 -0
  46. package/dist/generate/agents.js.map +1 -0
  47. package/dist/generate/claude-md.d.ts +9 -0
  48. package/dist/generate/claude-md.js +111 -0
  49. package/dist/generate/claude-md.js.map +1 -0
  50. package/dist/generate/config.d.ts +51 -0
  51. package/dist/generate/config.js +155 -0
  52. package/dist/generate/config.js.map +1 -0
  53. package/dist/generate/proposal.d.ts +11 -0
  54. package/dist/generate/proposal.js +175 -0
  55. package/dist/generate/proposal.js.map +1 -0
  56. package/dist/generate/settings.d.ts +35 -0
  57. package/dist/generate/settings.js +213 -0
  58. package/dist/generate/settings.js.map +1 -0
  59. package/dist/generate/skills.d.ts +8 -0
  60. package/dist/generate/skills.js +264 -0
  61. package/dist/generate/skills.js.map +1 -0
  62. package/dist/init.d.ts +10 -0
  63. package/dist/init.js +69 -0
  64. package/dist/init.js.map +1 -0
  65. package/dist/trace.d.ts +9 -0
  66. package/dist/trace.js +106 -0
  67. package/dist/trace.js.map +1 -0
  68. package/node_modules/@dougharness/flow/.claude-plugin/plugin.json +10 -0
  69. package/node_modules/@dougharness/flow/LICENSE +21 -0
  70. package/node_modules/@dougharness/flow/agents/adversary-claude.md +33 -0
  71. package/node_modules/@dougharness/flow/agents/adversary.md +29 -0
  72. package/node_modules/@dougharness/flow/agents/implementer.md +23 -0
  73. package/node_modules/@dougharness/flow/agents/lead.md +35 -0
  74. package/node_modules/@dougharness/flow/agents/planner.md +70 -0
  75. package/node_modules/@dougharness/flow/agents/researcher.md +31 -0
  76. package/node_modules/@dougharness/flow/agents/reviewer.md +26 -0
  77. package/node_modules/@dougharness/flow/agents/verifier.md +24 -0
  78. package/node_modules/@dougharness/flow/lib/board.mjs +840 -0
  79. package/node_modules/@dougharness/flow/lib/code-index.mjs +629 -0
  80. package/node_modules/@dougharness/flow/lib/cost.mjs +392 -0
  81. package/node_modules/@dougharness/flow/lib/decisions.mjs +314 -0
  82. package/node_modules/@dougharness/flow/lib/embeddings.mjs +539 -0
  83. package/node_modules/@dougharness/flow/lib/land.mjs +219 -0
  84. package/node_modules/@dougharness/flow/lib/learn.mjs +742 -0
  85. package/node_modules/@dougharness/flow/lib/memory-import.mjs +145 -0
  86. package/node_modules/@dougharness/flow/lib/memory.mjs +1641 -0
  87. package/node_modules/@dougharness/flow/lib/models.mjs +148 -0
  88. package/node_modules/@dougharness/flow/lib/plan.mjs +773 -0
  89. package/node_modules/@dougharness/flow/lib/rehearse.mjs +825 -0
  90. package/node_modules/@dougharness/flow/lib/worktrees.mjs +215 -0
  91. package/node_modules/@dougharness/flow/package.json +19 -0
  92. package/node_modules/@dougharness/flow/scripts/board.mjs +260 -0
  93. package/node_modules/@dougharness/flow/scripts/cost.mjs +66 -0
  94. package/node_modules/@dougharness/flow/scripts/learn.mjs +161 -0
  95. package/node_modules/@dougharness/flow/scripts/memory.mjs +1274 -0
  96. package/node_modules/@dougharness/flow/scripts/plan.mjs +547 -0
  97. package/node_modules/@dougharness/flow/scripts/rehearse.mjs +129 -0
  98. package/node_modules/@dougharness/flow/skills/core-next/SKILL.md +92 -0
  99. package/node_modules/@dougharness/flow/skills/doug-approve/SKILL.md +15 -0
  100. package/node_modules/@dougharness/flow/skills/doug-decide/SKILL.md +26 -0
  101. package/node_modules/@dougharness/flow/skills/doug-implement/SKILL.md +22 -0
  102. package/node_modules/@dougharness/flow/skills/doug-learn/SKILL.md +20 -0
  103. package/node_modules/@dougharness/flow/skills/doug-next/SKILL.md +87 -0
  104. package/node_modules/@dougharness/flow/skills/doug-plan/SKILL.md +22 -0
  105. package/node_modules/@dougharness/flow/skills/doug-swarm/SKILL.md +55 -0
  106. package/node_modules/@dougharness/flow/skills/harness-fix/SKILL.md +85 -0
  107. package/node_modules/@dougharness/flow/skills/research/SKILL.md +41 -0
  108. package/node_modules/@dougharness/flow/skills/run-report/SKILL.md +51 -0
  109. package/node_modules/@dougharness/flow/skills/swarm-launch/SKILL.md +27 -0
  110. package/node_modules/@dougharness/flow/workflows/doug-implement.js +2687 -0
  111. package/node_modules/@dougharness/gates/.claude-plugin/plugin.json +10 -0
  112. package/node_modules/@dougharness/gates/LICENSE +21 -0
  113. package/node_modules/@dougharness/gates/hooks/hooks.json +184 -0
  114. package/node_modules/@dougharness/gates/lib/agent-context.mjs +111 -0
  115. package/node_modules/@dougharness/gates/lib/anchor.mjs +110 -0
  116. package/node_modules/@dougharness/gates/lib/baseline.mjs +160 -0
  117. package/node_modules/@dougharness/gates/lib/bash-rules.mjs +1522 -0
  118. package/node_modules/@dougharness/gates/lib/block-ledger.mjs +127 -0
  119. package/node_modules/@dougharness/gates/lib/checkpoint.mjs +97 -0
  120. package/node_modules/@dougharness/gates/lib/config.mjs +168 -0
  121. package/node_modules/@dougharness/gates/lib/evidence.mjs +59 -0
  122. package/node_modules/@dougharness/gates/lib/glob.mjs +86 -0
  123. package/node_modules/@dougharness/gates/lib/io.mjs +91 -0
  124. package/node_modules/@dougharness/gates/lib/paths.mjs +101 -0
  125. package/node_modules/@dougharness/gates/lib/proposals.mjs +201 -0
  126. package/node_modules/@dougharness/gates/lib/run.mjs +147 -0
  127. package/node_modules/@dougharness/gates/lib/scope.mjs +117 -0
  128. package/node_modules/@dougharness/gates/lib/secret-rules.mjs +268 -0
  129. package/node_modules/@dougharness/gates/lib/state.mjs +114 -0
  130. package/node_modules/@dougharness/gates/lib/trace.mjs +196 -0
  131. package/node_modules/@dougharness/gates/package.json +17 -0
  132. package/node_modules/@dougharness/gates/scripts/edit-loop.mjs +39 -0
  133. package/node_modules/@dougharness/gates/scripts/format-on-edit.mjs +45 -0
  134. package/node_modules/@dougharness/gates/scripts/guard-bash.mjs +32 -0
  135. package/node_modules/@dougharness/gates/scripts/protect-paths.mjs +49 -0
  136. package/node_modules/@dougharness/gates/scripts/reanchor.mjs +81 -0
  137. package/node_modules/@dougharness/gates/scripts/research-cap.mjs +295 -0
  138. package/node_modules/@dougharness/gates/scripts/secret-scan.mjs +26 -0
  139. package/node_modules/@dougharness/gates/scripts/session-start-baseline.mjs +57 -0
  140. package/node_modules/@dougharness/gates/scripts/statusline.mjs +133 -0
  141. package/node_modules/@dougharness/gates/scripts/stop-gate.mjs +1422 -0
  142. package/node_modules/@dougharness/gates/scripts/trace.mjs +75 -0
  143. package/package.json +33 -0
  144. package/templates/board-app.js +533 -0
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+ // Claude Code status line: prints one line like `Doug 0.1.0 · Opus · main · ctx 8%`.
3
+ // Reads the status-line JSON Claude Code passes on stdin. Never prints an error, always exits 0;
4
+ // each segment degrades on its own, and any thrown error falls back to the bare line `Doug`.
5
+
6
+ import { readFileSync } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { spawnSync } from "node:child_process";
9
+ import { DEFAULTS } from "../lib/config.mjs";
10
+ import { loadState, saveState } from "../lib/state.mjs";
11
+
12
+ const SEP = " · ";
13
+
14
+ // Reads one JSON object from stdin. Empty or unparseable stdin throws so main() prints the
15
+ // bare fallback line instead of guessing paths from process.cwd().
16
+ async function readInput(timeoutMs) {
17
+ const chunks = [];
18
+ await new Promise((resolve) => {
19
+ process.stdin.on("data", (c) => chunks.push(c));
20
+ process.stdin.on("end", resolve);
21
+ process.stdin.on("error", resolve);
22
+ setTimeout(resolve, timeoutMs).unref();
23
+ });
24
+ const text = Buffer.concat(chunks).toString("utf8").trim();
25
+ if (!text) throw new Error("empty stdin");
26
+ const input = JSON.parse(text);
27
+ if (!input || typeof input !== "object" || Array.isArray(input)) throw new Error("stdin is not a JSON object");
28
+ return input;
29
+ }
30
+
31
+ function nonEmpty(v) {
32
+ return typeof v === "string" && v.trim() !== "";
33
+ }
34
+
35
+ function productSegment(projectDir) {
36
+ let name = "Doug";
37
+ let version = "";
38
+ try {
39
+ const cfg = JSON.parse(readFileSync(join(projectDir, ".doug", "config.json"), "utf8"));
40
+ const doug = cfg && typeof cfg === "object" ? cfg.doug : null;
41
+ if (doug && typeof doug === "object") {
42
+ if (nonEmpty(doug.name)) name = doug.name.trim();
43
+ if (nonEmpty(doug.version)) version = doug.version.trim();
44
+ }
45
+ } catch {
46
+ // missing or unreadable config: bare product name
47
+ }
48
+ return version ? `${name} ${version}` : name;
49
+ }
50
+
51
+ function branchSegment(workDir) {
52
+ try {
53
+ const res = spawnSync("git", ["branch", "--show-current"], {
54
+ cwd: workDir,
55
+ encoding: "utf8",
56
+ timeout: 2000,
57
+ stdio: ["ignore", "pipe", "ignore"],
58
+ });
59
+ if (res.status !== 0 || res.error) return null;
60
+ const branch = (res.stdout || "").trim();
61
+ return branch || null;
62
+ } catch {
63
+ return null;
64
+ }
65
+ }
66
+
67
+ // Reads only contextWindow out of .doug/config.json, deep-merged onto its defaults, without loadConfig's
68
+ // stderr line on a broken file (minor 4: this script's header promises it never prints an error).
69
+ function loadContextWindowConfig(projectDir) {
70
+ let cw = null;
71
+ try {
72
+ const raw = JSON.parse(readFileSync(join(projectDir, ".doug", "config.json"), "utf8"));
73
+ if (raw && typeof raw === "object" && raw.contextWindow && typeof raw.contextWindow === "object") cw = raw.contextWindow;
74
+ } catch {
75
+ // missing or unreadable config: contextWindow defaults (off)
76
+ }
77
+ return { contextWindow: { ...DEFAULTS.contextWindow, ...cw } };
78
+ }
79
+
80
+ function contextSegment(input, cfg) {
81
+ const pct = input.context_window?.used_percentage;
82
+ if (typeof pct !== "number" || !Number.isFinite(pct)) return "ctx --";
83
+ const rounded = Math.round(pct);
84
+ const threshold = cfg?.contextWindow?.threshold ?? 80;
85
+ const marker = cfg?.contextWindow?.enabled && rounded >= threshold ? " compact?" : "";
86
+ return `ctx ${rounded}%${marker}`;
87
+ }
88
+
89
+ // Records the rounded pct into session state (lib/state.mjs) for the Stop gate to read, only when the
90
+ // contextWindow feature is on, a session_id and a finite pct are both present, and the rounded value actually
91
+ // changed (the status line runs often). Never lets a state read/write failure change the printed line.
92
+ function recordContext(input, projectDir, cfg) {
93
+ try {
94
+ if (!cfg?.contextWindow?.enabled) return;
95
+ if (!nonEmpty(input.session_id)) return;
96
+ const pct = input.context_window?.used_percentage;
97
+ if (typeof pct !== "number" || !Number.isFinite(pct)) return;
98
+ const rounded = Math.round(pct);
99
+ const state = loadState(projectDir, input.session_id);
100
+ if (state.context && state.context.pct === rounded) return;
101
+ // Keep notifiedAt (set by the Stop gate) across a pct update, so growth is tracked from the last notice
102
+ // rather than reset by every status-line render.
103
+ state.context = { ...(state.context || {}), pct: rounded, at: new Date().toISOString() };
104
+ saveState(projectDir, input.session_id, state);
105
+ } catch {
106
+ // never let a state write failure change the status line output
107
+ }
108
+ }
109
+
110
+ async function main() {
111
+ const input = await readInput(1500);
112
+ const ws = input.workspace && typeof input.workspace === "object" ? input.workspace : {};
113
+ const projectDir = ws.project_dir ?? ws.current_dir ?? input.cwd ?? process.cwd();
114
+ const workDir = ws.current_dir ?? input.cwd ?? process.cwd();
115
+
116
+ const cfg = loadContextWindowConfig(projectDir);
117
+
118
+ const segments = [productSegment(projectDir)];
119
+ if (nonEmpty(input.model?.display_name)) segments.push(input.model.display_name.trim());
120
+ const branch = branchSegment(workDir);
121
+ if (branch) segments.push(branch);
122
+ segments.push(contextSegment(input, cfg));
123
+ recordContext(input, projectDir, cfg);
124
+
125
+ process.stdout.write(segments.join(SEP) + "\n");
126
+ }
127
+
128
+ main()
129
+ .then(() => process.exit(0))
130
+ .catch(() => {
131
+ process.stdout.write("Doug\n");
132
+ process.exit(0);
133
+ });