phonton-cli 0.17.1 → 0.19.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 CHANGED
@@ -1,120 +1,132 @@
1
1
  <p align="center">
2
- <img src="assets/readme/phonton-cli-logo.png" width="112" alt="Phonton CLI logo">
2
+ <img src="assets/readme/phonton-cli-logo.png" width="128" alt="Phonton CLI logo">
3
3
  </p>
4
4
 
5
- <h1 align="center">Phonton CLI · v0.17.1</h1>
5
+ <h1 align="center">Phonton CLI v0.19.0</h1>
6
6
 
7
7
  <p align="center">
8
- <strong>Verified code changes with local repo memory.</strong><br>
9
- A local-first agentic development environment (ADE) for developers who want autonomous code changes without giving up review control.
8
+ <strong>Your keys. Your code. The autonomous coding agent that never phones home.</strong><br>
9
+ Phonton is a local-first agentic development environment (ADE) built around the loop: <code>goal plan edit ➔ verify ➔ review ➔ remember</code>.
10
10
  </p>
11
11
 
12
12
  <p align="center">
13
- <a href="https://github.com/phonton-dev/phonton-cli/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/phonton-dev/phonton-cli/actions/workflows/ci.yml/badge.svg"></a>
14
- <a href="https://github.com/phonton-dev/phonton-cli/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/phonton-dev/phonton-cli?style=flat&label=stars"></a>
15
- <img alt="release" src="https://img.shields.io/badge/release-v0.17.1-6c63ff">
13
+ <a href="https://github.com/phonton-dev/phonton-cli/actions/workflows/ci.yml"><img alt="CI Status" src="https://github.com/phonton-dev/phonton-cli/actions/workflows/ci.yml/badge.svg"></a>
14
+ <a href="https://github.com/phonton-dev/phonton-cli/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/phonton-dev/phonton-cli?style=flat&label=stars&color=ff69b4"></a>
15
+ <img alt="release" src="https://img.shields.io/badge/release-v0.19.0-6c63ff">
16
16
  <img alt="license" src="https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue">
17
17
  </p>
18
18
 
19
19
  ---
20
20
 
21
- Phonton plans the work, routes it through local repo context, verifies changes before handoff, and keeps the result reviewable. The goal is not to be the loudest coding agent. The goal is to make AI-assisted development reliable and transparent.
21
+ ## 💡 What is Phonton?
22
+
23
+ Every AI coding assistant makes you trade privacy for autonomy. To get an agentic experience, you either hand your code to a SaaS vendor's proxy servers, or settle for inline autocompletion.
24
+
25
+ **Phonton is the first tool to deliver both: fully agentic development and absolute, uncompromising privacy.**
26
+
27
+ Phonton runs as a local-first, headless-ready terminal tool. Your code never leaves your machine. Your API keys go straight to Anthropic, OpenAI, Gemini, or Ollama. No intermediate proxy, no telemetry hooks, and no subscription required.
22
28
 
23
29
  <p align="center">
24
- <img src="assets/readme/phonton-cli-hero.png" alt="Phonton CLI hero with terminal UI preview">
30
+ <img src="assets/readme/phonton-cli-hero.png" alt="Phonton CLI hero with terminal UI preview" width="800">
25
31
  </p>
26
32
 
27
- ## ⚡ Quick Install
33
+ ---
28
34
 
29
- The easiest install path is npm. This downloads a prebuilt GitHub Release binary during installation.
35
+ ## 🌟 Core Differentiators
30
36
 
31
- ```bash
32
- # Install globally via npm
33
- npm install -g phonton-cli
37
+ ### 1. Zero-Telemetry BYOK (Bring Your Own Key)
38
+ Phonton is proxy-free. Requests go directly to `api.anthropic.com`, `api.openai.com`, `generativelanguage.googleapis.com`, or your local `ollama` daemon. Phonton never intercepts your keys and never touches your code in transit. You can packet-capture the network to verify.
34
39
 
35
- # Or run directly without installing
36
- npx phonton-cli
37
- ```
40
+ ### 2. The Strict 4-Layer Verification Gate
41
+ Unlike other tools that silently write code and let LLM hallucinations ship, Phonton enforces a strict verification gate. Every diff must pass through **four layers** before it is marked as review-ready:
42
+ 1. **Tree-Sitter Syntax check**
43
+ 2. **Crate check (`cargo check`)**
44
+ 3. **Workspace Check (Lints & Format)**
45
+ 4. **Automated Test suite execution**
46
+ 5. **Interactive Browser rendering check** (Playwright checks + Screenshots in `v0.19.0`)
38
47
 
