# Soap CLI Interactive Mode Plan

This plan adapts `/Users/rad/Downloads/SOAP_CLI_INTERACTIVE_MODE_TICKETS.md` to the current `soap-cli` codebase.

The current CLI is deterministic, registry-aware, and template-based. Interactive mode must preserve that model. It should resolve command inputs, never generate code through AI, and never hide file writes, deletes, or overwrites.

## Current Baseline

Current command surface:

- `soap create`
- `soap add resource`
- `soap add route`
- `soap add entity`
- `soap add use-case`
- `soap add repository`
- `soap add command`
- `soap add query`
- `soap add event`
- `soap add socket`
- `soap generate bruno`
- `soap generate openapi`
- `soap info`
- `soap doctor`
- `soap check routes`
- `soap remove route`
- `soap remove resource`
- `soap update config`

Current capability model:

- Framework: `express`
- Architecture: `regular`, `cqrs`
- Databases: `mongo`, `postgres`, `mysql`, `sqlite`, `redis`
- Auth: `jwt`, `api-key`, `local`, `google`
- Messaging: `in-memory`, `kafka`
- Realtime: `ws`
- Telemetry: `logs`, `otel-noop`
- Docs: `openapi`
- API client: `bruno`

Out of scope for the first interactive pass:

- MySQL and SQLite
- OAuth2 and Basic auth
- role/admin decorator policies beyond existing auth strategy values
- Zod as a separate capability
- Pino/tracing capability names
- git init
- Docker enable/disable toggle
- migrations, DB indexes, generated test suites, mapper prompts
- registry field metadata

These are valid future directions, but they require model/schema work before prompts should expose them.

## Design Rules

1. Interactive is optional.

   Every interactive flow must have an equivalent flag-based non-interactive flow.

2. Resolution order is fixed.

   ```txt
   explicit CLI flags
   interactive answers
   .soap project/api/registry defaults
   preset defaults
   hardcoded fallback defaults
   ```

3. Interactive prompts are project-aware.

   Existing `.soap/project.json`, `.soap/structure.json`, `.soap/api.json`, and `.soap/registry.json` determine available choices.

4. Prompting is only input resolution.

   Prompt answers feed the same deterministic planners and writers used by non-interactive commands.

5. File conflict behavior is shared.

   Interactive mode may ask, but actual writes/deletes must still go through the same safe file writer and registry hash checks.

6. Future capability expansion must happen below the prompt layer first.

   Do not ask users about a capability until the config schema, dependency resolver, templates, registry behavior, and validation support it.

## Phase 1 — Interactive Foundation

### INT-MVP-001 — Shared Interactive Option

Add `-i, --interactive` to supported commands.

Initial supported commands:

- `soap create <name>`
- `soap add resource <name>`
- `soap add route <resource> <name>`
- `soap generate bruno`
- `soap remove route <resource> <route>`
- `soap remove resource <resource>`

Also add shared `--on-conflict <policy>` where useful.

Policies:

- `ask`
- `skip`
- `overwrite`
- `new`
- `abort`

Mapping to existing behavior:

- `skip` -> current skip modified behavior
- `overwrite` -> `--force`
- `new` -> `--write-new` where supported
- `abort` -> fail on first conflict
- `ask` -> prompt only in interactive TTY

Acceptance:

- Commands accept `-i` and `--interactive`.
- Help documents interactive flags.
- No prompt appears unless `-i` is passed.
- Existing non-interactive behavior remains unchanged.

### INT-MVP-002 — Prompt Adapter

Add a prompt abstraction under `src/prompts`.

Suggested files:

```txt
src/prompts/prompt.types.ts
src/prompts/prompt-adapter.ts
src/prompts/inquirer-prompt-adapter.ts
src/prompts/mock-prompt-adapter.ts
```

Interface:

```ts
interface PromptAdapter {
  input(question: InputQuestion): Promise<string>;
  confirm(question: ConfirmQuestion): Promise<boolean>;
  select<T extends string>(question: SelectQuestion<T>): Promise<T>;
  multiSelect<T extends string>(question: MultiSelectQuestion<T>): Promise<T[]>;
}
```

Acceptance:

- Command code does not import `@inquirer/prompts` directly.
- Adapter is mockable in tests.
- `@inquirer/prompts` is the only prompt implementation dependency.

### INT-MVP-003 — Terminal Capability Guard

Add TTY detection.

Suggested files:

```txt
src/terminal/terminal-capabilities.ts
src/commands/shared/interactive-guard.ts
```

Behavior:

- If `--interactive` is passed outside a TTY, fail clearly.
- Non-interactive commands still work in CI.
- `--yes` may skip confirmations but must not imply interactive mode.

Error:

```txt
Interactive mode requires a TTY. Use explicit flags instead.
```

Acceptance:

- TTY and non-TTY behavior covered by unit tests.

### INT-MVP-004 — Input Resolvers

Add small resolvers for current command inputs.

Suggested files:

```txt
src/resolvers/resolver.types.ts
src/resolvers/create-config.resolver.ts
src/resolvers/add-resource.resolver.ts
src/resolvers/add-route.resolver.ts
src/resolvers/generate-bruno.resolver.ts
```

Acceptance:

- Flags always win over prompt answers.
- Prompt answers win over config defaults.
- Project config restricts available options.
- Invalid resolved values fail before file planning.

### INT-MVP-005 — Shared Conflict Policy

Consolidate current `force`, `writeNew`, and skip behavior.

Suggested files:

```txt
src/io/conflict-policy.ts
src/prompts/file-conflict.prompt.ts
```

Acceptance:

- Existing `--force` and `--write-new` still work.
- Interactive conflict `ask` presents skip/overwrite/write-new/abort.
- Non-interactive default stays safe.

## Phase 2 — Interactive Create

### INT-MVP-101 — `soap create <name> -i`

Prompt only for current supported capabilities.

Prompt flow:

```txt
Project name
Framework: express
Architecture: regular/cqrs
Databases: mongo/postgres/mysql/sqlite/redis/none
Auth: jwt/api-key/local/none
Messaging: in-memory/kafka
Realtime: ws/none
Telemetry: logs/otel-noop
Docs: openapi/none
API client: bruno/none
Zones: public/private/admin
Package manager: npm/pnpm/yarn/bun
Install dependencies: yes/no
```

Do not prompt for unsupported future options.

Acceptance:

- Provided flags skip matching questions.
- Answers feed existing `createProjectFiles` and `createSoapConfigBundle`.
- Generated `.soap` files match selected answers.
- `--dry-run` prints summary and planned file count.

### INT-MVP-102 — Create Summary

Before writing files, show a summary in interactive mode.

Example:

```txt
Project: billing-service
Architecture: regular
Databases: postgres
Auth: jwt
Docs: openapi
API client: bruno

Generate project? yes/no
```

Acceptance:

- User can abort before writes.
- `--yes` skips final confirmation.

### INT-MVP-103 — Create Presets

Add presets compatible with current capability model.

Initial presets:

- `express-mongo-api`
- `express-postgres-api`
- `express-cqrs-kafka-api`
- `express-full-demo`

Suggested files:

```txt
src/presets/create-presets.ts
src/presets/preset.types.ts
```

Acceptance:

- `soap create my-api --preset express-mongo-api` works without prompts.
- `soap create my-api -i --preset express-mongo-api` uses preset values as defaults.
- Invalid preset shows available presets.

## Phase 3 — Interactive Resource And Route

### INT-MVP-201 — `soap add resource <name> -i`

Prompt flow based on current generator:

```txt
Resource name
Generate CRUD: yes/no
Storage: none + enabled databases only
Auth: none + enabled route auth only
Zone: enabled project zones
Generate Bruno requests: yes/no if Bruno enabled
Enable Bruno now: yes/no if Bruno disabled
Run as dry-run first: yes/no
```

Acceptance:

- Reads `.soap` before prompting.
- Does not offer unavailable DB/auth choices.
- If Bruno is enabled interactively, updates `.soap/api.json` and project capabilities using update config behavior.
- Generated files and registry are unchanged from equivalent flag-based flow.

### INT-MVP-202 — Resource Plan Summary

Reuse the existing resource planning summary from `soap add resource --dry-run`.

Acceptance:

- Interactive mode shows planned file groups before writing.
- User can abort.
- `--yes` skips final confirmation.

### INT-MVP-203 — `soap add route <resource> <name> -i`

Prompt flow:

```txt
Resource: select from registry if missing
Route name
HTTP method
Path
Zone
Auth
Target: direct/use-case/command/query
Generate Bruno request: yes/no if Bruno enabled
```

Acceptance:

- Resource list comes from registry.
- Auth choices come from enabled capabilities.
- Zone choices come from `.soap/project.json`.
- Generated route matches equivalent non-interactive flags.

## Phase 4 — Interactive Generated Artifacts

### INT-MVP-301 — `soap generate bruno -i`

Prompt flow:

```txt
Detected routes
Existing Bruno files
Missing Bruno files
Modified generated Bruno files

Choose:
- generate missing only
- regenerate all unmodified generated files
- generate E2E flow
- abort
```

Acceptance:

- Manual `.bru` edits are detected.
- User can avoid overwriting modified files.
- `--force` still overrides.

### INT-MVP-302 — Interactive OpenAPI Export

Optional small enhancement:

```bash
soap generate openapi -i
```

Prompt:

```txt
Output path: openapi.json
```

Acceptance:

- Only offered when OpenAPI capability is enabled.
- Dry run does not fetch from server.

