phonton-cli 0.8.2 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -5
- package/npm/bin/phonton.js +48 -2
- package/npm/install.js +15 -0
- package/npm/test-wrapper.js +69 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<img src="assets/readme/phonton-cli-logo.png" width="112" alt="Phonton CLI logo">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
<h1 align="center">Phonton CLI · v0.
|
|
5
|
+
<h1 align="center">Phonton CLI · v0.9.1</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<strong>Verified code changes with repo memory.</strong><br>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<p align="center">
|
|
13
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
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.
|
|
15
|
+
<img alt="release" src="https://img.shields.io/badge/release-v0.9.1-6c63ff">
|
|
16
16
|
<img alt="license" src="https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue">
|
|
17
17
|
<img alt="status" src="https://img.shields.io/badge/status-public_alpha-f97316">
|
|
18
18
|
</p>
|
|
@@ -69,7 +69,7 @@ It walks through the evidence trail a real run should expose: GoalContract, plan
|
|
|
69
69
|
## What Works Today
|
|
70
70
|
|
|
71
71
|
- Interactive Ratatui TUI with goal, task, ask, settings, git, and flight-log surfaces.
|
|
72
|
-
- Unified slash commands in the TUI: `/settings`, `/config`, `/status`, `/context`, `/compact`, `/compress`, `/goals`, `/switch`, `/focus`, `/copy`, `/rerun`, `/stats`, `/stop`, `/review`, `/memory`, `/permissions`, `/model`, `/commands`, `/run`, and `!` all route through the same command registry and prompt drawer.
|
|
72
|
+
- Unified slash commands in the TUI: `/settings`, `/config`, `/status`, `/context`, `/compact`, `/compress`, `/goals`, `/switch`, `/focus`, `/copy`, `/rerun`, `/stats`, `/stop`, `/review`, `/memory`, `/permissions`, `/trust`, `/model`, `/commands`, `/run`, and `!` all route through the same command registry and prompt drawer.
|
|
73
73
|
- Faster multi-goal navigation: the sidebar shows stable goal indexes, `Alt+Up` / `Alt+Down` switches goals even while drafting text, `Alt+1` through `Alt+9` jumps directly, and `/goals` opens a searchable switcher.
|
|
74
74
|
- Review-ready goals now default to a Code focus view when diff hunks are available, with Receipt, Code, Commands, and Log tabs in the Active panel plus `f` / `[` / `]` keyboard navigation.
|
|
75
75
|
- Command run receipts stay collapsed by default; the Commands focus view shows status, exit code, duration, and short stdout/stderr previews. `/rerun` repeats the latest command through the same sandbox path and `/copy` copies the current focus view to the Windows clipboard.
|
|
@@ -78,6 +78,9 @@ It walks through the evidence trail a real run should expose: GoalContract, plan
|
|
|
78
78
|
- Image path paste/drop artifacts: pasted image file paths collapse into `[image: name.png]` chips and flow into the submitted prompt as image artifacts.
|
|
79
79
|
- Active review/code output is scrollable with the mouse wheel, `PgUp` / `PgDn`, and `Home` / `End`, so large generated diffs do not trap the user at the top of the receipt.
|
|
80
80
|
- Windows clipboard import in the TUI with `Ctrl+V`, including content selected from Windows clipboard history (`Win+V`) when the terminal does not emit bracketed paste directly.
|
|
81
|
+
- Lower-noise worker prompts: first attempts omit bulky diff examples, duplicate repo context slices are deduped, and Flight Log prompt manifests show repo-code, compaction, dedupe, and budget buckets.
|
|
82
|
+
- Resumed sessions keep recent prompt history, and the History view supports in-place filtering and row selection for inspecting previous task receipts.
|
|
83
|
+
- Workspace trust is saved as structured per-workspace records, mirrored into the local store, visible with `/trust current` or `/trust list`, and revocable with `/trust revoke-current`.
|
|
81
84
|
- Sandboxed command runs from the prompt bar with `/run <cmd>` or `!<cmd>`, plus command status, output previews, context meters, and permission mode controls in the TUI and Flight Log.
|
|
82
85
|
- `phonton doctor` setup diagnostics for config, provider key, store, trust, git, cargo, and Nexus config.
|
|
83
86
|
- `phonton plan` preview for task DAGs and the visible GoalContract before edits happen.
|
|
@@ -132,7 +135,7 @@ Windows PowerShell:
|
|
|
132
135
|
Direct Cargo install:
|
|
133
136
|
|
|
134
137
|
```bash
|
|
135
|
-
cargo install --git https://github.com/phonton-dev/phonton-cli --tag v0.
|
|
138
|
+
cargo install --git https://github.com/phonton-dev/phonton-cli --tag v0.9.1 phonton-cli --locked --force
|
|
136
139
|
```
|
|
137
140
|
|
|
138
141
|
Check the install:
|
|
@@ -148,7 +151,7 @@ Phonton uses GitHub branches and releases as install channels:
|
|
|
148
151
|
|
|
149
152
|
| Channel | Install | Use when |
|
|
150
153
|
|---|---|---|
|
|
151
|
-
| Stable | `cargo install --git https://github.com/phonton-dev/phonton-cli --tag v0.
|
|
154
|
+
| Stable | `cargo install --git https://github.com/phonton-dev/phonton-cli --tag v0.9.1 phonton-cli --locked --force` | You want the best validated public alpha |
|
|
152
155
|
| Dev | `cargo install --git https://github.com/phonton-dev/phonton-cli --branch dev phonton-cli --locked --force` | You want next-release integration changes |
|
|
153
156
|
| Nightly | `cargo install --git https://github.com/phonton-dev/phonton-cli --branch nightly phonton-cli --locked --force` | You want daily snapshots and can tolerate breakage |
|
|
154
157
|
| Main | `cargo install --git https://github.com/phonton-dev/phonton-cli --branch main phonton-cli --locked --force` | You want the current release branch tip |
|
|
@@ -253,6 +256,7 @@ Inside the TUI prompt bar:
|
|
|
253
256
|
/review Show review receipt guidance for the selected goal
|
|
254
257
|
/memory Inspect local decision memory
|
|
255
258
|
/permissions Show sandbox, trust, and approval status
|
|
259
|
+
/trust Show or revoke workspace trust records
|
|
256
260
|
/model set <name> Save a model preference
|
|
257
261
|
/commands Show slash-command and keyboard help
|
|
258
262
|
/run <cmd> Run a sandboxed command
|
package/npm/bin/phonton.js
CHANGED
|
@@ -4,14 +4,18 @@ 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");
|
|
7
8
|
const binaryName = process.platform === "win32" ? "phonton.exe" : "phonton";
|
|
8
9
|
const configuredBinary = process.env.PHONTON_BINARY || process.env.PHONTON_CLI_BINARY;
|
|
9
10
|
const binaryPath = configuredBinary
|
|
10
11
|
? path.resolve(configuredBinary)
|
|
11
12
|
: path.join(__dirname, "..", "vendor", binaryName);
|
|
13
|
+
const vendorDir = path.join(__dirname, "..", "vendor");
|
|
14
|
+
const markerPath = path.join(vendorDir, "version.json");
|
|
12
15
|
|
|
13
16
|
function ensureBinary() {
|
|
14
|
-
if (fs.existsSync(binaryPath)) {
|
|
17
|
+
if (configuredBinary && fs.existsSync(binaryPath)) {
|
|
18
|
+
assertBinaryVersion(binaryPath);
|
|
15
19
|
return;
|
|
16
20
|
}
|
|
17
21
|
|
|
@@ -20,11 +24,53 @@ function ensureBinary() {
|
|
|
20
24
|
process.exit(1);
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
|
|
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");
|
|
24
34
|
const result = spawnSync(process.execPath, [installScript], { stdio: "inherit" });
|
|
25
35
|
if (result.status !== 0 || !fs.existsSync(binaryPath)) {
|
|
26
36
|
process.exit(result.status || 1);
|
|
27
37
|
}
|
|
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
|
+
};
|
|
28
74
|
}
|
|
29
75
|
|
|
30
76
|
ensureBinary();
|
package/npm/install.js
CHANGED
|
@@ -12,6 +12,7 @@ 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");
|
|
15
16
|
|
|
16
17
|
const targets = {
|
|
17
18
|
"linux-x64": {
|
|
@@ -55,6 +56,20 @@ download(url, archivePath)
|
|
|
55
56
|
if (process.platform !== "win32") {
|
|
56
57
|
fs.chmodSync(binaryPath, 0o755);
|
|
57
58
|
}
|
|
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
|
+
);
|
|
58
73
|
console.log(`Installed Phonton CLI ${tag} for ${process.platform}-${process.arch}`);
|
|
59
74
|
})
|
|
60
75
|
.catch((error) => {
|
package/npm/test-wrapper.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const fs = require("fs");
|
|
4
|
+
const os = require("os");
|
|
4
5
|
const path = require("path");
|
|
5
6
|
const { spawnSync } = require("child_process");
|
|
6
7
|
|
|
@@ -46,6 +47,8 @@ if (!versionOutput.includes(expected)) {
|
|
|
46
47
|
process.exit(1);
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
testStaleVendorReinstall();
|
|
51
|
+
|
|
49
52
|
const goal = "add input validation to config loading";
|
|
50
53
|
const planOutput = runWrapper(["plan", "--json", "--no-memory", goal]);
|
|
51
54
|
let planJson;
|
|
@@ -65,3 +68,69 @@ if (planJson.goal_contract.goal !== goal) {
|
|
|
65
68
|
console.error("Expected plan --json goal_contract.goal to match the requested goal.");
|
|
66
69
|
process.exit(1);
|
|
67
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.
|
|
3
|
+
"version": "0.9.1",
|
|
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",
|