39
- ### Alternative Installation Methods
48
+ On failure, verifier diagnostics are surgically fed back to the worker for recursive repair loops.
40
49
 
41
- **macOS / Linux Shell Installer:**
42
- ```bash
43
- curl -fsSL https://raw.githubusercontent.com/phonton-dev/phonton-cli/main/scripts/install.sh | sh
44
- ```
50
+ ### 3. Multi-Model Intelligence Routing
51
+ Phonton routes subtasks by complexity using tiered model mapping (`Local ➔ Cheap ➔ Standard ➔ Frontier`). It automatically escalates to a more powerful model only on verify failure. You pay pennies for boilerplate and invoke frontier intelligence only when a task demands it.
45
52
 
46
- **Windows PowerShell Installer:**
47
- ```powershell
48
- & ([scriptblock]::Create((irm https://raw.githubusercontent.com/phonton-dev/phonton-cli/main/scripts/install.ps1)))
49
- ```
53
+ ### 4. Semantic Memory Across Sessions
54
+ Phonton maintains a persistent SQLite store of architectural decisions, rejected approaches, and task history. The planner consults this memory on every goal decomposition, ensuring it never re-attempts approaches that failed before and builds upon approved design patterns.
50
55
 
51
- **Direct Cargo Install (Builds from Source):**
52
- ```bash
53
- cargo install --git https://github.com/phonton-dev/phonton-cli --tag v0.17.1 phonton-cli --locked --force
54
- ```
56
+ ---
57
+
58
+ ## Quick Install
59
+
60
+ The easiest path to install is via npm. The wrapper automatically downloads the prebuilt binary for your platform.
55
61
 
56
- Verify your installation:
57
62
  ```bash
63
+ # Install globally
64
+ npm install -g phonton-cli
65
+
66
+ # Verify your installation
58
67
  phonton version
59
68
  phonton doctor
60
69
  ```
61
70
 
62
- ---
63
-
64
- ## 💡 Why Phonton
71
+ ### Alternative Installers
72
+
73
+ * **Shell Script (macOS/Linux)**:
74
+ ```bash
75
+ curl -fsSL https://raw.githubusercontent.com/phonton-dev/phonton-cli/main/scripts/install.sh | sh
76
+ ```
77
+ * **PowerShell (Windows)**:
78
+ ```powershell
79
+ & ([scriptblock]::Create((irm https://raw.githubusercontent.com/phonton-dev/phonton-cli/main/scripts/install.ps1)))
80
+ ```
81
+ * **Cargo (From Source)**:
82
+ ```bash
83
+ cargo install --git https://github.com/phonton-dev/phonton-cli --tag v0.19.0 phonton-cli --locked --force
84
+ ```
65
85
 
66
- Most coding agents start with chat. Phonton starts with the engineering loop:
67
-
68
- ```mermaid
69
- flowchart LR
70
- A["Goal"] --> B["Plan preview"]
71
- B --> C["Repo-aware worker"]
72
- C --> D["Verification gate"]
73
- D --> E["Reviewable diff"]
74
- E --> F["Memory and history"]
75
- F --> B
76
- ```
86
+ ---
77
87
 
78
- This structural architecture gives Phonton a distinct advantage for serious code editing:
88
+ ## ⚖️ How We Compare
79
89
 
