@pugi/cli 0.1.0-beta.2 → 0.1.0-beta.20

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 (130) hide show
  1. package/THIRD_PARTY_NOTICES.md +40 -0
  2. package/assets/pugi-mascot.ansi +15 -40
  3. package/bin/run.js +33 -1
  4. package/dist/commands/jobs-watch.js +201 -0
  5. package/dist/commands/jobs.js +15 -0
  6. package/dist/core/agent-progress/cleanup.js +134 -0
  7. package/dist/core/agent-progress/schema.js +144 -0
  8. package/dist/core/agent-progress/writer.js +101 -0
  9. package/dist/core/compact/auto-trigger.js +96 -0
  10. package/dist/core/compact/buffer-rewriter.js +115 -0
  11. package/dist/core/compact/summarizer.js +196 -0
  12. package/dist/core/compact/token-counter.js +108 -0
  13. package/dist/core/consensus/diff-capture.js +73 -0
  14. package/dist/core/context/index.js +7 -0
  15. package/dist/core/context/markdown-traverse.js +255 -0
  16. package/dist/core/cost/rate-card.js +129 -0
  17. package/dist/core/cost/tracker.js +221 -0
  18. package/dist/core/denial-tracking/index.js +8 -0
  19. package/dist/core/denial-tracking/state.js +264 -0
  20. package/dist/core/diagnostics/probe-runner.js +93 -0
  21. package/dist/core/diagnostics/probes/api.js +46 -0
  22. package/dist/core/diagnostics/probes/auth.js +86 -0
  23. package/dist/core/diagnostics/probes/cli-version.js +127 -0
  24. package/dist/core/diagnostics/probes/config.js +72 -0
  25. package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
  26. package/dist/core/diagnostics/probes/disk.js +81 -0
  27. package/dist/core/diagnostics/probes/git.js +65 -0
  28. package/dist/core/diagnostics/probes/mcp.js +75 -0
  29. package/dist/core/diagnostics/probes/node.js +59 -0
  30. package/dist/core/diagnostics/probes/pnpm.js +36 -0
  31. package/dist/core/diagnostics/probes/session.js +74 -0
  32. package/dist/core/diagnostics/probes/status-snapshot.js +442 -0
  33. package/dist/core/diagnostics/probes/workspace.js +63 -0
  34. package/dist/core/diagnostics/types.js +70 -0
  35. package/dist/core/edits/dispatch.js +218 -2
  36. package/dist/core/edits/journal.js +199 -0
  37. package/dist/core/edits/layer-d-ast.js +557 -14
  38. package/dist/core/edits/verify-hook.js +273 -0
  39. package/dist/core/edits/worktree.js +111 -18
  40. package/dist/core/engine/anvil-client.js +115 -5
  41. package/dist/core/engine/budgets.js +89 -0
  42. package/dist/core/engine/context-prefix.js +155 -0
  43. package/dist/core/engine/intent.js +260 -0
  44. package/dist/core/engine/native-pugi.js +744 -210
  45. package/dist/core/engine/prompts.js +61 -6
  46. package/dist/core/engine/strip-internal-fields.js +124 -0
  47. package/dist/core/engine/tool-bridge.js +818 -31
  48. package/dist/core/file-cache.js +113 -1
  49. package/dist/core/init/scaffold.js +195 -0
  50. package/dist/core/lsp/client.js +174 -29
  51. package/dist/core/mcp/client.js +75 -6
  52. package/dist/core/mcp/http-server.js +553 -0
  53. package/dist/core/mcp/permission.js +190 -0
  54. package/dist/core/mcp/registry.js +24 -2
  55. package/dist/core/mcp/server-tools.js +219 -0
  56. package/dist/core/mcp/server.js +397 -0
  57. package/dist/core/permissions/gate.js +187 -0
  58. package/dist/core/permissions/index.js +18 -0
  59. package/dist/core/permissions/mode.js +102 -0
  60. package/dist/core/permissions/state.js +160 -0
  61. package/dist/core/permissions/tool-class.js +93 -0
  62. package/dist/core/repl/codebase-survey.js +308 -0
  63. package/dist/core/repl/history.js +11 -1
  64. package/dist/core/repl/init-interview.js +457 -0
  65. package/dist/core/repl/model-pricing.js +135 -0
  66. package/dist/core/repl/onboarding-state.js +297 -0
  67. package/dist/core/repl/session.js +719 -29
  68. package/dist/core/repl/slash-commands.js +133 -9
  69. package/dist/core/retry-budget/budget.js +284 -0
  70. package/dist/core/retry-budget/index.js +5 -0
  71. package/dist/core/settings.js +71 -0
  72. package/dist/core/skills/defaults.js +457 -0
  73. package/dist/core/subagents/dispatcher-real.js +600 -0
  74. package/dist/core/subagents/dispatcher.js +113 -24
  75. package/dist/core/subagents/index.js +18 -5
  76. package/dist/core/subagents/isolation-matrix.js +213 -0
  77. package/dist/core/subagents/spawn.js +19 -4
  78. package/dist/core/transport/version-interceptor.js +166 -0
  79. package/dist/index.js +28 -0
  80. package/dist/runtime/bootstrap.js +190 -0
  81. package/dist/runtime/cli.js +1588 -266
  82. package/dist/runtime/commands/compact.js +296 -0
  83. package/dist/runtime/commands/cost.js +199 -0
  84. package/dist/runtime/commands/delegate.js +289 -0
  85. package/dist/runtime/commands/doctor.js +369 -0
  86. package/dist/runtime/commands/lsp.js +187 -5
  87. package/dist/runtime/commands/mcp.js +824 -0
  88. package/dist/runtime/commands/patch.js +17 -0
  89. package/dist/runtime/commands/permissions.js +87 -0
  90. package/dist/runtime/commands/report.js +299 -0
  91. package/dist/runtime/commands/review-consensus.js +17 -2
  92. package/dist/runtime/commands/roster.js +117 -0
  93. package/dist/runtime/commands/status.js +178 -0
  94. package/dist/runtime/commands/worktree.js +50 -6
  95. package/dist/runtime/headless.js +543 -0
  96. package/dist/runtime/load-hooks-or-exit.js +71 -0
  97. package/dist/runtime/plan-decompose.js +531 -0
  98. package/dist/runtime/version.js +65 -0
  99. package/dist/tools/agent-tool.js +206 -0
  100. package/dist/tools/apply-patch.js +281 -39
  101. package/dist/tools/ask-user-question.js +213 -0
  102. package/dist/tools/ask-user.js +115 -0
  103. package/dist/tools/file-tools.js +85 -14
  104. package/dist/tools/mcp-tool.js +260 -0
  105. package/dist/tools/multi-edit.js +361 -0
  106. package/dist/tools/registry.js +22 -2
  107. package/dist/tools/skill-tool.js +96 -0
  108. package/dist/tools/tasks.js +208 -0
  109. package/dist/tools/web-fetch.js +147 -2
  110. package/dist/tools/web-search.js +458 -0
  111. package/dist/tui/agent-progress-card.js +111 -0
  112. package/dist/tui/agent-tree.js +10 -0
  113. package/dist/tui/ask-modal.js +2 -2
  114. package/dist/tui/ask-user-question-prompt.js +192 -0
  115. package/dist/tui/compact-banner.js +54 -0
  116. package/dist/tui/conversation-pane.js +69 -8
  117. package/dist/tui/cost-table.js +111 -0
  118. package/dist/tui/doctor-table.js +31 -0
  119. package/dist/tui/input-box.js +1 -1
  120. package/dist/tui/markdown-render.js +4 -4
  121. package/dist/tui/repl-render.js +276 -37
  122. package/dist/tui/repl-splash.js +2 -2
  123. package/dist/tui/repl.js +25 -6
  124. package/dist/tui/splash.js +1 -1
  125. package/dist/tui/status-bar.js +94 -16
  126. package/dist/tui/status-table.js +7 -0
  127. package/dist/tui/tool-stream-pane.js +7 -0
  128. package/dist/tui/update-banner.js +20 -2
  129. package/docs/examples/codegraph.mcp.json +10 -0
  130. package/package.json +9 -6
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Bootstrap helpers — β1b U7 / U8 (2026-05-26).
3
+ *
4
+ * Two related contracts:
5
+ *
6
+ * - U7: when `pugi` runs in a bare directory (no `.pugi/` and no
7
+ * project-marker file like `package.json` / `Cargo.toml` / `go.mod`)
8
+ * AND we have a TTY, offer an interactive `pugi init`.
9
+ *
10
+ * - U8: when `pugi` runs in a sub-directory of one or more parent
11
+ * projects (each carrying a `.pugi/settings.json` OR a git root),
12
+ * present a picker — "Found N projects: <list>. Pick OR /init here".
13
+ *
14
+ * Both checks are pure file-system queries; the interactive bridge
15
+ * lives one layer up (REPL bootstrap, slash-command palette). This
16
+ * module surfaces the structured result and the caller decides UX.
17
+ *
18
+ * Project markers we recognise (first match wins):
19
+ * - `.pugi/settings.json` (highest priority — Pugi-aware project)
20
+ * - `package.json` (Node / TypeScript / pnpm monorepo)
21
+ * - `Cargo.toml`
22
+ * - `go.mod`
23
+ * - `pyproject.toml` / `requirements.txt` / `setup.py`
24
+ * - `Gemfile`
25
+ * - `composer.json`
26
+ * - `pom.xml` / `build.gradle` / `build.gradle.kts`
27
+ * - `.git/` directory (last resort — git repo root)
28
+ *
29
+ * Walk depth is capped at 12 ancestors. Anything deeper is operator
30
+ * error (running `pugi` from `/Users/x/Library/.../node_modules/...`)
31
+ * and a deeper walk would be slow + surprising.
32
+ *
33
+ * Brand voice: ASCII only.
34
+ */
35
+ import { existsSync, statSync } from 'node:fs';
36
+ import { dirname, resolve, basename } from 'node:path';
37
+ const PROJECT_MARKER_FILES = [
38
+ '.pugi/settings.json',
39
+ 'package.json',
40
+ 'Cargo.toml',
41
+ 'go.mod',
42
+ 'pyproject.toml',
43
+ 'requirements.txt',
44
+ 'setup.py',
45
+ 'Gemfile',
46
+ 'composer.json',
47
+ 'pom.xml',
48
+ 'build.gradle',
49
+ 'build.gradle.kts',
50
+ ];
51
+ const MAX_PARENT_WALK = 12;
52
+ /**
53
+ * Detect the workspace state at `cwd`. Pure file-system query; never
54
+ * throws. The caller pairs this with the TTY / --no-tty / --json flags
55
+ * to decide whether to prompt the operator.
56
+ */
57
+ export function detectWorkspaceState(cwd) {
58
+ const absCwd = resolve(cwd);
59
+ // `.pugi/` at cwd always wins — we are already initialised.
60
+ if (hasPugiDir(absCwd)) {
61
+ return { kind: 'existing_pugi', root: absCwd };
62
+ }
63
+ // Project marker at cwd → proceed without prompting.
64
+ const cwdMarker = findMarkerAt(absCwd);
65
+ if (cwdMarker) {
66
+ return { kind: 'existing_project', root: absCwd, marker: cwdMarker };
67
+ }
68
+ // Walk parents — collect every ancestor that looks like a project.
69
+ const parents = findParentProjects(absCwd);
70
+ if (parents.length > 0) {
71
+ return { kind: 'inside_parent_projects', parents };
72
+ }
73
+ return { kind: 'bare' };
74
+ }
75
+ /**
76
+ * Walk parent directories up to MAX_PARENT_WALK ancestors, collecting
77
+ * every directory that has a project marker. Nearest-first. Stops at
78
+ * the filesystem root. Exported for U8 spec coverage + for callers
79
+ * that want the raw list (e.g. a /workspaces shell command).
80
+ */
81
+ export function findParentProjects(cwd) {
82
+ const out = [];
83
+ let current = dirname(resolve(cwd));
84
+ let last = '';
85
+ let hops = 0;
86
+ while (current && current !== last && hops < MAX_PARENT_WALK) {
87
+ const marker = findMarkerAt(current);
88
+ if (marker) {
89
+ out.push({ root: current, marker });
90
+ }
91
+ last = current;
92
+ current = dirname(current);
93
+ hops += 1;
94
+ }
95
+ return out;
96
+ }
97
+ /**
98
+ * Return the first matching project marker filename inside `dir`, or
99
+ * null when none of the candidates exist. `.pugi/settings.json` is a
100
+ * file (not the directory), so we test both for symmetry — if the
101
+ * operator has `.pugi/` but no settings.json yet, we treat it as a
102
+ * Pugi-aware project (the directory itself is the signal).
103
+ */
104
+ function findMarkerAt(dir) {
105
+ for (const marker of PROJECT_MARKER_FILES) {
106
+ const path = resolve(dir, marker);
107
+ try {
108
+ if (existsSync(path))
109
+ return marker;
110
+ }
111
+ catch {
112
+ /* permission error — treat as missing */
113
+ }
114
+ }
115
+ // `.git/` last — costly because it touches the FS but only when no
116
+ // other marker hit. Skip if `.git/` is a file (worktree shim) since
117
+ // we still want the worktree path.
118
+ const gitPath = resolve(dir, '.git');
119
+ try {
120
+ if (existsSync(gitPath))
121
+ return '.git';
122
+ }
123
+ catch {
124
+ /* ignore */
125
+ }
126
+ return null;
127
+ }
128
+ /**
129
+ * True iff the directory has a `.pugi/` subdirectory. We check the
130
+ * directory itself (not the settings.json inside) because the moment
131
+ * `.pugi/` exists Pugi is "set up here" from the operator's POV —
132
+ * settings.json may be empty / lazily written.
133
+ */
134
+ function hasPugiDir(dir) {
135
+ const path = resolve(dir, '.pugi');
136
+ try {
137
+ if (!existsSync(path))
138
+ return false;
139
+ return statSync(path).isDirectory();
140
+ }
141
+ catch {
142
+ return false;
143
+ }
144
+ }
145
+ /**
146
+ * Build a human-friendly label for a project root: prefer the basename
147
+ * suffixed with the marker (`pugi (package.json)`). Used by the U8
148
+ * picker to render the list. Exported for spec coverage.
149
+ */
150
+ export function projectLabel(root, marker) {
151
+ const name = basename(root) || root;
152
+ return `${name} (${marker})`;
153
+ }
154
+ /**
155
+ * Should we proactively offer `pugi init` in this invocation?
156
+ *
157
+ * - kind === 'bare' → yes (U7)
158
+ * - kind === 'inside_parent_projects' → yes (U8 picker, "or init here")
159
+ * - existing_pugi / existing_project → no
160
+ *
161
+ * Caller must additionally gate on TTY + non-json mode. Exported so a
162
+ * UI layer can reuse the same decision rule without re-implementing
163
+ * the state switch.
164
+ */
165
+ export function shouldOfferInit(state) {
166
+ return state.kind === 'bare' || state.kind === 'inside_parent_projects';
167
+ }
168
+ /**
169
+ * Convenience formatter: synthesize the prompt text U7 / U8 callers
170
+ * surface to the operator on the bare/inside-parents paths. The text
171
+ * is plain ASCII; the UI layer wraps it in Ink as needed.
172
+ */
173
+ export function formatInitPrompt(state, cwd) {
174
+ switch (state.kind) {
175
+ case 'bare':
176
+ return `No project detected at ${cwd}. Run \`pugi init\` here?`;
177
+ case 'inside_parent_projects': {
178
+ const lines = state.parents.map((p) => ` - ${projectLabel(p.root, p.marker)} (${p.root})`);
179
+ return `Found ${state.parents.length} parent project(s):\n${lines.join('\n')}\nPick one above or run \`pugi init\` here.`;
180
+ }
181
+ default:
182
+ return '';
183
+ }
184
+ }
185
+ /* β1b r1: dropped the `_internal` re-export. It was a leftover from
186
+ * an earlier spec that asserted module load order; the test was
187
+ * removed but the export lingered. No callers consume it inside the
188
+ * monorepo (verified via repo-wide grep), and `verbatimModuleSyntax`
189
+ * is happy with the module's regular exports. */
190
+ //# sourceMappingURL=bootstrap.js.map