You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(cli): honest non-interactive init — fail on skew, no false success (rc.2 M4)
Non-interactive `stash init` reported success for setups that didn't fully
complete. Three honesty gaps closed:
1. Version skew. A non-interactive run can't reconcile a `behind` skew (it
won't mutate an install without consent), so instead of warning-and-
proceeding — scaffolding against packages older than this CLI expects and
then claiming success — it now REFUSES with a non-zero exit (CliExit(1))
and the exact align command. The #661/#666 no-mutation principle is
preserved (execSync still not called); only the post-warning action
changes from proceed to fail. `ahead` skew stays a warn (install likely
fine; update the CLI).
2. False 'Setup complete'. The summary header and the auth/db/scaffold
checkmarks were unconditional. Now: when EQL is required but not installed
(eqlInstalled=false AND integration !== prisma-next), the summary reads
'Setup incomplete' and init exits non-zero, pointing at `stash eql install`.
'Database connection verified' → 'Database URL resolved' (init resolves a
URL, never opens a connection). 'Encryption client scaffolded' is shown
only when a client was written (clientFilePath set; skipped for prisma-next).
3. False 'skills loaded'. The Claude/Codex handoff launch prompt referenced
the skills dir unconditionally; a stripped build installs no skills, so it
told the agent to read files that aren't there. The clause is now
conditional on installSkills() actually copying something.
Tests: install-deps skew tests updated to assert the refusal (still never
mutates); new init-command honest-summary tests (EQL-missing → exit 1 +
'Setup incomplete'; prisma-next eqlInstalled=false → completes). Skill + doc
comments updated. Suite 542 unit / 62 e2e green, code:check clean. Changeset:
stash minor.
Claude-Session: https://claude.ai/code/session_01MxTTPaPP16m6br7Hoab94w
// Only point the agent at the skills dir when skills were actually copied.
39
+
// A stripped CLI build (no bundled skills) returns [] — claiming they're
40
+
// there would send the agent to read files that don't exist.
41
+
constskillsClause=
42
+
installed.length>0
43
+
? `The installed skills under ${CLAUDE_SKILLS_DIR}/ have the rules; `
44
+
: ''
38
45
constlaunchPrompt=
39
46
mode==='plan'
40
-
? `Read ${SETUP_PROMPT_REL_PATH} and produce the planning deliverable it describes. The installed skills under ${CLAUDE_SKILLS_DIR}/ have the rules; ${CONTEXT_REL_PATH} has the project facts. Do not edit code or run mutating commands during this phase.`
41
-
: `Read ${SETUP_PROMPT_REL_PATH} and complete the setup steps. The installed skills under ${CLAUDE_SKILLS_DIR}/ have the rules; ${CONTEXT_REL_PATH} has the project facts.`
47
+
? `Read ${SETUP_PROMPT_REL_PATH} and produce the planning deliverable it describes. ${skillsClause}${CONTEXT_REL_PATH} has the project facts. Do not edit code or run mutating commands during this phase.`
48
+
: `Read ${SETUP_PROMPT_REL_PATH} and complete the setup steps. ${skillsClause}${CONTEXT_REL_PATH} has the project facts.`
// Only reference the skills dir when skills were actually copied (a
58
+
// stripped build returns []); the durable rules live in AGENTS.md either
59
+
// way, so the prompt stays useful without them.
60
+
constskillsClause=
61
+
installed.length>0
62
+
? `the skills under ${CODEX_SKILLS_DIR}/ have the API details; `
63
+
: ''
57
64
constlaunchPrompt=
58
65
mode==='plan'
59
-
? `Read ${SETUP_PROMPT_REL_PATH} and produce the planning deliverable it describes. AGENTS.md has the durable rules; the skills under ${CODEX_SKILLS_DIR}/ have the API details; ${CONTEXT_REL_PATH} has the project facts. Do not edit code or run mutating commands during this phase.`
60
-
: `Read ${SETUP_PROMPT_REL_PATH} and complete the setup steps. AGENTS.md has the durable rules; the skills under ${CODEX_SKILLS_DIR}/ have the API details; ${CONTEXT_REL_PATH} has the project facts.`
66
+
? `Read ${SETUP_PROMPT_REL_PATH} and produce the planning deliverable it describes. AGENTS.md has the durable rules; ${skillsClause}${CONTEXT_REL_PATH} has the project facts. Do not edit code or run mutating commands during this phase.`
67
+
: `Read ${SETUP_PROMPT_REL_PATH} and complete the setup steps. AGENTS.md has the durable rules; ${skillsClause}${CONTEXT_REL_PATH} has the project facts.`
Copy file name to clipboardExpand all lines: packages/cli/src/messages.ts
+11Lines changed: 11 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -119,6 +119,17 @@ export const messages = {
119
119
nameRequiresValue: '--name requires a value',
120
120
unexpectedArgument: 'Unexpected argument',
121
121
},
122
+
init: {
123
+
/**
124
+
* Honest non-interactive init. These exit non-zero so automation never
125
+
* reads a false success — the e2e suite asserts on the leaders.
126
+
*/
127
+
setupIncomplete: 'Setup incomplete',
128
+
eqlNotInstalled: 'EQL is not installed — encryption queries will fail.',
129
+
/** Shown when a non-interactive run hits version skew it won't reconcile. */
130
+
skewNonInteractive:
131
+
'Version skew on already-installed packages — refusing to proceed non-interactively. Align the packages (below) and re-run, or run init interactively.',
132
+
},
122
133
telemetry: {
123
134
/**
124
135
* The one-time first-run notice. Printed to stderr so it never pollutes
`stash init` installs the CLI as a project dev dependency, so subsequent commands can drop the `npx`. The CLI is package-manager aware — before init, use whichever one-shot runner your project uses (`npx`, `pnpm dlx`, `bunx`, `yarn dlx`). Installs are **pinned to the exact `@cipherstash/*` versions this CLI release shipped with** (never bare dist-tags, which can lag behind a release), and init warns if an already-installed package's resolved version differs from the release's. Treat that warning as a real problem — but the fix depends on direction, and init says which applies: an **older** install should be aligned to the release (init offers the exact command); a **newer** install must NOT be downgraded — update the `stash` CLI to the matching release instead (init prints that command too).
39
+
`stash init` installs the CLI as a project dev dependency, so subsequent commands can drop the `npx`. The CLI is package-manager aware — before init, use whichever one-shot runner your project uses (`npx`, `pnpm dlx`, `bunx`, `yarn dlx`). Installs are **pinned to the exact `@cipherstash/*` versions this CLI release shipped with** (never bare dist-tags, which can lag behind a release), and init flags any already-installed `@cipherstash/*` package whose resolved version differs from the release's. The fix depends on direction, and init says which applies: an **older** install should be aligned to the release (init offers the exact command); a **newer** install must NOT be downgraded — update the `stash` CLI to the matching release instead (init prints that command too). **Non-interactively, an older ("behind") skew is fatal** — init refuses with a non-zero exit and the align command rather than scaffolding against mismatched packages and reporting a false success. Interactively it offers to align. Likewise, if the EQL extension isn't installed at the end (and the integration isn't Prisma Next, which installs it via `migration apply`), init reports **"Setup incomplete"** and exits non-zero — it never claims a setup is complete when encryption would fail at query time.
0 commit comments