80
- - **Review First:** Diffs are first-class, fully interactive terminal surfaces, not buried in a chat stream.
81
- - **Verification First:** Diffs are validated via Tree-sitter syntax checks and test suites before presentation.
82
- - **Local First:** Settings, session store, local history, and vector memory live entirely on your machine.
83
- - **AST Quality Gates:** In-process tree-sitter validators catch parsing issues across Rust, Python, TypeScript, and more in **under 50ms**.
84
- - **BYOK (Bring Your Own Key):** Connect directly to Anthropic, OpenAI, DeepSeek, Gemini, xAI, or local Ollama with zero server proxying.
90
+ | Feature | Phonton CLI | Claude Code | Cursor | Aider |
91
+ |---|---|---|---|---|
92
+ | **Privacy Model** | **100% Direct (No Proxy)** | Anthropic Proxy | Cursor Proxy | Direct (No Proxy) |
93
+ | **Telemetry** | **Zero** | Opt-out | Opt-out | Optional |
94
+ | **Multi-Model Support** | **All (BYOK & Local)** | Anthropic Only | Pre-selected | Many |
95
+ | **Subscription Fee** | **$0 (Open Source)** | Usage-based | $20/month | $0 (Open Source) |
96
+ | **Execution Loop** | **Full Plan/Edit/Verify** | Interactive Chat | Interactive Chat | Interactive Chat |
97
+ | **Verification Gates** | **Mandatory 4-Layer** | Manual/Run Command | Manual | Optional |
98
+ | **Memory Spine** | **Semantic SQLite** | None | Simple Context | None |
85
99
 
86
100
  ---
87
101
 
88
- ## 🏆 Benchmark Results
102
+ ## 🔄 The Autonomous ADE Loop
89
103
 
90
- Phonton prioritizes surgical context retrieval over massive, expensive whole-repo context dumps. We run continuous, auditable benchmarks against popular coding agents under the exact same prompts, fixtures, and execution bounds.
104
+ ```mermaid
105
+ flowchart TD
106
+ Goal["Goal (User Request)"] --> Plan["1. Goal Decomposition (Planner)"]
107
+ Plan --> Graph["2. PlanGraph & Conflict Groups Staged"]
108
+ Graph --> Dispatch["3. Concurrent / Serialized Worker Dispatch"]
109
+ Dispatch --> Edit["4. Bounded Code Modifications (Diff-Only)"]
110
+ Edit --> Verify{"5. Strict Verification Gate"}
111
+ Verify -- FAIL: Surgical Repair Prompt --> Edit
112
+ Verify -- PASS --> Review["6. Reviewable Handoff (HandoffPacket)"]
113
+ Review --> Remember["7. SQLite Memory & Session Snapshot Saved"]
114
+ ```
91
115
 
92
- ### 1. Headline Benchmarking Comparison
116
+ ---
93
117
 
94
- | Suite | Tool | Status | Elapsed Time | Input Tokens | Output Tokens | Cached Tokens | Total Tokens | Changed Paths |
95
- |---|---|---|---|---|---|---|---|---:|
96
- | **`02-bugfix`** | **Phonton v0.17.1** | **verified_success** | **38.6s** | **2,006** | **730** | **1,280** | **2,736** | **1** |
97
- | | Claude Code | completed | 58.0s | 212 | 3,261 | 163,137 | 203,018 | 1 |
98
- | | DeepSeek-TUI | completed | 88.2s | 28,490 | 1,210 | 22,400 | 52,100 | 1 |
99
- | | Gemini CLI | completed | 199.8s | 95,008 | 1,948 | 113,770 | 214,287 | 1 |
100
- | | Codex CLI | completed | 218.9s | 379,331 | 5,515 | 346,624 | 384,846 | 2 |
101
- | **`03-refactor`** | **Phonton v0.17.1** | **verified_success** | **50.6s** | **5,164** | **5,034** | **768** | **10,198** | **2** |
102
- | | Gemini CLI | completed | 118.4s | 76,079 | 5,092 | 453,239 | 536,583 | 2 |
103
- | | DeepSeek-TUI | completed | 112.5s | 42,300 | 4,890 | 55,600 | 102,790 | 2 |
104
- | | Claude Code | completed | 156.7s | 2,821 | 11,781 | 176,187 | 224,947 | 2 |
105
- | | Codex CLI | completed | 229.0s | 451,983 | 8,479 | 412,416 | 460,462 | 2 |
118
+ ## 🚀 New in v0.19.0: Swarm Planning & Pluggable Indices
106
119
 
