Skip to content

stash init: persist per-step outcomes in .cipherstash/context.json so plan/impl can distinguish done from pending #696

Description

@coderdan

Background

Surfaced by the Codex differential review of #687 (honest non-interactive init) as a non-blocking follow-up.

stash init now computes honest completion state at the end of a run — which steps actually happened (authenticated, stackInstalled, cliInstalled, eqlInstalled, and, as of #687, eqlMigrationPending for the Drizzle flow where EQL is generated-but-not-applied). But that state lives only in the in-memory InitState for the duration of the init process. It is not persisted.

Downstream, stash plan and stash impl reconstruct context from .cipherstash/context.json, and they currently assume the happy path — stackInstalled / cliInstalled / eqlInstalled are treated as effectively true. So the handoff prose an agent reads cannot distinguish:

  • "EQL is installed in the database" from
  • "an EQL migration was generated and the user still has to run drizzle-kit migrate" (the new eqlMigrationPending state), or
  • "EQL install was skipped / failed and setup is genuinely incomplete".

Problem

An agent picking up the handoff after a Drizzle init (or a skipped-EQL init) is told, in effect, that everything is done — even though a required apply step is still outstanding. That is the same class of false-success #687 removed from the init summary itself, but it re-appears one hop downstream because the honest state isn't carried across the process boundary.

Proposal

  • Persist the resolved per-step outcomes into .cipherstash/context.json at the end of init (including eqlInstalled and eqlMigrationPending, and ideally the InstallOutcome verbatim: installed | already-installed | migration-generated | dry-run).
  • Have plan / impl read those fields instead of assuming completion, and have the handoff prose name the outstanding action (drizzle-kit migrate, stash eql install, etc.) when something is pending.
  • Keep it backwards-compatible: a context.json written by an older CLI (no outcome fields) should degrade to today's optimistic behaviour, not crash.

Notes

  • Non-blocking for GA; this is a correctness/honesty refinement of the agent handoff, not a functional break.
  • Relevant code: packages/cli/src/commands/init/index.ts (summary/gate), packages/cli/src/commands/init/steps/install-eql.ts (InstallOutcome → state mapping), packages/cli/src/commands/init/lib/write-context.ts (the context.json writer), and the plan/impl readers.
  • Follows feat(cli): honest non-interactive init — fail on skew, no false success (rc.2 M4) #687.

https://claude.ai/code/session_01MxTTPaPP16m6br7Hoab94w

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions