pi-plans 0.1.2 → 0.3.0
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 +98 -19
- package/index.ts +147 -66
- package/package.json +7 -1
- package/references/pi-planning-workflow.md +21 -3
- package/references/state-and-config.md +35 -3
- package/scripts/validate.ts +4 -0
- package/src/autocomplete.ts +163 -0
- package/src/code-graph/commands.ts +437 -0
- package/src/code-graph/discovery.ts +118 -0
- package/src/code-graph/git.ts +108 -0
- package/src/code-graph/identity.ts +59 -0
- package/src/code-graph/indexer.ts +281 -0
- package/src/code-graph/materialize.ts +166 -0
- package/src/code-graph/mode.ts +28 -0
- package/src/code-graph/mutations.ts +160 -0
- package/src/code-graph/parser.ts +51 -0
- package/src/code-graph/parsers/javascript.ts +35 -0
- package/src/code-graph/parsers/python.ts +160 -0
- package/src/code-graph/parsers/tree-sitter.ts +316 -0
- package/src/code-graph/paths.ts +85 -0
- package/src/code-graph/prompts.ts +18 -0
- package/src/code-graph/resolver.ts +69 -0
- package/src/code-graph/runtime.ts +158 -0
- package/src/code-graph/schema.ts +135 -0
- package/src/code-graph/screening.ts +82 -0
- package/src/code-graph/store.ts +278 -0
- package/src/code-graph/summary.ts +435 -0
- package/src/code-graph/types.ts +163 -0
- package/src/compaction.ts +1256 -0
- package/src/config-command.ts +326 -0
- package/src/exec.ts +519 -625
- package/src/plan.ts +37 -0
- package/src/query-hook.ts +82 -0
- package/src/refine-prompts.ts +50 -0
- package/src/refine-ui-helpers.ts +142 -0
- package/src/refine-ui-state.ts +144 -0
- package/src/refine-ui.ts +430 -0
- package/src/state.ts +24 -29
- package/src/subagent.ts +299 -70
- package/tests/ask-choice.test.ts +263 -0
- package/tests/autocomplete.test.ts +147 -0
- package/tests/code-graph-apply.test.ts +185 -0
- package/tests/code-graph-commands.test.ts +211 -0
- package/tests/code-graph-db.test.ts +166 -0
- package/tests/code-graph-discovery.test.ts +38 -0
- package/tests/code-graph-git.test.ts +94 -0
- package/tests/code-graph-index.test.ts +175 -0
- package/tests/code-graph-loop.e2e.test.ts +159 -0
- package/tests/code-graph-mutations.test.ts +117 -0
- package/tests/code-graph-parser.test.ts +85 -0
- package/tests/code-graph-rollback.test.ts +100 -0
- package/tests/code-graph-summary-batching.test.ts +518 -0
- package/tests/code-graph-summary.test.ts +148 -0
- package/tests/compaction.test.ts +388 -0
- package/tests/config-command.test.ts +255 -0
- package/tests/exec.test.ts +751 -422
- package/tests/execute-plan.test.ts +65 -0
- package/tests/fixtures/code-graph/sample.js +36 -0
- package/tests/fixtures/code-graph/sample.py +20 -0
- package/tests/fixtures/code-graph/sample.ts +15 -0
- package/tests/graph-aware-file-tools.test.ts +411 -0
- package/tests/plan.test.ts +11 -1
- package/tests/plans.test.ts +6 -5
- package/tests/query-hook.test.ts +82 -0
- package/tests/refine-prompts.test.ts +67 -2
- package/tests/refine-ui.test.ts +392 -0
- package/tests/state.test.ts +12 -15
- package/tests/subagent.test.ts +120 -0
- package/tools/ask-choice.ts +180 -11
- package/tools/code-graph.ts +254 -0
- package/tools/execute-plan.ts +7 -39
- package/tools/graph-aware-file-tools.ts +392 -0
- package/tools/plans.ts +84 -18
- package/tools/refine.ts +180 -80
- package/src/execution-panel.ts +0 -633
- package/tests/execution-panel.test.ts +0 -234
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<h2 align="center"><b>Plan. Review. Execute.</b></h2>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
|
-
<i>Versioned, reviewed Markdown plans land before any code changes.<br>Human-in-the-loop planning for the Pi coding agent
|
|
10
|
+
<i>Versioned, reviewed Markdown plans land before any code changes.<br>Human-in-the-loop planning for the <a href="https://github.com/earendil-works/pi">Pi coding agent</a>.</i>
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
<a href="https://www.npmjs.com/package/pi-plans"><img alt="npm downloads" src="https://img.shields.io/npm/dt/pi-plans?color=38bdf8" /></a>
|
|
17
17
|
<a href="https://www.npmjs.com/package/pi-plans"><img alt="npm version" src="https://img.shields.io/npm/v/pi-plans?color=60a5fa" /></a>
|
|
18
18
|
<a href="https://github.com/earendil-works/pi"><img alt="Pi package" src="https://img.shields.io/badge/Pi-package-fbbf24" /></a>
|
|
19
|
+
<a href="https://github.com/earendil-works/pi"><img alt="Pi coding agent" src="https://img.shields.io/badge/Pi%20coding%20agent-earendil--works-22d3ee" /></a>
|
|
19
20
|
<a href="./LICENSE"><img alt="License" src="https://img.shields.io/npm/l/pi-plans?color=22c55e" /></a>
|
|
20
21
|
<a href="https://github.com/MaxInGaussian/pi-plans/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/MaxInGaussian/pi-plans/actions/workflows/ci.yml/badge.svg" /></a>
|
|
21
22
|
</p>
|
|
@@ -62,7 +63,7 @@ A rough change request becomes a versioned Markdown plan instead of a surprise d
|
|
|
62
63
|
tracked execution loop
|
|
63
64
|
fused AGENTS.md × Ponytail executor rules
|
|
64
65
|
checklist injected each turn, [DONE:VC-xxx]
|
|
65
|
-
markers tracked via bottom status bar
|
|
66
|
+
markers tracked via bottom status bar
|
|
66
67
|
|
|
|
67
68
|
v
|
|
68
69
|
run status: done
|
|
@@ -112,13 +113,15 @@ Planning artifacts live under `./docs/pi-plans/YYYY-MM-DD-<topic>/` by default (
|
|
|
112
113
|
| Capability | In short |
|
|
113
114
|
|---|---|
|
|
114
115
|
| Planning router + five specialist skills | Start with `/skill:planning` to route to the narrowest matching specialist (`plan-small` → `plan-big`, `debug-and-plan`, `plan-with-refs`) |
|
|
115
|
-
| Choice prompts | `ask_choice`: recommended option first, answers auto-recorded per run |
|
|
116
|
-
| Refinement rounds | Read-only reviewer/criticizer Pi subagents consolidate findings into the next plan version |
|
|
116
|
+
| Choice prompts | `ask_choice`: recommended option first, answers auto-recorded per run; choosing Auto-complete enables recommendation-only answers for later eligible questions in the current planning run, with `/plans-autocomplete-stop` available to take back control. After execution completes, the continuation prompt enters goal-running mode by default: it asks only for the implementation-review loop's termination condition and then keeps refining until the loop ends or the cap is reached. |
|
|
117
|
+
| Refinement rounds | Read-only reviewer/criticizer Pi subagents consolidate findings into the next plan version; delegated runs have standalone `Reviewer`/`Criticizer` progress overlays that close before the tool result returns |
|
|
117
118
|
| Workspace state | Config, runs, decisions, refs, and subagent ledgers in `.git/pi_plans/` (git common dir) |
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
|
|
|
121
|
-
|
|
|
119
|
+
| VCC compact | Active planning/execution compaction uses deterministic, no-LLM VCC-style summaries when Pi core emits manual `/compact`, threshold, or overflow events. Summaries use five bracket sections plus a brief transcript, keep a smart recent tail, support `keep:N`, and write VCC details/stats without adding `/pi-vcc` commands. |
|
|
120
|
+
| Visible Refiner overlay | Delegated reviewer/criticizer subagents surface as a named public overlay in the TUI — one `Reviewer`/`Criticizer` panel with per-lane tool progress, full streaming transcript with follow-bottom scroll, Tab-pane focus, retention until the user presses `Esc` after completion, and clean cancelled/timed-out vs completed states. `reviewers: 3` renders three equal-height panes inside the same overlay |
|
|
121
|
+
| Tracked execution | Checklist injected each turn; `[DONE:VC-xxx]` markers drive completion; implementation items report progress with `[I-xxx:implemented]` / `[I-xxx:validating]` markers; the bottom status bar shows lifecycle, `x/y` progress, elapsed time, and input/output token usage in real time |
|
|
122
|
+
| Execution handoff | The accepted plan resumes in the current session model; no separate model selection is performed. |
|
|
123
|
+
| Execution-phase compaction | Pi core owns scheduling; pi-plans maps the active plan path, current `I-###`, implementation IDs, and remaining `VC-###` checklist into the VCC sections. The old current-I proactive trigger and model-generated summary path are removed. |
|
|
124
|
+
| Planning-phase compaction | During `run.status=planning` with no active execution, pi-plans maps active run, artifact directory, latest plan path from session entries, and observed current-I markers into the VCC sections. Without an active planning run, compaction returns to Pi core. |
|
|
122
125
|
| Efficient executor prompt | Each turn, the executor is steered by a fused rule set — Marcos Hernanz's AGENTS.md principles × Ponytail minimalism: layered growth, simplest implementation, long-term architecture (no stopgaps), library discipline — so plans finish in fewer tokens and fewer detours |
|
|
123
126
|
| Write guard | `edit`/`write` blocked outside planning artifacts while a run is active |
|
|
124
127
|
|
|
@@ -126,17 +129,40 @@ Planning artifacts live under `./docs/pi-plans/YYYY-MM-DD-<topic>/` by default (
|
|
|
126
129
|
|
|
127
130
|
| Tool / Command | Purpose |
|
|
128
131
|
|---|---|
|
|
129
|
-
| `plans` | State CLI: `init`, `show`, `set-language`, `set-artifact-root`, `set-
|
|
132
|
+
| `plans` | State CLI: `init`, `show`, `set-language`, `set-artifact-root`, `set-role`, `start-run`, `set-status`, `record-decision`, `record-ref`, `record-subagent` |
|
|
130
133
|
| `ask_choice` | Numbered choice prompt; `autoComplete: false` for the merged accept/execute question and external-state questions |
|
|
131
|
-
| `refine` | Reviewer/criticizer round via read-only subagents (`--tools read,grep,find,ls`); `reviewers: 3`
|
|
132
|
-
| `execute_plan` | Execution handoff: re-confirms with the user
|
|
134
|
+
| `refine` | Reviewer/criticizer round via standalone read-only subagents (`--mode json -p --no-session --tools read,grep,find,ls`, plus `code_graph` for both roles when the workspace has the code graph enabled); `target: "plan"` (default) reviews the plan, `target: "implementation"` reviews the implemented worktree against the plan; delegated TUI runs show one `Reviewer`/`Criticizer` overlay (78% width × 78% height, top-center, ≥72 cols) with per-lane transcript, follow-bottom scroll, Tab focus, and retention until `Esc`; `reviewers: 3` renders three equal-height panes; enforces role/model confirmation gates |
|
|
135
|
+
| `execute_plan` | Execution handoff: re-confirms with the user and enters extension-managed execution mode |
|
|
133
136
|
| `/plans` | Show config, active run, and execution progress |
|
|
134
|
-
| `/plans
|
|
135
|
-
| `/plans-execute [plan.md]` | Manual execution handoff (defaults to highest `PLAN_vN.md
|
|
137
|
+
| `/config-pi-plans` | Re-ask workspace defaults for language, artifact root, code graph, reviewer mode/model, and criticizer mode/model |
|
|
138
|
+
| `/plans-execute [plan.md]` | Manual execution handoff (defaults to highest `PLAN_vN.md`) |
|
|
136
139
|
| `/update-plan [plan.md] [reason…]` | Interrupt-and-refine: stops execution (if any), returns the run to planning, and directs the agent to revise the plan into `PLAN_vN+1.md` while preserving verified work |
|
|
140
|
+
| `/plans-autocomplete-stop` | Stop the current run's Auto-complete mode and return later planning questions to normal interaction |
|
|
137
141
|
| `/plans-stop` | Stop execution mode |
|
|
138
142
|
| `/plans-abandon` | Abandon the active run (lifts the write guard; artifacts stay) |
|
|
139
|
-
| Status bar (lifecycle) | 💬 Q&A → 📝 draft written (planning sub-phases) → ⌛ executing `x/y · spent · in/out-toks` in the
|
|
143
|
+
| Status bar (lifecycle) | 💬 Q&A → 📝 draft written (planning sub-phases) → ⌛ executing `x/y · spent · in/out-toks` in the bottom status bar → ⛔ stopped / 🎯 done / 🚫 abandoned |
|
|
144
|
+
|
|
145
|
+
## VCC compact
|
|
146
|
+
|
|
147
|
+
Pi core remains the owner of compaction scheduling: manual `/compact`, threshold, and overflow events are emitted by Pi as usual. During an active pi-plans planning or execution run, pi-plans handles `session_before_compact` with a deterministic VCC-style compiler instead of calling a model for a summary.
|
|
148
|
+
|
|
149
|
+
- **Summary shape.** The summary contains exactly five bracket sections: `[Session Goal]`, `[Files And Changes]`, `[Commits]`, `[Outstanding Context]`, and `[User Preferences]`, followed by `---` and a ranked brief transcript. Execution contributes plan path, current `I-###`, implementation IDs, and remaining verifier IDs; planning contributes run ID, artifact directory, latest plan path from session entries, and any observed current-I marker.
|
|
150
|
+
- **Session-only input.** Compact summaries are built from the event's branch entries, previous summary, file ops, pi-plans custom session entries, and live phase state. The compiler does not read plan files, git history, or the worktree to invent context.
|
|
151
|
+
- **Tail policy.** The default keep is one recent user turn; smart keep may retain more turns when the tail is still small. Explicit `keep:N` is honored, while no-anchor and oversized-tail cases use a deterministic token-budget cut that avoids starting retained context with an orphan tool result.
|
|
152
|
+
- **Manual matrix.** Plain `/compact` and `/compact keep:N` compact and show stats without continuing. `/compact <text>` and `/compact keep:N <text>` compact, then send the text once as the follow-up prompt. Internal pi-plans compaction markers are never reused as user follow-up prompts.
|
|
153
|
+
- **Fallbacks and stats.** Unsafe manual/threshold cuts cancel with a warning; overflow or retrying unsafe cuts return control to Pi core. Successful VCC compactions notify with kept-tail and summarized-message stats. Threshold/overflow compactions may queue one hidden continuation only when the running Pi version still needs it and `continueAfterThresholdCompact` is enabled.
|
|
154
|
+
- **Repo-private config.** Defaults are scaffolded in `.git/pi_plans/pi-vcc-config.json` under the resolved git common dir: `overrideDefaultCompaction:true`, `smartKeepTail:true`, `continueAfterThresholdCompact:true`, `debug:false`. Global pi-vcc config and `PI_VCC_CONFIG_PATH` are intentionally ignored.
|
|
155
|
+
|
|
156
|
+
## Visible Refiner overlay
|
|
157
|
+
|
|
158
|
+
Delegated `refine` rounds (reviewer or criticizer) show their progress directly inside the Pi TUI instead of disappearing into the child process's terminal. The overlay is a public, named panel so users always know who is doing what:
|
|
159
|
+
|
|
160
|
+
- **Pi-btw-aligned geometry.** Each round uses `width: "78%"`, `minWidth: 72`, `maxHeight: "78%"`, `anchor: "top-center"`, and `{ top: 1, left: 2, right: 2 }` margins (no dependency on `pi-btw`; the renderer is built on Pi's public `pi-tui` primitives).
|
|
161
|
+
- **Complete streaming transcript.** Assistant text, thinking blocks, tool calls, tool results, and stderr are merged per turn/content block into lane entries without overlay-facing truncation; only the viewport slices them. Final `message_end` / `tool_execution_end` overwrite the live snapshot with the authoritative content.
|
|
162
|
+
- **No input row.** The overlay has no composer, no submit path, and no printable input forwarding. Only `Esc`, `Tab`/`Shift+Tab`, `↑/↓`, `PgUp/PgDn`, and SGR mouse wheel are consumed; everything else is ignored by design.
|
|
163
|
+
- **Equal-height panes for `reviewers: 3`.** Concurrent reviewer rounds render one reviewer lane per subagent as three independent equal-height panes inside the same top-center overlay; each pane keeps its own scroll offset and `follow-bottom` state. `Tab`/`Shift+Tab` switches the focused pane and scroll keys only affect it.
|
|
164
|
+
- **Lifecycle.** The overlay opens at round start, advances via the JSONL progress feed emitted by `pi --mode json`, and is dismissed by `Esc`. `Esc` is close-only — it never aborts the refiner child; the child keeps running to natural completion and its result still flows back through the tool result path. A new refinement round replaces any retained finished overlay to avoid overlay stacking. Cancelled and timed-out children render as terminal states with the original error message — never as silent drops.
|
|
165
|
+
- **Tool-only progress.** The overlay only consumes tool and message lifecycle events from the child; unrelated `pi` events are ignored, so a noisy upstream release does not desync the panel.
|
|
140
166
|
|
|
141
167
|
## The execution rules
|
|
142
168
|
|
|
@@ -154,6 +180,9 @@ Once you approve the handoff, every turn injects a compact rule set that fuses M
|
|
|
154
180
|
|
|
155
181
|
The rules cost four lines per turn and buy back far more: fewer wrong turns, shorter implementation paths, plans that finish in fewer tokens.
|
|
156
182
|
|
|
183
|
+
Waiting for subprocess-backed verification:
|
|
184
|
+
For subprocess-backed verification, when a step starts a subprocess and needs its result before verifying, use literal `waiting for` with backoff `5s -> 10s -> 20s -> 40s -> 80s`, then keep polling at 80s; restart at 5s for each new subprocess.
|
|
185
|
+
|
|
157
186
|
## Skills
|
|
158
187
|
|
|
159
188
|
Invoked via `resources_discover`, callable as `/skill:<name>`, directly as `/<name>` (e.g. `/planning`, `/plan-small` — extension aliases that forward to the skill), or picked automatically from the task description.
|
|
@@ -188,18 +217,65 @@ or register the absolute path in `~/.pi/agent/settings.json`:
|
|
|
188
217
|
{ "extensions": ["/absolute/path/to/pi-plans"] }
|
|
189
218
|
```
|
|
190
219
|
|
|
220
|
+
## Code graph (v0.3+)
|
|
221
|
+
|
|
222
|
+
`/init-graph` walks the worktree, parses JavaScript/TypeScript and Python
|
|
223
|
+
files with Tree-sitter, and stores a normalized function graph in
|
|
224
|
+
`.git/pi_plans/code_graph.db`. The DB is the canonical source for downstream
|
|
225
|
+
agents: function rows expose a low-token `description`/`inputs`/`outputs`
|
|
226
|
+
JSON view, call edges are normalized with `in_links`/`out_links` derived on
|
|
227
|
+
read, and each function retains its full UTF-8 source.
|
|
228
|
+
|
|
229
|
+
- `/init-graph [--reindex] [--no-summary] [--no-commit]` — scan the worktree and write the graph; if `code_graph.db` already exists, it first asks whether to rebuild or sync changed paths via `/update-graph` (non-interactive runs and `--reindex` stay on the rebuild path). With `--reindex` it keeps the existing full-worktree reindex semantics on the rebuild path. Dirty trees get a `chore(code-graph): pre-init snapshot` commit first (`--no-commit` skips). After indexing it records a `code_graph_snapshot` (HEAD + uncommitted paths) that `/graph-drift` compares against. The parser dependencies are installed via npm (`tree-sitter`, grammars).
|
|
230
|
+
- `/graph-status` — print function/file/edge counts.
|
|
231
|
+
- `/update-graph [--dry-run] [--base <commit>]` — incrementally reindex only the paths `git status --porcelain` reports (including untracked and rename targets); deleted files' DB rows are purged, never resurrected. `/init-graph` uses this path when you choose the sync-changes branch.
|
|
232
|
+
- `/graph-drift [--json] [--commit-aware]` — direction-aware convergence check:
|
|
233
|
+
(a) per-file hash match or a pending apply marker, (b) every uncommitted
|
|
234
|
+
indexable path is indexed, (c) snapshot vs current HEAD (informational).
|
|
235
|
+
- `/apply-graph [--force]` — materialize DB edits back to source. Files with
|
|
236
|
+
`pending_kind='update'` are written (created when missing on disk);
|
|
237
|
+
`pending_kind='delete'` files are removed from disk and the DB; pending-null
|
|
238
|
+
missing files are skipped, never resurrected. Refuses when the active
|
|
239
|
+
planning run is `planning`/`accepted`.
|
|
240
|
+
- `/enable-graph` / `/disable-graph` — toggle the `graph_enabled` config
|
|
241
|
+
flag (disable refuses while drift is dirty). When enabled, planner/refiner/
|
|
242
|
+
executor prompts hard-require function-level reads for indexed code, and the
|
|
243
|
+
built-in `read`/`write`/`edit` tools become graph-aware overrides for
|
|
244
|
+
indexed source files: `read` returns a capped function digest (≤50 lines,
|
|
245
|
+
synthetic anonymous entries folded) with `full: true` as the only whole-file
|
|
246
|
+
exit (small/zero-function files return full text); `write`/`edit` stage
|
|
247
|
+
DB-first mutations; unexpected fallbacks (not indexed / runtime unavailable /
|
|
248
|
+
config unreadable) are marked in the result; refiner and criticizer
|
|
249
|
+
subagents get the `code_graph` tool in their allowlist (verified in headless
|
|
250
|
+
no-session children); the executor loop
|
|
251
|
+
becomes DB-first: `code_graph` mutations → `/apply-graph` → `/graph-drift`
|
|
252
|
+
→ `plans final-commit` → `/init-graph`.
|
|
253
|
+
- The `code_graph` tool provides read-only screening (`status`, `screening`,
|
|
254
|
+
`get-function`, `manifest`), DB-first mutations (`update-function`,
|
|
255
|
+
`update-file`, `delete-file` — all mark files `pending_materialization`
|
|
256
|
+
and append to `change_log`), and `list-pending` so agents can navigate and
|
|
257
|
+
edit the graph without pulling `full_code`.
|
|
258
|
+
|
|
259
|
+
Runtime requirements: the base extension still requires Node ≥ 22.6; the
|
|
260
|
+
graph feature additionally requires Node ≥ 22.13 (or `--experimental-sqlite`)
|
|
261
|
+
so that `node:sqlite` is available without flag. Pi's host currently ships
|
|
262
|
+
Node ≥ 22.19, so a fresh install works out of the box. On unsupported
|
|
263
|
+
runtimes (Bun, missing parsers) graph commands fail locally without
|
|
264
|
+
affecting the planning workflow.
|
|
265
|
+
|
|
191
266
|
## Layout
|
|
192
267
|
|
|
193
268
|
```
|
|
194
269
|
pi-plans/
|
|
195
270
|
├── index.ts # Extension entry: tools, commands, guard, execution loop
|
|
196
|
-
├── tools/ # plans, ask-choice, refine, execute-plan
|
|
197
|
-
├── src/ # state, guard, plan parsing, subagent runner, exec loop
|
|
271
|
+
├── tools/ # plans, ask-choice, refine, execute-plan, code-graph
|
|
272
|
+
├── src/ # state, guard, plan parsing, subagent runner, refine overlay, exec loop
|
|
273
|
+
│ └── code-graph/ # SQLite schema/store, parsers, indexer, summary, materialize
|
|
198
274
|
├── skills/ # The planning router plus five specialist planning skills
|
|
199
275
|
├── references/ # Shared workflow, state/config, plan template (normative)
|
|
200
276
|
├── agents/ # reviewer.md / criticizer.md subagent prompts
|
|
201
277
|
├── scripts/validate.ts # Structure validator
|
|
202
|
-
└── tests/ # node:test suite (state, guard, plan parsing, execution)
|
|
278
|
+
└── tests/ # node:test suite (state, guard, plan parsing, execution, refine progress, code-graph)
|
|
203
279
|
```
|
|
204
280
|
|
|
205
281
|
## Safety model
|
|
@@ -213,7 +289,10 @@ npm run validate # structure validator
|
|
|
213
289
|
npm test # node:test suite (stdlib only, no deps)
|
|
214
290
|
```
|
|
215
291
|
|
|
216
|
-
Both run on Node ≥ 22.6 via `--experimental-strip-types
|
|
292
|
+
Both run on Node ≥ 22.6 via `--experimental-strip-types`. The graph
|
|
293
|
+
extension additionally requires `node:sqlite` (Node ≥ 22.13 unflagged, or
|
|
294
|
+
any Node ≥ 22.6 with `--experimental-sqlite`) and the four parser
|
|
295
|
+
dependencies listed in `dependencies`.
|
|
217
296
|
|
|
218
297
|
## FAQ
|
|
219
298
|
|
|
@@ -223,7 +302,7 @@ The plan is the contract. Refinement converges on scope while nothing is writabl
|
|
|
223
302
|
|
|
224
303
|
**What can Auto-complete decide on my behalf?**
|
|
225
304
|
|
|
226
|
-
Planning and refinement choices only (the recommended option). It is never offered for execution approval, installs, publishing, deployment, merge, push, or credentials — those questions stop and wait for you.
|
|
305
|
+
Planning and refinement choices only (the recommended option). Choosing Auto-complete enables the recommended answer for later eligible planning questions in the current run and the extension continues the planning turn when the model stops early. Use `/plans-autocomplete-stop` to take back control. It is never offered for execution approval, installs, publishing, deployment, merge, push, or credentials — those questions stop and wait for you. After execution completes, interactive sessions enter goal-running review mode automatically and ask only for the implementation-review loop's termination condition; the loop then continues until that condition or the 5-round cap. Headless sessions stay silent.
|
|
227
306
|
|
|
228
307
|
**Where does all the state live?**
|
|
229
308
|
|
package/index.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - `refine` tool — reviewer/criticizer rounds via read-only pi subagents
|
|
11
11
|
* - `execute_plan` — execution handoff into the tracked execution loop
|
|
12
12
|
* - write guard — planning runs may only write planning artifacts
|
|
13
|
-
* - execution loop — checklist injection, [DONE:VC-xxx] tracking, progress
|
|
13
|
+
* - execution loop — checklist injection, [DONE:VC-xxx] tracking, progress status
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
@@ -19,7 +19,6 @@ import * as path from "node:path";
|
|
|
19
19
|
import { dirname, join } from "node:path";
|
|
20
20
|
import { fileURLToPath } from "node:url";
|
|
21
21
|
import {
|
|
22
|
-
consumePendingPanelSync,
|
|
23
22
|
consumePlanningCompactionResumeGuard,
|
|
24
23
|
drainExecutionFlush,
|
|
25
24
|
executionContextMessage,
|
|
@@ -29,25 +28,44 @@ import {
|
|
|
29
28
|
handleExecutionBeforeCompact,
|
|
30
29
|
handleExecutionCompact,
|
|
31
30
|
handleExecutionCompactFailed,
|
|
31
|
+
handleExecutionTurnCompaction,
|
|
32
32
|
handlePlanningBeforeCompact,
|
|
33
33
|
handlePlanningCompact,
|
|
34
34
|
handlePlanningCompactFailed,
|
|
35
|
+
noteCompactionEnded,
|
|
36
|
+
noteCompactionStarted,
|
|
35
37
|
PLANNING_PLAN_WRITTEN_CUSTOM_TYPE,
|
|
36
38
|
registerExecutionTurnHandlers,
|
|
37
|
-
recordTouchedPaths,
|
|
38
39
|
refreshPlanningCompactionCooldown,
|
|
39
40
|
requestPlanningCompaction,
|
|
40
41
|
restoreFromSession,
|
|
41
|
-
ensureExecutionModelActive,
|
|
42
42
|
stopExecution,
|
|
43
|
-
syncExecutionPanel,
|
|
44
|
-
toggleExecutionPanelView,
|
|
45
43
|
updateStatusWidget,
|
|
46
44
|
shouldTriggerPlanningCompaction,
|
|
47
45
|
} from "./src/exec.ts";
|
|
46
|
+
import {
|
|
47
|
+
autoCompleteStatus,
|
|
48
|
+
disableAutoComplete,
|
|
49
|
+
markPlanWritten,
|
|
50
|
+
registerAutoCompleteTurnHandlers,
|
|
51
|
+
restoreAutoCompleteFromSession,
|
|
52
|
+
} from "./src/autocomplete.ts";
|
|
48
53
|
import { planningWriteBlockReason } from "./src/guard.ts";
|
|
54
|
+
import { registerQueryInterviewHooks } from "./src/query-hook.ts";
|
|
55
|
+
import { registerCodeGraphTool } from "./tools/code-graph.ts";
|
|
56
|
+
import { registerGraphAwareFileTools } from "./tools/graph-aware-file-tools.ts";
|
|
57
|
+
import {
|
|
58
|
+
initGraphCommand,
|
|
59
|
+
applyGraphCommand,
|
|
60
|
+
graphStatusCommand,
|
|
61
|
+
updateGraphCommand,
|
|
62
|
+
graphDriftCommand,
|
|
63
|
+
enableGraphCommand,
|
|
64
|
+
disableGraphCommand,
|
|
65
|
+
} from "./src/code-graph/commands.ts";
|
|
49
66
|
import { latestPlanVersion, nextPlanVersionPath } from "./src/plan.ts";
|
|
50
|
-
import {
|
|
67
|
+
import { configPiPlansCommand } from "./src/config-command.ts";
|
|
68
|
+
import { getRun, loadConfig, readActive, recordDecision, resolveStateRootOrNull, setRunStatus } from "./src/state.ts";
|
|
51
69
|
import { registerAskChoiceTool } from "./tools/ask-choice.ts";
|
|
52
70
|
import { executeHandoff, registerExecutePlanTool } from "./tools/execute-plan.ts";
|
|
53
71
|
import { registerPlansTool } from "./tools/plans.ts";
|
|
@@ -63,12 +81,17 @@ const extensionLoadedAt = new Date();
|
|
|
63
81
|
function extensionStalenessLine(): string {
|
|
64
82
|
try {
|
|
65
83
|
const dirs = [baseDir, path.join(baseDir, "src"), path.join(baseDir, "tools")];
|
|
84
|
+
const stack: string[] = [...dirs];
|
|
66
85
|
let newest = 0;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
86
|
+
while (stack.length) {
|
|
87
|
+
const dir = stack.pop()!;
|
|
88
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
89
|
+
const full = path.join(dir, entry.name);
|
|
90
|
+
if (entry.isDirectory()) stack.push(full);
|
|
91
|
+
else if (entry.isFile() && entry.name.endsWith(".ts")) {
|
|
92
|
+
const mtime = fs.statSync(full).mtimeMs;
|
|
93
|
+
if (mtime > newest) newest = mtime;
|
|
94
|
+
}
|
|
72
95
|
}
|
|
73
96
|
}
|
|
74
97
|
if (newest > extensionLoadedAt.getTime() + 2000) {
|
|
@@ -80,20 +103,12 @@ function extensionStalenessLine(): string {
|
|
|
80
103
|
}
|
|
81
104
|
}
|
|
82
105
|
|
|
83
|
-
function
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
cleaned.includes("/") ||
|
|
90
|
-
cleaned.startsWith(".") ||
|
|
91
|
-
cleaned.startsWith("~") ||
|
|
92
|
-
/^[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+$/.test(cleaned);
|
|
93
|
-
if (!looksLikePath) continue;
|
|
94
|
-
values.add(cleaned);
|
|
95
|
-
}
|
|
96
|
-
return [...values];
|
|
106
|
+
function hasActivePlanningWorkflow(ctx: Parameters<typeof updateStatusWidget>[0]): boolean {
|
|
107
|
+
if (getExecution()) return true;
|
|
108
|
+
const active = readActive(ctx.cwd);
|
|
109
|
+
if (!active) return false;
|
|
110
|
+
const status = getRun(ctx.cwd, active.run_id)?.status;
|
|
111
|
+
return status === "planning" || status === "accepted" || status === "executing";
|
|
97
112
|
}
|
|
98
113
|
|
|
99
114
|
export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
@@ -101,6 +116,9 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
101
116
|
registerAskChoiceTool(pi);
|
|
102
117
|
registerRefineTool(pi, baseDir);
|
|
103
118
|
registerExecutePlanTool(pi);
|
|
119
|
+
registerQueryInterviewHooks(pi, hasActivePlanningWorkflow);
|
|
120
|
+
registerCodeGraphTool(pi);
|
|
121
|
+
registerGraphAwareFileTools(pi);
|
|
104
122
|
|
|
105
123
|
// Contribute the router skill plus the five specialist planning skills.
|
|
106
124
|
pi.on("resources_discover", () => ({
|
|
@@ -142,25 +160,14 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
142
160
|
// not been approved), edit/write may only target planning artifacts.
|
|
143
161
|
// -----------------------------------------------------------------------
|
|
144
162
|
pi.on("tool_call", async (event, ctx) => {
|
|
145
|
-
|
|
146
|
-
if (execution) {
|
|
147
|
-
if (event.toolName === "edit" || event.toolName === "write") {
|
|
148
|
-
const rawPath = String((event.input as { path?: string }).path ?? "");
|
|
149
|
-
if (rawPath) recordTouchedPaths(ctx.cwd, [rawPath]);
|
|
150
|
-
}
|
|
151
|
-
if (event.toolName === "bash") {
|
|
152
|
-
const command = String((event.input as { command?: string }).command ?? "");
|
|
153
|
-
if (command) recordTouchedPaths(ctx.cwd, extractPathsFromBash(command));
|
|
154
|
-
}
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
163
|
+
if (getExecution()) return;
|
|
157
164
|
const rawPath = String((event.input as { path?: string }).path ?? "");
|
|
158
165
|
if (!rawPath) return;
|
|
159
166
|
const reason = planningWriteBlockReason({ workdir: ctx.cwd, toolName: event.toolName, rawPath });
|
|
160
167
|
if (reason) return { block: true, reason };
|
|
161
168
|
// Allowed write: if it lands exactly on the run's latest plan file, drop a
|
|
162
169
|
// marker entry so planning-phase compaction can anchor its cut point there.
|
|
163
|
-
if (event.toolName === "write") {
|
|
170
|
+
if (event.toolName === "write" || event.toolName === "edit") {
|
|
164
171
|
const active = readActive(ctx.cwd);
|
|
165
172
|
if (active) {
|
|
166
173
|
const latest = latestPlanVersion(active.artifact_dir);
|
|
@@ -169,12 +176,39 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
169
176
|
runId: active.run_id,
|
|
170
177
|
planPath: latest.path,
|
|
171
178
|
});
|
|
179
|
+
markPlanWritten(ctx);
|
|
172
180
|
}
|
|
173
181
|
}
|
|
174
182
|
}
|
|
175
183
|
return;
|
|
176
184
|
});
|
|
177
185
|
|
|
186
|
+
// Bidirectional code-graph reminder hook: separate from the planning guard
|
|
187
|
+
// above (which early-returns during execution). Fires only when the graph
|
|
188
|
+
// is enabled and an execution is active. Reminders are best-effort notifies.
|
|
189
|
+
pi.on("tool_call", async (event, ctx) => {
|
|
190
|
+
if (!getExecution()) return;
|
|
191
|
+
const stateRoot = resolveStateRootOrNull(ctx.cwd);
|
|
192
|
+
if (!stateRoot) return;
|
|
193
|
+
let graphEnabled = false;
|
|
194
|
+
try {
|
|
195
|
+
graphEnabled = loadConfig(stateRoot).graph_enabled === true;
|
|
196
|
+
} catch {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (!graphEnabled) return;
|
|
200
|
+
if (event.toolName === "edit" || event.toolName === "write") {
|
|
201
|
+
ctx.ui?.notify?.("code-graph: source edited directly — run /update-graph to sync the graph, or use code_graph mutations + /apply-graph for DB-first edits", "info");
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (event.toolName === "code_graph") {
|
|
205
|
+
const action = String((event.input as { action?: string }).action ?? "");
|
|
206
|
+
if (action === "update-function" || action === "update-file" || action === "delete-file") {
|
|
207
|
+
ctx.ui?.notify?.("code-graph: mutation staged — run /apply-graph to materialize, then /graph-drift to verify", "info");
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
178
212
|
pi.on("context", (event) => {
|
|
179
213
|
const filteredExecution = filterExecutionResumeMessages(event.messages as Array<{ customType?: string }>);
|
|
180
214
|
const messages = filterPlanningResumeMessages(filteredExecution);
|
|
@@ -184,17 +218,20 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
184
218
|
});
|
|
185
219
|
|
|
186
220
|
pi.on("session_before_compact", async (event, ctx) => {
|
|
221
|
+
noteCompactionStarted(ctx, event.customInstructions);
|
|
187
222
|
const executionResult = await handleExecutionBeforeCompact(pi, ctx, event);
|
|
188
223
|
if (executionResult) return executionResult;
|
|
189
224
|
return handlePlanningBeforeCompact(pi, ctx, event);
|
|
190
225
|
});
|
|
191
226
|
pi.on("session_compact", async (event, ctx) => {
|
|
192
|
-
handleExecutionCompact(pi, ctx, event);
|
|
193
|
-
handlePlanningCompact(pi, ctx, event);
|
|
227
|
+
await handleExecutionCompact(pi, ctx, event);
|
|
228
|
+
await handlePlanningCompact(pi, ctx, event);
|
|
229
|
+
noteCompactionEnded(ctx, event.customInstructions);
|
|
194
230
|
});
|
|
195
231
|
pi.on("session_compact_failed", async (event, ctx) => {
|
|
196
232
|
handleExecutionCompactFailed(pi, ctx, event);
|
|
197
233
|
handlePlanningCompactFailed(pi, ctx, event);
|
|
234
|
+
noteCompactionEnded(ctx, event.customInstructions);
|
|
198
235
|
});
|
|
199
236
|
|
|
200
237
|
// Flush points for deferred execution-loop writes: primary drain when the
|
|
@@ -210,8 +247,7 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
210
247
|
// -----------------------------------------------------------------------
|
|
211
248
|
pi.on("before_agent_start", async (_event, ctx) => {
|
|
212
249
|
drainExecutionFlush(pi, ctx);
|
|
213
|
-
|
|
214
|
-
const content = executionContextMessage();
|
|
250
|
+
const content = executionContextMessage(ctx);
|
|
215
251
|
if (!content) {
|
|
216
252
|
if (!getExecution() && shouldTriggerPlanningCompaction(ctx)) {
|
|
217
253
|
requestPlanningCompaction(ctx);
|
|
@@ -228,10 +264,11 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
228
264
|
});
|
|
229
265
|
|
|
230
266
|
registerExecutionTurnHandlers(pi, async (ctx) => {
|
|
231
|
-
if (
|
|
267
|
+
if (getExecution()) {
|
|
268
|
+
handleExecutionTurnCompaction(ctx);
|
|
269
|
+
} else {
|
|
232
270
|
refreshPlanningCompactionCooldown(ctx);
|
|
233
271
|
if (consumePlanningCompactionResumeGuard(ctx)) {
|
|
234
|
-
if (consumePendingPanelSync()) syncExecutionPanel(ctx);
|
|
235
272
|
updateStatusWidget(ctx);
|
|
236
273
|
return;
|
|
237
274
|
}
|
|
@@ -239,24 +276,61 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
239
276
|
requestPlanningCompaction(ctx);
|
|
240
277
|
}
|
|
241
278
|
}
|
|
242
|
-
// A
|
|
243
|
-
// turn just ended, so this is the safe point to apply it.
|
|
244
|
-
if (consumePendingPanelSync()) syncExecutionPanel(ctx);
|
|
279
|
+
// A completed turn is the safe point for status updates.
|
|
245
280
|
updateStatusWidget(ctx);
|
|
246
281
|
});
|
|
282
|
+
registerAutoCompleteTurnHandlers(pi);
|
|
247
283
|
|
|
248
284
|
// -----------------------------------------------------------------------
|
|
249
|
-
// Commands
|
|
285
|
+
// Commands
|
|
250
286
|
// -----------------------------------------------------------------------
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
287
|
+
|
|
288
|
+
pi.registerCommand("init-graph", {
|
|
289
|
+
description: "Index the worktree into .git/pi_plans/code_graph.db. If a graph DB already exists, prompt to rebuild or sync changed paths via /update-graph; `--reindex` and non-interactive runs stay on the rebuild path.",
|
|
290
|
+
handler: async (args, ctx) => {
|
|
291
|
+
await initGraphCommand(args, ctx);
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
pi.registerCommand("apply-graph", {
|
|
296
|
+
description: "Apply code_graph.db changes back to source. Refuses during active planning/accepted run.",
|
|
297
|
+
handler: async (args, ctx) => {
|
|
298
|
+
await applyGraphCommand(args, ctx);
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
pi.registerCommand("graph-status", {
|
|
303
|
+
description: "Show code graph counts (functions, files, edges).",
|
|
304
|
+
handler: async (args, ctx) => {
|
|
305
|
+
await graphStatusCommand(args, ctx);
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
pi.registerCommand("update-graph", {
|
|
310
|
+
description: "Incrementally reindex working-tree changes (git status porcelain, incl. untracked/renames) into code_graph.db. Also used by /init-graph when you choose the sync-changes branch. Flags: --dry-run, --base <commit>.",
|
|
311
|
+
handler: async (args, ctx) => {
|
|
312
|
+
await updateGraphCommand(args, ctx);
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
pi.registerCommand("graph-drift", {
|
|
317
|
+
description: "Check DB↔source convergence (hash/pending, uncommitted coverage, snapshot). Flags: --json, --commit-aware.",
|
|
318
|
+
handler: async (args, ctx) => {
|
|
319
|
+
await graphDriftCommand(args, ctx);
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
pi.registerCommand("enable-graph", {
|
|
324
|
+
description: "Enable the code graph: agents prefer graph reads and DB-first edits.",
|
|
325
|
+
handler: async (_args, ctx) => {
|
|
326
|
+
await enableGraphCommand(_args, ctx);
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
pi.registerCommand("disable-graph", {
|
|
331
|
+
description: "Disable the code graph (refuses while DB/source drift is dirty).",
|
|
332
|
+
handler: async (_args, ctx) => {
|
|
333
|
+
await disableGraphCommand(_args, ctx);
|
|
260
334
|
},
|
|
261
335
|
});
|
|
262
336
|
|
|
@@ -283,20 +357,24 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
283
357
|
lines.push(` ${item.done ? "☑" : "☐"} ${item.id}`);
|
|
284
358
|
}
|
|
285
359
|
}
|
|
360
|
+
lines.push(`Auto-complete: ${autoCompleteStatus(ctx)}`);
|
|
286
361
|
lines.push(extensionStalenessLine());
|
|
287
362
|
ctx.ui.notify(lines.join("\n"), "info");
|
|
288
363
|
},
|
|
289
364
|
});
|
|
290
365
|
|
|
291
|
-
pi.registerCommand("plans
|
|
292
|
-
description: "
|
|
366
|
+
pi.registerCommand("config-pi-plans", {
|
|
367
|
+
description: "Re-ask and update pi-plans workspace config: language, artifact root, graph, reviewer, and criticizer defaults",
|
|
368
|
+
handler: async (args, ctx) => {
|
|
369
|
+
await configPiPlansCommand(args, ctx);
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
pi.registerCommand("plans-autocomplete-stop", {
|
|
374
|
+
description: "Stop Auto-complete for the active planning run",
|
|
293
375
|
handler: async (_args, ctx) => {
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
ctx.ui.notify("No execution in progress.", "info");
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
ctx.ui.notify(expanded ? "Execution checklist expanded." : "Execution checklist collapsed.", "info");
|
|
376
|
+
const stopped = disableAutoComplete(ctx, "stopped by user");
|
|
377
|
+
ctx.ui.notify(stopped ? "Auto-complete stopped." : "Auto-complete is not active.", stopped ? "info" : "warning");
|
|
300
378
|
},
|
|
301
379
|
});
|
|
302
380
|
|
|
@@ -333,6 +411,7 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
333
411
|
|
|
334
412
|
const active = readActive(ctx.cwd);
|
|
335
413
|
const execution = getExecution();
|
|
414
|
+
disableAutoComplete(ctx, "plan update");
|
|
336
415
|
|
|
337
416
|
// Resolve the plan to revise: explicit arg > running execution > latest in artifact dir.
|
|
338
417
|
let sourcePlanPath: string | null = planArg
|
|
@@ -441,6 +520,7 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
441
520
|
);
|
|
442
521
|
if (!ok) return;
|
|
443
522
|
// Abandon must end execution first so the planning model is restored.
|
|
523
|
+
disableAutoComplete(ctx, "run abandoned");
|
|
444
524
|
if (getExecution()) {
|
|
445
525
|
await stopExecution(pi, ctx, "run abandoned via /plans-abandon");
|
|
446
526
|
}
|
|
@@ -459,5 +539,6 @@ export default function piPlansExtension(pi: ExtensionAPI): void {
|
|
|
459
539
|
// -----------------------------------------------------------------------
|
|
460
540
|
pi.on("session_start", async (_event, ctx) => {
|
|
461
541
|
await restoreFromSession(pi, ctx, ctx.sessionManager.getEntries() as unknown as Parameters<typeof restoreFromSession>[2]);
|
|
542
|
+
restoreAutoCompleteFromSession(ctx, ctx.sessionManager.getEntries() as unknown as Parameters<typeof restoreAutoCompleteFromSession>[1]);
|
|
462
543
|
});
|
|
463
544
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-plans",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Human-in-the-loop planning extension for the Pi coding agent: researched, refined Markdown plans before any code changes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -54,5 +54,11 @@
|
|
|
54
54
|
"validate": "node --experimental-strip-types scripts/validate.ts",
|
|
55
55
|
"test": "node --experimental-strip-types scripts/run-tests.ts",
|
|
56
56
|
"prepack": "npm run validate && npm test"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"tree-sitter": "^0.25.1",
|
|
60
|
+
"tree-sitter-javascript": "^0.25.0",
|
|
61
|
+
"tree-sitter-python": "^0.25.0",
|
|
62
|
+
"tree-sitter-typescript": "^0.23.2"
|
|
57
63
|
}
|
|
58
64
|
}
|