107
- ### 2. Core Takeaways
108
- * **98%+ Token Savings:** Swapping generic directory dumps for high-speed local semantic memories gives Phonton a massive token-usage saving.
109
- * **Microsecond Context Retrieval:** The concurrent HNSW vector index searches 1,000 architectural concepts in just **158.697µs**, yielding highly targeted model prompts.
110
- * **Grammar Quality Guard:** Preflight checks compile and verify AST structures locally before touching the git tree, guaranteeing syntax safety.
120
+ * **Conflict-Aware Swarm Scheduling (`PlanGraph`)**: Broad goals are decomposed into collaborative swarms. Overlapping touch scopes are isolated into Conflict Groups and serialized, while independent subtasks run concurrently to optimize execution time.
121
+ * **Pluggable Code Indexing**: Upgraded `phonton-index` with a pluggable `CodeRetriever` trait. Supports default high-performance `local-hnsw` search and external `qdrant` HTTP vector storage for larger enterprise repositories.
122
+ * **Dynamic MCP Capability Discovery**: Run `phonton mcp capabilities <server-id> [--yes]` to preview server info, exposed tools, and sandbox permission proposals safely before initiating any tool execution.
123
+ * **Robust Browser Verification**: Dynamically injected `NODE_PATH` resolution guarantees Playwright DOM and interaction tests run flawlessly on isolated temp directories and production workspaces alike.
111
124
 
112
125
  ---
113
126
 
114
- ## ⚙️ Quick Start & Setup
127
+ ## ⚙️ Configuration
115
128
 
116
- ### 1. Configure a Provider
117
- Phonton looks for credentials inside `~/.phonton/config.toml`. Create it with a minimal configuration:
129
+ Configure your direct providers and indexing backend in `~/.phonton/config.toml`:
118
130
 
119
131
  ```toml
120
132
  [provider]
@@ -124,50 +136,62 @@ model = "deepseek-v4-flash"
124
136
  [provider.keys]
125
137
  deepseek = "sk-deepseek-api-key-here"
126
138
  anthropic = "sk-ant-api-key-here"
139
+ openai = "sk-proj-openai-key-here"
140
+
141
+ [index]
142
+ backend = "local-hnsw"
127
143
  ```
128
144
 
129
- ### 2. Auto-Import Credentials
130
- Alternatively, automatically import API keys from standard environments:
131
- ```bash
132
- export DEEPSEEK_API_KEY="sk-..."
133
- phonton providers import-opencode
145
+ To enable the external **Qdrant** backend:
146
+
147
+ ```toml
148
+ [index]
149
+ backend = "qdrant"
150
+ qdrant_url = "http://127.0.0.1:6333"
151
+ qdrant_collection = "phonton-code"
134
152
  ```
135
153
 
136
- ### 3. Verify Configuration
137
- Ensure everything is set up correctly:
154
+ ---
155
+
156
+ ## 🛠️ Commands Reference
157
+
138
158
  ```bash
159
+ # Launch the interactive Ratatui TUI
160
+ phonton
161
+
162
+ # Run a goal non-interactively through the full plan/edit/verify pipeline
163
+ phonton goal "add input validation to config loading" --yes
164
+
165
+ # Preview the subtask graph and Conflict Groups without editing files
166
+ phonton plan "refactor auth layer"
167
+
168
+ # Audit configuration, API keys, database, and vector index connectivity
139
169
  phonton doctor --provider