## Phase 5 — Interactive Remove

### INT-MVP-401 — `soap remove route/resource -i`

Use existing safe remove behavior.

Prompt flow:

```txt
Found route/resource
Tracked files to delete
Modified tracked files
Registry entries to remove

Continue? yes/no
```

Acceptance:

- Shows tracked file list before deletion.
- Refuses modified files unless user chooses overwrite/force.
- Dry run shows planned deletion.
- Does not delete untracked files.

## Phase 6 — Tests And Docs

### INT-MVP-501 — Resolver Unit Tests

Test:

- flags override prompts
- prompts override project config
- project config overrides preset
- preset overrides fallback
- invalid values fail

### INT-MVP-502 — Prompt Adapter Tests

Test commands with mocked prompt adapter.

Initial integration tests:

- `soap create my-api -i`
- `soap add resource users -i`
- `soap add route users search -i`
- `soap generate bruno -i`
- `soap remove route users create-user -i`

### INT-MVP-503 — Interactive Docs

Add:

```txt
docs/cli/interactive-mode.md
docs/cli/create.md
docs/cli/add-resource.md
docs/cli/add-route.md
docs/cli/bruno.md
```

Update root README with an interactive section.

## Phase 7 — Future Capability Expansion

These items should not be prompt-only tickets. Each needs schema, templates, validation, registry, docs, and tests.

### FUT-001 — Contracts Capability

Add explicit contract capability, likely:

```ts
contracts: ["zod"]
```

Work required:

- config schema
- dependency resolver
- route/resource templates
- registry metadata
- `soap update config --add-contracts zod`
- interactive prompts

### FUT-002 — Resource Field Metadata

Add field definitions to registry.

Used by:

- entity templates
- contracts
- Bruno request bodies
- repositories
- later migrations/indexes

This should be implemented before INT-style field prompts.

### FUT-003 — CRUD Route Matrix

Allow per-operation route config:

- method
- path
- zone
- auth
- Bruno yes/no

Requires route registry extension before interactive prompts expose it.

### FUT-004 — Auth Policies

Add route policy support beyond strategy names:

- admin
- roles
- custom

Implemented through registry metadata, `--policy`, CRUD matrix policy overrides, generated auth decorators, docs, and route checks.

### FUT-005 — More Storage Adapters

Add MySQL/SQLite only after:

- dependency resolver support
- generated config
- docker/dev story
- repository templates
- smoke tests

Implemented for MySQL and SQLite through the shared SQL runtime path, dependency resolver, generated config/client files, Docker/dev configuration for MySQL, SQLite env configuration, resource SQL repositories, and smoke generation tests.

### FUT-006 — Generated Tests

Add unit/integration test generation as a separate epic.

Do not include test prompts before the generator can produce compiling tests.

Implemented for generated CRUD resources in regular and CQRS modes:

- entity specs
- in-memory repository CRUD specs
- regular CRUD use-case specs
- CQRS command/query handler specs

Verified with generated project `npm test` for regular and CQRS resources with custom field metadata.

### FUT-007 — Git Init And Install

Can be added later, but should remain explicit and safe.

Implemented as explicit post-create actions:

- `--install` runs the selected package manager after files are written.
- `--skip-install` takes precedence over install.
- interactive create asks about dependency installation.
- `--git-init` runs `git init` after files are written.
- interactive create asks about git init with default `false`.
- no auto-commit and no push behavior.

## Recommended Implementation Order

```txt
1. INT-MVP-001 shared interactive option
2. INT-MVP-002 prompt adapter
3. INT-MVP-003 terminal guard
4. INT-MVP-005 shared conflict policy
5. INT-MVP-004 input resolvers
6. INT-MVP-101 create wizard
7. INT-MVP-102 create summary
8. INT-MVP-103 create presets
9. INT-MVP-201 add resource wizard
10. INT-MVP-202 resource plan summary
11. INT-MVP-203 add route wizard
12. INT-MVP-301 generate bruno wizard
13. INT-MVP-401 remove wizard
14. INT-MVP-501 resolver tests
15. INT-MVP-502 prompt/integration tests
16. INT-MVP-503 interactive docs
17. FUT-001 contracts capability
18. FUT-002 resource field metadata
19. FUT-003 CRUD route matrix
20. FUT-004 auth policies
21. FUT-005 more storage adapters
22. FUT-006 generated tests
23. FUT-007 git init and install
```

## Codex Ticket Prompt

```txt
Implement INT-MVP-XXX from docs/plans/interactive-mode-plan.md.

Constraints:
- Preserve non-interactive behavior.
- Interactive mode only resolves options; generation stays deterministic.
- Use the existing .soap config and registry model.
- Do not expose unsupported future capabilities in prompts.
- Do not overwrite modified generated files without shared conflict policy.
- Add focused tests or smoke verification for the implemented behavior.
```
