loadout-ai 0.2.2 → 0.3.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/CHANGELOG.md +37 -0
- package/MASTER_PLAN.md +68 -33
- package/README.md +33 -1
- package/dist/src/cli.js +168 -17
- package/dist/src/core/active-set.js +37 -2
- package/dist/src/core/cli-guide.js +101 -0
- package/dist/src/core/completion.js +3 -0
- package/dist/src/core/mcp-recipes.js +21 -0
- package/dist/src/core/profile-state.js +101 -0
- package/dist/src/core/remove.js +6 -7
- package/dist/src/core/runtime-tool-recipe.js +10 -1
- package/dist/src/core/runtime-tools.js +24 -1
- package/dist/src/core/scheduler.js +2 -2
- package/dist/src/core/snapshot.js +15 -2
- package/dist/src/core/state.js +5 -2
- package/dist/src/core/uninstall.js +109 -0
- package/dist/src/core/update.js +87 -58
- package/dist/src/shared/schemas.js +12 -0
- package/docs/TESTING.md +25 -2
- package/docs/USER_TEST_GUIDE.md +176 -0
- package/docs/plans/2026-07-18-release-0.3.md +42 -0
- package/docs/superpowers/plans/2026-07-18-cli-ux-polish.md +86 -0
- package/package.json +1 -1
package/dist/src/core/update.js
CHANGED
|
@@ -85,66 +85,89 @@ async function analyzeManagedUpdate(oldRoot, newRoot, unitIds) {
|
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
87
|
/** Builds a read-only update plan from persisted installs and live GitHub snapshots. */
|
|
88
|
-
export async function buildUpdatePlan(resolver = async (repository) => fetchRepositorySnapshot(repository)) {
|
|
88
|
+
export async function buildUpdatePlan(resolver = async (repository) => fetchRepositorySnapshot(repository, { timeoutMs: 30_000 }), options = {}) {
|
|
89
89
|
const state = await readInstallState();
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
90
|
+
const records = options.packageId
|
|
91
|
+
? state.installs.filter((record) => record.packageId === options.packageId)
|
|
92
|
+
: state.installs;
|
|
93
|
+
const results = new Array(records.length);
|
|
94
|
+
let cursor = 0;
|
|
95
|
+
let completed = 0;
|
|
96
|
+
const workers = Array.from({
|
|
97
|
+
length: Math.min(Math.max(1, options.concurrency ?? 4), Math.max(1, records.length)),
|
|
98
|
+
}, async () => {
|
|
99
|
+
while (cursor < records.length) {
|
|
100
|
+
const index = cursor++;
|
|
101
|
+
const record = records[index];
|
|
102
|
+
results[index] = await (async () => {
|
|
103
|
+
const disabledAgents = (state.activations ?? [])
|
|
104
|
+
.filter((activation) => activation.packageId === record.packageId &&
|
|
105
|
+
activation.installationState === "installed" &&
|
|
106
|
+
activation.activationState === "disabled")
|
|
107
|
+
.map((activation) => activation.agent);
|
|
108
|
+
const base = {
|
|
109
|
+
packageId: record.packageId,
|
|
110
|
+
repository: record.repository,
|
|
111
|
+
installedCommit: record.resolvedCommit,
|
|
112
|
+
targetAgents: record.targetAgents,
|
|
113
|
+
...(disabledAgents.length ? { disabledAgents } : {}),
|
|
114
|
+
};
|
|
115
|
+
if (!record.repository || !record.resolvedCommit) {
|
|
116
|
+
return {
|
|
117
|
+
...base,
|
|
118
|
+
status: "untracked",
|
|
119
|
+
action: "Reinstall from the original source to begin update tracking.",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
const current = await resolver(record.repository);
|
|
124
|
+
const same = current.commit.toLowerCase() ===
|
|
125
|
+
record.resolvedCommit.toLowerCase();
|
|
126
|
+
let diff;
|
|
127
|
+
let safetyFindings;
|
|
128
|
+
let approvalRequired = false;
|
|
129
|
+
if (!same && current.path) {
|
|
130
|
+
const oldPath = repositoryCachePath(record.repository, record.resolvedCommit);
|
|
131
|
+
const analysis = await analyzeManagedUpdate(oldPath, current.path, managedUnitIds(state, record.packageId));
|
|
132
|
+
diff = analysis.diff;
|
|
133
|
+
safetyFindings = analysis.safetyFindings;
|
|
134
|
+
approvalRequired = analysis.approvalRequired;
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
...base,
|
|
138
|
+
availableCommit: current.commit,
|
|
139
|
+
status: same ? "up-to-date" : "update-available",
|
|
140
|
+
action: same
|
|
141
|
+
? "No action required."
|
|
142
|
+
: disabledAgents.length
|
|
143
|
+
? `Enable ${record.packageId} for ${disabledAgents.join(", ")} before applying an update; planning remains read-only.`
|
|
144
|
+
: approvalRequired
|
|
145
|
+
? `Approval required: review safety warnings before updating ${record.packageId}.`
|
|
146
|
+
: `Run loadout update --package ${record.packageId} --yes after review.`,
|
|
147
|
+
...(approvalRequired ? { approvalRequired: true } : {}),
|
|
148
|
+
...(safetyFindings?.length ? { safetyFindings } : {}),
|
|
149
|
+
...(diff ? { diff } : {}),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
return {
|
|
154
|
+
...base,
|
|
155
|
+
status: "error",
|
|
156
|
+
action: "Retry when GitHub is reachable; the installed version was not changed.",
|
|
157
|
+
error: error instanceof Error ? error.message : String(error),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
})();
|
|
161
|
+
completed += 1;
|
|
162
|
+
options.onProgress?.({
|
|
163
|
+
completed,
|
|
164
|
+
total: records.length,
|
|
165
|
+
packageId: record.packageId,
|
|
166
|
+
});
|
|
146
167
|
}
|
|
147
|
-
})
|
|
168
|
+
});
|
|
169
|
+
await Promise.all(workers);
|
|
170
|
+
return results;
|
|
148
171
|
}
|
|
149
172
|
export function formatUpdatePlan(plans) {
|
|
150
173
|
if (plans.length === 0)
|
|
@@ -160,6 +183,12 @@ export function formatUpdatePlan(plans) {
|
|
|
160
183
|
})
|
|
161
184
|
.join("\n");
|
|
162
185
|
}
|
|
186
|
+
/** Updates safe enough for an explicit whole-profile `update --yes` apply. */
|
|
187
|
+
export function selectSafeAutomaticUpdates(plans) {
|
|
188
|
+
return plans.filter((plan) => plan.status === "update-available" &&
|
|
189
|
+
!plan.approvalRequired &&
|
|
190
|
+
!plan.disabledAgents?.length);
|
|
191
|
+
}
|
|
163
192
|
function quarantineRoot() {
|
|
164
193
|
return join(loadoutHome(), "quarantine");
|
|
165
194
|
}
|
|
@@ -304,6 +304,18 @@ export const installStateSchema = z
|
|
|
304
304
|
installs: z.array(installRecordSchema),
|
|
305
305
|
mcpInstalls: z.array(mcpInstallRecordSchema).default([]),
|
|
306
306
|
activations: z.array(managedActivationRecordSchema).default([]),
|
|
307
|
+
profile: z
|
|
308
|
+
.object({
|
|
309
|
+
mode: z.enum(["stable", "power", "maximum", "custom"]),
|
|
310
|
+
packageIds: z.array(text).optional(),
|
|
311
|
+
agents: z.array(agentIdSchema),
|
|
312
|
+
catalogPackages: z.array(z.object({
|
|
313
|
+
packageId: text,
|
|
314
|
+
reviewedCommit: optionalText,
|
|
315
|
+
})),
|
|
316
|
+
appliedAt: text,
|
|
317
|
+
})
|
|
318
|
+
.optional(),
|
|
307
319
|
})
|
|
308
320
|
.passthrough();
|
|
309
321
|
const lockedPackageSchema = z
|
package/docs/TESTING.md
CHANGED
|
@@ -199,8 +199,20 @@ write to the detected real agent profiles. After npm publication, replace `npx .
|
|
|
199
199
|
|
|
200
200
|
## 8. Test credential-gated MCP configuration without exposing a key
|
|
201
201
|
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
List the reviewed recipes that need no separately billed AI/model API key:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npx . mcp-recipe --no-key
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
This includes Playwright, Chrome DevTools, and GitHub read-only. The first two have no
|
|
209
|
+
service credential. GitHub read-only needs a GitHub token and must refuse `--yes`
|
|
210
|
+
until its declared environment reference resolves. Use `--credential-free` for the
|
|
211
|
+
stricter zero-credential list:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
npx . mcp-recipe --credential-free
|
|
215
|
+
```
|
|
204
216
|
|
|
205
217
|
```bash
|
|
206
218
|
npx . mcp-recipe github-readonly --config "$TEST_HOME/mcp.json" --yes
|
|
@@ -230,3 +242,14 @@ npx . dashboard
|
|
|
230
242
|
Open the printed loopback URL. CLI setup, updates, removal, discovery, and rollback all
|
|
231
243
|
work without it. Browser automation is also optional and runs only when manually
|
|
232
244
|
dispatched in CI; locally, use `npm run test:e2e:dashboard`.
|
|
245
|
+
|
|
246
|
+
## Final cleanup test
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
npx . uninstall
|
|
250
|
+
npx . uninstall --yes
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
The first command is a dry run. The second removes only Loadout-managed agent files,
|
|
254
|
+
runtime tools, native jobs, state, snapshots, and cache; it leaves the locally invoked
|
|
255
|
+
package itself alone. Use `--remove-cli` only when testing a global npm install.
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Test Loadout on your own machine
|
|
2
|
+
|
|
3
|
+
This is the short, safe route through the product. Start in a normal terminal.
|
|
4
|
+
The first group only reads local state or prepares a preview; it does not replace
|
|
5
|
+
agent files. A preview can download reviewed source into Loadout's cache, but it
|
|
6
|
+
does not activate skills or change an agent configuration.
|
|
7
|
+
|
|
8
|
+
## 1. Get oriented
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
loadout guide
|
|
12
|
+
loadout library
|
|
13
|
+
loadout scan
|
|
14
|
+
loadout health
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`library` is the concise provenance view: it shows active skills and disabled
|
|
18
|
+
reviewed-library copies per agent. For the full source-package and upstream-repository
|
|
19
|
+
record for every skill, use `loadout library --all`. `scan` distinguishes
|
|
20
|
+
Loadout-managed skills from your own pre-existing skills. `health` checks local drift only; add
|
|
21
|
+
`--updates` only when you want it to contact the tracked public repositories.
|
|
22
|
+
|
|
23
|
+
## 2. Explore without installing
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
loadout catalog --json
|
|
27
|
+
loadout candidate list --limit 10
|
|
28
|
+
loadout recommend --project .
|
|
29
|
+
loadout optimize --project .
|
|
30
|
+
loadout tool
|
|
31
|
+
loadout tool graphify
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Run the project commands from the project you care about, or replace `.` with its
|
|
35
|
+
absolute path. `optimize` is still a preview until `--yes` is supplied. `tool
|
|
36
|
+
graphify` is also a preview; Graphify is a reviewed runtime tool and does not
|
|
37
|
+
need an OpenAI or Anthropic API key for its code-only install.
|
|
38
|
+
|
|
39
|
+
## 3. Open the optional dashboard
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
loadout dashboard
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Open the `http://127.0.0.1:PORT` address it prints. It never listens on the
|
|
46
|
+
network. The dashboard shows status, health, installed packages, updates, local
|
|
47
|
+
project recommendations, profiles, and the catalog. Its Apply and Undo buttons
|
|
48
|
+
require an in-page preview, acknowledgement, and a private local session token.
|
|
49
|
+
Stop the server with `Control-C`.
|
|
50
|
+
|
|
51
|
+
## 4. Preview and install a profile
|
|
52
|
+
|
|
53
|
+
Use this order. Each setup command previews first; interactive setup asks for
|
|
54
|
+
confirmation before changing files. A mutation creates a snapshot first.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Recommended everyday skills
|
|
58
|
+
loadout setup --mode stable --agents codex,claude-code
|
|
59
|
+
|
|
60
|
+
# Broader daily-use selection (50 curated skill directories)
|
|
61
|
+
loadout setup --mode power --agents codex,claude-code
|
|
62
|
+
|
|
63
|
+
# Download the broad reviewed library while keeping the active set controlled
|
|
64
|
+
loadout setup --mode maximum --agents codex,claude-code
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
At the API-access question, choose `None` unless you separately pay for a
|
|
68
|
+
provider API. A ChatGPT Plus or Claude Pro subscription is not an API key. Core
|
|
69
|
+
skill profiles do not require one; credentialed MCP and runtime operations stay
|
|
70
|
+
explicit.
|
|
71
|
+
|
|
72
|
+
For unattended use only after reviewing a preview, the equivalent is:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
loadout setup --mode stable --agents codex,claude-code --yes
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Do not add `--approve-risk` unless the displayed preview identifies a specific
|
|
79
|
+
reviewed finding and you understand it.
|
|
80
|
+
|
|
81
|
+
## 5. Test a change and recover
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Preview Graphify, then install only if the preview looks right
|
|
85
|
+
loadout tool graphify --agents codex,claude-code
|
|
86
|
+
loadout tool graphify --agents codex,claude-code --yes --approve-risk
|
|
87
|
+
|
|
88
|
+
# Check the exact current state
|
|
89
|
+
loadout library
|
|
90
|
+
loadout health
|
|
91
|
+
|
|
92
|
+
# Restore a prior snapshot if you do not like the result
|
|
93
|
+
loadout rollback --list
|
|
94
|
+
loadout rollback
|
|
95
|
+
|
|
96
|
+
# Or remove only Graphify and restore its pre-install agent state
|
|
97
|
+
loadout tool graphify --remove --agents codex,claude-code --yes --approve-risk
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`rollback` restores a whole Loadout snapshot. The tool-specific remove command
|
|
101
|
+
is narrower and is preferable when you only want to undo that one runtime tool.
|
|
102
|
+
|
|
103
|
+
## 6. Test daily discovery and updates
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
loadout alerts
|
|
107
|
+
loadout update
|
|
108
|
+
loadout update --package superpowers
|
|
109
|
+
loadout autopilot
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`update --package` checks only the named tracked package. The default is a
|
|
113
|
+
read-only diff and safety plan. Apply only after review:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
loadout update --package superpowers --apply
|
|
117
|
+
loadout update --yes
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`autopilot` previews two native daily read-only jobs (updates and discovery).
|
|
121
|
+
Enable or remove both explicitly:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
loadout autopilot --time 09:00 --yes
|
|
125
|
+
loadout autopilot --remove --yes
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The daily update job re-evaluates your saved Stable, Power, or Maximum profile and
|
|
129
|
+
checks every managed package, but never supplies `--yes`. Daily discovery can add
|
|
130
|
+
interesting repositories to the review queue; it cannot silently promote or install
|
|
131
|
+
them.
|
|
132
|
+
|
|
133
|
+
## 7. Test MCP choices without a model API key
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
loadout mcp-recipe --no-key
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Expect Playwright MCP, Chrome DevTools MCP, and GitHub read-only. None requires a
|
|
140
|
+
separately billed AI/model API key. GitHub read-only still discloses that it needs a
|
|
141
|
+
GitHub token; use `loadout mcp-recipe --credential-free` to exclude every service
|
|
142
|
+
credential too. Browser configuration and real connection testing remain explicit.
|
|
143
|
+
Graphify is a separate runtime tool, not an MCP server.
|
|
144
|
+
|
|
145
|
+
## 8. Preview complete cleanup
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
loadout uninstall
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Read the package, runtime, scheduler, and state summary. The preview changes nothing.
|
|
152
|
+
At the very end of testing, remove all Loadout-managed data while keeping the CLI:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
loadout uninstall --yes
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
To remove the npm command too, use `loadout uninstall --yes --remove-cli`. Complete
|
|
159
|
+
cleanup deliberately deletes Loadout's snapshots, so it is the last lifecycle test.
|
|
160
|
+
|
|
161
|
+
## 9. Advanced surface
|
|
162
|
+
|
|
163
|
+
The first help screen deliberately focuses on daily use. Existing advanced
|
|
164
|
+
commands have not been removed:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
loadout advanced
|
|
168
|
+
loadout candidate --help
|
|
169
|
+
loadout mcp-recipe --help
|
|
170
|
+
loadout <command> --help
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Avoid running registry publishing, signing, sandbox, credential, or arbitrary
|
|
174
|
+
MCP configuration commands on your main profile as part of routine user testing.
|
|
175
|
+
They are package-author or integration workflows, not required to use Loadout's
|
|
176
|
+
core product.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Loadout 0.3 Product-Hardening Plan
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Ship a user-testable CLI release with one-command cleanup, honest whole-profile update
|
|
6
|
+
checks, explicit no-key MCP discovery, and a verified local dashboard.
|
|
7
|
+
|
|
8
|
+
## Public contracts
|
|
9
|
+
|
|
10
|
+
1. `loadout uninstall` is a preview. `loadout uninstall --yes` removes scheduled
|
|
11
|
+
Loadout jobs, runtime tools, managed agent files, disabled library copies, cache,
|
|
12
|
+
snapshots, and state while preserving unmanaged or modified files. `--remove-cli`
|
|
13
|
+
additionally runs the global npm uninstall.
|
|
14
|
+
2. `loadout update` checks every tracked package and compares the last installed
|
|
15
|
+
Stable/Power/Maximum profile with the current trusted catalog. It never mutates by
|
|
16
|
+
default.
|
|
17
|
+
3. `loadout update --yes` reapplies trusted profile changes and applies all
|
|
18
|
+
statically-safe active package updates; blocked, disabled, or failed updates are
|
|
19
|
+
reported and skipped. `--package <id> --yes` remains the precise path.
|
|
20
|
+
4. Stable, Power, and Maximum are re-evaluated against the trusted catalog whenever
|
|
21
|
+
`update` runs. Discovery can nominate new candidates daily, but candidates cannot
|
|
22
|
+
enter a profile until immutable source, license, compatibility, and safety review
|
|
23
|
+
are recorded.
|
|
24
|
+
5. `loadout mcp-recipe --no-key` lists reviewed recipes requiring no separately
|
|
25
|
+
billed AI/model API key. It includes GitHub read-only while separately disclosing
|
|
26
|
+
the GitHub token. `--credential-free` is the stricter zero-credential filter.
|
|
27
|
+
6. `loadout dashboard` remains loopback-only and is verified by the browser E2E test.
|
|
28
|
+
|
|
29
|
+
## Implementation sequence
|
|
30
|
+
|
|
31
|
+
- [x] Add failing tests for uninstall preview/application and CLI help.
|
|
32
|
+
- [x] Implement uninstall orchestration with dependency injection and path guards.
|
|
33
|
+
- [x] Add failing tests for persisted profile state and profile drift reporting.
|
|
34
|
+
- [x] Record setup mode in snapshot-restorable install state and include it in update.
|
|
35
|
+
- [x] Add failing tests for bulk safe update selection and clear skipped results.
|
|
36
|
+
- [x] Implement `update --yes`, retaining `--apply` as a compatible alias.
|
|
37
|
+
- [x] Add and test Chrome DevTools as a pinned no-key MCP recipe.
|
|
38
|
+
- [x] Add `mcp-recipe --no-key` and beginner-readable recipe output.
|
|
39
|
+
- [x] Update README, test guide, master plan, changelog, completion, and version.
|
|
40
|
+
- [ ] Run unit, lint, type, evidence, package, CLI E2E, performance, dashboard E2E,
|
|
41
|
+
and npm dry-run gates.
|
|
42
|
+
- [ ] Review, commit, merge to main, push, tag, and publish to npm.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# CLI UX Polish Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use `executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Make Loadout's everyday CLI path understandable for a first-time user while preserving its existing safe, advanced capabilities.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Keep the CLI as the primary interface. Add one concise, read-only `guide` command and a focused help footer; retain advanced commands but remove them from the first-screen help. Fix JSON output and package-scoped update previews as explicit public CLI contracts. Document a safe test journey and keep the dashboard as an optional local companion.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Node.js 20+, TypeScript, Commander, Vitest, framework-free local dashboard.
|
|
10
|
+
|
|
11
|
+
## Global Constraints
|
|
12
|
+
|
|
13
|
+
- Never mutate a user's agent configuration from a default or preview command.
|
|
14
|
+
- Existing command names remain valid even if hidden from first-screen help.
|
|
15
|
+
- Machine-readable commands must emit valid JSON when `--json` is accepted.
|
|
16
|
+
- Do not require an API key or GitHub account for the core test journey.
|
|
17
|
+
- Every behavior change gets a test before its production code.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
### Task 1: Define the beginner CLI contract
|
|
22
|
+
|
|
23
|
+
**Files:**
|
|
24
|
+
|
|
25
|
+
- Modify: `tests/cli-help.test.ts`
|
|
26
|
+
- Modify: `src/cli.ts`
|
|
27
|
+
|
|
28
|
+
**Interfaces:**
|
|
29
|
+
|
|
30
|
+
- Produces: `loadout guide`, a read-only command that explains setup, discovery, project recommendations, recovery, dashboard, and help.
|
|
31
|
+
|
|
32
|
+
- [x] **Step 1: Write failing CLI contract tests** for `loadout guide`, a focused top-level help footer, and retained access to an advanced command.
|
|
33
|
+
- [x] **Step 2: Run** `npm test -- tests/cli-help.test.ts` **and confirm the new assertions fail.**
|
|
34
|
+
- [x] **Step 3: Implement** `guide`, hide maintainer-only commands from first-screen help, and add a short help footer that points to the guide.
|
|
35
|
+
- [x] **Step 4: Run** `npm test -- tests/cli-help.test.ts` **and confirm it passes.**
|
|
36
|
+
- [ ] **Step 5: Commit** the focused CLI discoverability change.
|
|
37
|
+
|
|
38
|
+
### Task 2: Repair machine-readable and scoped preview contracts
|
|
39
|
+
|
|
40
|
+
**Files:**
|
|
41
|
+
|
|
42
|
+
- Modify: `tests/cli-help.test.ts`
|
|
43
|
+
- Modify: `tests/update.test.ts`
|
|
44
|
+
- Modify: `src/cli.ts`
|
|
45
|
+
- Modify: `src/core/update.ts`
|
|
46
|
+
|
|
47
|
+
**Interfaces:**
|
|
48
|
+
|
|
49
|
+
- `loadout catalog --json` returns a JSON array.
|
|
50
|
+
- `loadout update --package <id>` plans only that managed package and rejects an unknown installed package clearly.
|
|
51
|
+
|
|
52
|
+
- [x] **Step 1: Write failing tests** for catalog JSON and package-scoped update planning.
|
|
53
|
+
- [x] **Step 2: Run the focused test files** and confirm the assertions fail for the existing implementation.
|
|
54
|
+
- [x] **Step 3: Implement the smallest compatible fixes.**
|
|
55
|
+
- [x] **Step 4: Run the focused tests** and confirm they pass.
|
|
56
|
+
- [ ] **Step 5: Commit** the contract fixes separately.
|
|
57
|
+
|
|
58
|
+
### Task 3: Record user testing and current product scope
|
|
59
|
+
|
|
60
|
+
**Files:**
|
|
61
|
+
|
|
62
|
+
- Create: `docs/USER_TEST_GUIDE.md`
|
|
63
|
+
- Modify: `MASTER_PLAN.md`
|
|
64
|
+
|
|
65
|
+
**Interfaces:**
|
|
66
|
+
|
|
67
|
+
- The guide gives a real-profile-safe order of commands, says which commands change state, and gives rollback instructions.
|
|
68
|
+
- `MASTER_PLAN.md` begins with the one authoritative unfinished-work section and moves stale immediate tasks out of the active path.
|
|
69
|
+
|
|
70
|
+
- [x] **Step 1: Add a concise user testing guide** for daily use, discovery, optional dashboard, safe mutation, rollback, and advanced validation.
|
|
71
|
+
- [x] **Step 2: Add the current remaining work section** and mark historic, non-essential ideas as deferred rather than pretending they are active product requirements.
|
|
72
|
+
- [x] **Step 3: Run markdown and CLI smoke checks** to make sure command names match the real surface.
|
|
73
|
+
- [ ] **Step 4: Commit** documentation separately.
|
|
74
|
+
|
|
75
|
+
### Task 4: Validate the actual user journey
|
|
76
|
+
|
|
77
|
+
**Files:**
|
|
78
|
+
|
|
79
|
+
- Test: `tests/cli-help.test.ts`
|
|
80
|
+
- Test: `tests/update.test.ts`
|
|
81
|
+
- Test: `tests/dashboard.test.ts`
|
|
82
|
+
|
|
83
|
+
- [x] **Step 1: Build and run** the CLI guide, catalog JSON, health, library, project recommendation preview, and dashboard endpoint checks without changing agent files.
|
|
84
|
+
- [ ] **Step 2: Run** `npm run verify:full` **and inspect every failure if any.**
|
|
85
|
+
- [ ] **Step 3: Review the diff for accidental profile/cache/secrets changes.**
|
|
86
|
+
- [ ] **Step 4: Commit, then present the exact install/test/recovery commands to the user.**
|