140
- ```
141
170
 
142
- ### 4. Run the Trust-Loop Demo
143
- Explore Phonton's evidence trail (GoalContract, AST checking, verification gates) locally without sending remote model calls:
144
- ```bash
145
- phonton demo trust-loop
171
+ # Export benchmark telemetry from the latest run
172
+ phonton benchmark export --latest --format json
146
173
  ```
147
174
 
148
175
  ---
149
176
 
150
- ## 🛠️ CLI Command Reference
177
+ ## 🗺️ Crate Architecture
151
178
 
152
- Execute commands directly from your shell or use the interactive Ratatui TUI dashboard.
153
-
154
- * **`phonton`**: Starts the interactive Ratatui terminal UI dashboard for managing tasks, reviewing plans, and executing rollbacks.
155
- * **`phonton goal "<prompt>"`**: Submit a long-running, multi-step engineering goal in headless mode. Supports `--prompt-file <path>` and `--yes` for automated scripts.
156
- * **`phonton ask "<question>"`**: Ask a workspace-aware, semantic question. Mentions (e.g. `@src/lib.rs`) are automatically gathered into context.
157
- * **`phonton diff`**: Export verified unified diffs from completed subtasks in the task store. Supports `--stat` and `--name-only`.
158
- * **`phonton doctor`**: Run diagnostics on tool installations (git, cargo, npm) and provider key routing.
159
- * **`phonton extensions`**: Manage extension packs. Install MCP servers, custom profiles, or steering guides.
160
- * Install an MCP recipe: `phonton extensions install github`
179
+ Phonton is written entirely in Rust for performance, correctness, and low memory overhead:
180
+ * `phonton-cli`: Interactive TUI, headless runner, benchmark, and CLI commands.
181
+ * `phonton-planner`: Multi-model goal decomposition and `PlanGraph` sidecar staging.
182
+ * `phonton-orchestrator`: Swarm scheduler, Conflict Group serialization, and verifier pipeline execution.
183
+ * `phonton-worker`: Highly optimized context assembler and diff-only code modifier.
184
+ * `phonton-index`: Local HNSW symbol index and Qdrant integration.
185
+ * `phonton-verify`: Four-layer static checkers (Tree-Sitter, Cargo, Playwright Browser/Screenshot).
186
+ * `phonton-mcp`: Lazy initialization client, permission gates, and capabilities descriptor.
161
187
 
162
188
  ---
163
189
 
164
- ## 🏁 Release Channels
190
+ ## 💖 Star History
191
+
192
+ If you support a privacy-first, fully autonomous developer experience, please leave us a star!
165
193
 
166
- | Channel | Install Command | Use Case |
167
- |---|---|---|
168
- | **Stable** | `cargo install --git https://github.com/phonton-dev/phonton-cli --tag v0.17.1 phonton-cli --locked --force` | Best validated release |
169
- | **Dev** | `cargo install --git https://github.com/phonton-dev/phonton-cli --branch dev phonton-cli --locked --force` | Upcoming release features |
170
- | **Nightly** | `cargo install --git https://github.com/phonton-dev/phonton-cli --branch nightly phonton-cli --locked --force` | Daily automated snapshots |
194
+ [![Star History Chart](https://api.star-history.com/chart?repos=phonton-dev/phonton-cli&type=date&legend=top-left)](https://www.star-history.com/?repos=phonton-dev%2Fphonton-cli&type=date&legend=top-left)
171
195
 
172
196
  ---
173
197
 
@@ -177,4 +201,4 @@ Licensed under either of:
177
201
  * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
178
202
  * MIT License ([LICENSE-MIT](LICENSE-MIT))
179
203
 
180
- at your option.
204
+ At your option.
@@ -4,18 +4,14 @@ const fs = require("fs");
4
4
  const path = require("path");
5
5
  const { spawn, spawnSync } = require("child_process");
6
6
 
7
- const packageJson = require("../../package.json");
8
7
  const binaryName = process.platform === "win32" ? "phonton.exe" : "phonton";
9
8
  const configuredBinary = process.env.PHONTON_BINARY || process.env.PHONTON_CLI_BINARY;
10
9
  const binaryPath = configuredBinary
11
10
  ? path.resolve(configuredBinary)
12
11
  : path.join(__dirname, "..", "vendor", binaryName);
13
- const vendorDir = path.join(__dirname, "..", "vendor");
14
- const markerPath = path.join(vendorDir, "version.json");
15
12
 
16
13
  function ensureBinary() {
17
- if (configuredBinary && fs.existsSync(binaryPath)) {
18
- assertBinaryVersion(binaryPath);
14
+ if (fs.existsSync(binaryPath)) {
19
15
  return;
20
16
  }
21
17
 
@@ -24,53 +20,11 @@ function ensureBinary() {
24
20
  process.exit(1);
25
21
  }
26
22
 
27
- if (fs.existsSync(binaryPath) && vendorMatchesPackage() && binaryVersionMatches(binaryPath).ok) {
28
- return;
29
- }
30
-
31
- fs.rmSync(vendorDir, { recursive: true, force: true });
32
-
33
- const installScript = process.env.PHONTON_INSTALL_SCRIPT || path.join(__dirname, "..", "install.js");
23
+ const installScript = path.join(__dirname, "..", "install.js");
34
24
  const result = spawnSync(process.execPath, [installScript], { stdio: "inherit" });
35
25
  if (result.status !== 0 || !fs.existsSync(binaryPath)) {
36
26
  process.exit(result.status || 1);
37
27
  }
38
- assertBinaryVersion(binaryPath);
39
- }
40
-
41
- function vendorMatchesPackage() {
42
- try {
43
- const marker = JSON.parse(fs.readFileSync(markerPath, "utf8"));
44
- return (
45
- marker.version === packageJson.version &&
46
- marker.platform === process.platform &&
47
- marker.arch === process.arch
48
- );
49
- } catch (_error) {
50
- return false;
51
- }
52
- }
53
-
54
- function assertBinaryVersion(candidate) {
55
- const check = binaryVersionMatches(candidate);
56
- if (!check.ok) {
57
- console.error(`Installed Phonton binary is stale or invalid: expected ${check.expected}, got ${check.output}`);
58
- if (!configuredBinary) {
59
- fs.rmSync(vendorDir, { recursive: true, force: true });
60
- }
61
- process.exit(1);
62
- }
63
- }
64
-
65
- function binaryVersionMatches(candidate) {
66
- const result = spawnSync(candidate, ["version"], { encoding: "utf8" });
67
- const output = `${result.stdout || ""}${result.stderr || ""}`.trim() || "no output";
68
- const expected = `phonton ${packageJson.version}`;
69
- return {
70
- ok: result.status === 0 && output.includes(expected),
71
- expected,
72
- output,
73
- };
74
28
  }
75
29
 
76
30
  ensureBinary();
package/npm/install.js CHANGED
@@ -12,7 +12,6 @@ const repo = "phonton-dev/phonton-cli";
12
12
  const version = packageJson.version;
13
13
  const tag = process.env.PHONTON_RELEASE_TAG || (version.includes("nightly") ? "nightly" : `v${version}`);
14
14
  const vendorDir = path.join(__dirname, "vendor");
15
- const markerPath = path.join(vendorDir, "version.json");
16
15
 
17
16
  const targets = {
18
17
  "linux-x64": {
@@ -56,20 +55,6 @@ download(url, archivePath)
56
55
  if (process.platform !== "win32") {
57
56
  fs.chmodSync(binaryPath, 0o755);
58
57
  }
59
- fs.writeFileSync(
60
- markerPath,
61
- `${JSON.stringify(
62
- {
63
- version,
64
- tag,
65
- asset: target.asset,
66
- platform: process.platform,
67
- arch: process.arch,
68
- },
69
- null,
70
- 2,
71
- )}\n`,
72
- );
73
58
  console.log(`Installed Phonton CLI ${tag} for ${process.platform}-${process.arch}`);
74
59
  })
75
60
  .catch((error) => {
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const fs = require("fs");
4
- const os = require("os");
5
4
  const path = require("path");
6
5
  const { spawnSync } = require("child_process");
7
6
 
@@ -19,118 +18,24 @@ if (!binary) {
19
18
  process.exit(1);
20
19
  }
21
20
 
22
- function runWrapper(args) {
23
- const result = spawnSync(process.execPath, [path.join(root, "npm", "bin", "phonton.js"), ...args], {
24
- cwd: root,
25
- encoding: "utf8",
26
- env: {
27
- ...process.env,
28
- PHONTON_BINARY: binary,
29
- },
30
- });
21
+ const result = spawnSync(process.execPath, [path.join(root, "npm", "bin", "phonton.js"), "version"], {
22
+ cwd: root,
23
+ encoding: "utf8",
24
+ env: {
25
+ ...process.env,
26
+ PHONTON_BINARY: binary,
27
+ },
28
+ });
31
29
 
32
- process.stdout.write(result.stdout || "");
33
- process.stderr.write(result.stderr || "");
30
+ process.stdout.write(result.stdout || "");
31
+ process.stderr.write(result.stderr || "");
34
32
 
35
- if (result.status !== 0) {
36
- process.exit(result.status || 1);
37
- }
38
-
39
- return result.stdout;
33
+ if (result.status !== 0) {
34
+ process.exit(result.status || 1);
40
35
  }
41
36
 
42
- const versionOutput = runWrapper(["version"]);
43
-
44
37
  const expected = `phonton ${packageJson.version}`;
45
- if (!versionOutput.includes(expected)) {
38
+ if (!result.stdout.includes(expected)) {
46
39
  console.error(`Expected npm wrapper to report ${expected}.`);
47
40
  process.exit(1);
48
41
  }
49
-
50
- testStaleVendorReinstall();
51
-
52
- const goal = "add input validation to config loading";
53
- const planOutput = runWrapper(["plan", "--json", "--no-memory", goal]);
54
- let planJson;
55
- try {
56
- planJson = JSON.parse(planOutput);
57
- } catch (error) {
58
- console.error(`Expected plan --json to emit parseable JSON: ${error.message}`);
59
- process.exit(1);
60
- }
61
-
62
- if (!planJson.goal_contract) {
63
- console.error("Expected plan --json to expose goal_contract at the top level.");
64
- process.exit(1);
65
- }
66
-
67
- if (planJson.goal_contract.goal !== goal) {
68
- console.error("Expected plan --json goal_contract.goal to match the requested goal.");
69
- process.exit(1);
70
- }
71
-
72
- function testStaleVendorReinstall() {
73
- const vendorDir = path.join(root, "npm", "vendor");
74
- const vendorBinary = path.join(vendorDir, binaryName);
75
- const markerPath = path.join(vendorDir, "version.json");
76
- const installScript = path.join(os.tmpdir(), `phonton-test-install-${process.pid}.js`);
77
-
78
- fs.rmSync(vendorDir, { recursive: true, force: true });
79
- fs.mkdirSync(vendorDir, { recursive: true });
80
- fs.copyFileSync(binary, vendorBinary);
81
- if (process.platform !== "win32") {
82
- fs.chmodSync(vendorBinary, 0o755);
83
- }
84
- fs.writeFileSync(
85
- markerPath,
86
- JSON.stringify({
87
- version: "0.0.0-stale",
88
- platform: process.platform,
89
- arch: process.arch,
90
- }),
91
- );
92
-
93
- fs.writeFileSync(
94
- installScript,
95
- `
96
- const fs = require("fs");
97
- const path = require("path");
98
- const vendorDir = ${JSON.stringify(vendorDir)};
99
- const binary = ${JSON.stringify(binary)};
100
- const binaryName = ${JSON.stringify(binaryName)};
101
- const version = ${JSON.stringify(packageJson.version)};
102
- fs.mkdirSync(vendorDir, { recursive: true });
103
- fs.copyFileSync(binary, path.join(vendorDir, binaryName));
104
- if (process.platform !== "win32") fs.chmodSync(path.join(vendorDir, binaryName), 0o755);
105
- fs.writeFileSync(path.join(vendorDir, "version.json"), JSON.stringify({
106
- version,
107
- platform: process.platform,
108
- arch: process.arch,
109
- }, null, 2));
110
- `,
111
- );
112
-
113
- try {
114
- const result = spawnSync(process.execPath, [path.join(root, "npm", "bin", "phonton.js"), "version"], {
115
- cwd: root,
116
- encoding: "utf8",
117
- env: {
118
- ...process.env,
119
- PHONTON_INSTALL_SCRIPT: installScript,
120
- PHONTON_BINARY: "",
121
- PHONTON_CLI_BINARY: "",
122
- },
123
- });
124
-
125
- process.stdout.write(result.stdout || "");
126
- process.stderr.write(result.stderr || "");
127
-
128
- if (result.status !== 0 || !result.stdout.includes(expected)) {
129
- console.error("Expected npm wrapper to refresh stale vendor binary metadata.");
130
- process.exit(result.status || 1);
131
- }
132
- } finally {
133
- fs.rmSync(installScript, { force: true });
134
- fs.rmSync(vendorDir, { recursive: true, force: true });
135
- }
136
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phonton-cli",
3
- "version": "0.17.1",
3
+ "version": "0.19.0",
4
4
  "description": "Local-first agentic development terminal with context packs, source handles, and verification gates.",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "homepage": "https://github.com/phonton-dev/phonton-cli#readme",
@@ -41,5 +41,9 @@
41
41
  ],
42
42
  "engines": {
43
43
  "node": ">=18"
44
+ },
45
+ "devDependencies": {
46
+ "@playwright/test": "^1.60.0",
47
+ "playwright": "^1.60.0"
44
48
  }
45
49
  }