Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/skills/ink-tui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ service wiring depends on the screen's needs; `App` remains the shared shell.

Business logic calls [WizardUI](../../../src/store/ui/wizard-ui.ts) through
[getUI](../../../src/store/ui/index.ts). Screens use
[WizardStore](../../../src/store/state/store.ts) setters for reactive changes.
[FlowStore](../../../src/store/state/store.ts) setters for reactive changes.
The router resolves program screens from session predicates; overlays interrupt
that resolution. Local state is appropriate for presentation details such as tab
selection, not wizard progression.
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/ink-tui/references/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
| [ProgramStep](../../../../src/store/programs/program-step.ts) | Screens, visibility/completion predicates, gates, and initialization hooks |
| [screen-sequences.ts](../../../../src/tui/screen-sequences.ts) | `ScreenId`, `Screen`, `Sequence`, and the derived `PROGRAM_SEQUENCES` |
| [WizardRouter](../../../../src/tui/router.ts) | Resolution and the `Overlay` stack |
| [WizardStore](../../../../src/store/state/store.ts) | Reactive state, gate promises, display observations, and pending interactions |
| [FlowStore](../../../../src/store/state/store.ts) | Reactive state, gate promises, display observations, and pending interactions |
| [WizardUI](../../../../src/store/ui/wizard-ui.ts) | Typed operations available to business logic |

## Program screens
Expand Down
19 changes: 10 additions & 9 deletions e2e-harness/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ scripts/
wizard-ci-explore.no-jest.ts open an app, confirm setup, print one frame
```

The server reads and mutates the **real** `WizardStore` the TUI renders from.
The router resolves the active screen from session state, every action goes
through a store setter, and the render is a pure projection of that state. So a
commit over the socket makes the real TUI react, and the parent never touches
the TUI's input.
The server reads and mutates the **real** `FlowStore` the TUI renders from. The
router resolves the active screen from session state, every action goes through
a store setter, and the render is a pure projection of that state. So a commit
over the socket makes the real TUI react, and the parent never touches the TUI's
input.

## Launching a controlled wizard

Expand Down Expand Up @@ -83,7 +83,7 @@ program), 404 (unknown route), 409 (a run is in flight), 413 (body over 64 KB),
| `POST /credentials` | Resolves the API key into project credentials and commits them, advancing `auth` |
| `POST /run` | TUI surface: `requestRun` on the store, releasing the runner's agent start. Idempotent |
| `POST /detect` body `{ programId?, installDir? }` | Headless surface: runs detection through the store's setters |
| `POST /runs` body `{ programId, installDir?, frameworkContext?, skillId? }` | Headless surface: one independent agent run; 409 while one runs |
| `POST /runs` body `{ programId, installDir?, frameworkContext?, skillId? }` | Headless surface: one independent agent run on a fresh `RunStore`; 409 while one runs |
| `GET /runs` | The run ledger: `runId`, `programId`, `installDir`, `status`, `error`, timestamps, `result` |
| `POST /shutdown` | Flushes and exits. Idempotent |

Expand All @@ -96,9 +96,10 @@ follow-up flags, `runRequested`, `runPhase`, `pendingQuestion`, `taskNotice`,
redaction (`secret:<id>` refs become `[secret-ref]`, secret-looking keys become
`[redacted]`); credentials reduce to `hasCredentials` and `projectId`.
`session.runPhase` is the run status and `session.outroData` carries a failed
run's reason. No access token, API key, user record, or answer value is ever
projected. A ledger record's `result` is this state as it read when the run
ended.
run's reason. `dashboardUrl` and `notebookUrl` are artefacts of the session: a
later run inherits them. No access token, API key, user record, or answer value
is ever projected. A ledger record's `result` is this state as it read when the
run ended.

The socket is created mode 0600 in a directory the caller owns. A stale socket
file is replaced; a live one is refused. The wizard unlinks it on exit.
Expand Down
18 changes: 9 additions & 9 deletions e2e-harness/__tests__/control-driver.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Control-plane test: drive a REAL WizardStore through the full integration
* Control-plane test: drive a REAL FlowStore through the full integration
* screen sequence using only the ControlDriver — proving read_state is a
* truthful projection of router-resolved state and that perform_action commits
* cause the same transitions the interactive UI would.
Expand All @@ -9,7 +9,7 @@
* through the driver.
*/

import { WizardStore } from '@store/state/store';
import { FlowStore } from '@store/state/store';
import { StoreUI } from '@store/ui/store-ui';
import { setUI } from '@store/ui';
import {
Expand All @@ -28,8 +28,8 @@ import { SOURCE_MAPS_CONTEXT_KEYS } from '@store/programs/error-tracking-upload-
import { OutroKind } from '@store/session/wizard-session';
import { flowFor } from '@store/programs/flow-for';

function freshStore(): WizardStore {
const store = new WizardStore(flowFor(Program.PostHogIntegration).flow);
function freshStore(): FlowStore {
const store = new FlowStore(flowFor(Program.PostHogIntegration).flow);
// Headless: a real store + StoreUI (which only forwards to the store), no Ink
// render. setUI so any getUI() path the store touches resolves.
setUI(new StoreUI(store));
Expand Down Expand Up @@ -205,8 +205,8 @@ describe('ControlDriver — wizard_ask overlay', () => {
});

describe('ControlDriver — self-driving integration check', () => {
function selfDrivingStore(): WizardStore {
const store = new WizardStore(flowFor(Program.SelfDriving).flow);
function selfDrivingStore(): FlowStore {
const store = new FlowStore(flowFor(Program.SelfDriving).flow);
setUI(new StoreUI(store));
store.session = buildSession({ installDir: '/tmp/ci-driver-sd', ci: true });
return store;
Expand Down Expand Up @@ -245,16 +245,16 @@ describe('ControlDriver — self-driving integration check', () => {
});

describe('ControlDriver — source-maps project pick', () => {
function sourceMapsStore(): WizardStore {
const store = new WizardStore(
function sourceMapsStore(): FlowStore {
const store = new FlowStore(
flowFor(Program.ErrorTrackingUploadSourceMaps).flow,
);
setUI(new StoreUI(store));
store.session = buildSession({ installDir: '/tmp/ci-driver-sm', ci: true });
return store;
}

function toDetectScreen(store: WizardStore): void {
function toDetectScreen(store: FlowStore): void {
// Intro → auth → detect.
store.completeSetup();
store.setCredentials({
Expand Down
4 changes: 2 additions & 2 deletions e2e-harness/__tests__/e2e-flow-snapshot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* Update goldens with `jest -u` after an intentional flow change.
*/

import { WizardStore } from '@store/state/store';
import { FlowStore } from '@store/state/store';
import { StoreUI } from '@store/ui/store-ui';
import { setUI } from '@store/ui';
import { buildSession, RunPhase } from '@store/session/wizard-session';
Expand Down Expand Up @@ -51,7 +51,7 @@ function traceFlow(
action: string;
params?: Record<string, unknown>;
}> {
const store = new WizardStore(flowFor(program).flow);
const store = new FlowStore(flowFor(program).flow);
setUI(new StoreUI(store));
const session = buildSession({ installDir: '/tmp/e2e-snap', ci: true });
if (integration) {
Expand Down
16 changes: 8 additions & 8 deletions e2e-harness/__tests__/keyboard-equivalence.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest';
import { render, cleanup } from 'ink-testing-library';
import {
WizardStore,
FlowStore,
Program,
RunPhase,
McpOutcome,
Expand Down Expand Up @@ -90,11 +90,11 @@ const approved = (ok: boolean) =>
organization: { is_ai_data_processing_approved: ok },
} as unknown as WizardSession['apiUser']);

const confirmed = (s: WizardStore) => {
const confirmed = (s: FlowStore) => {
s.completeSetup();
s.setReadinessResult(clean);
};
const authed = (s: WizardStore) => {
const authed = (s: FlowStore) => {
s.setCredentials({
accessToken: 'phx_test',
projectApiKey: 'phc_test',
Expand All @@ -103,7 +103,7 @@ const authed = (s: WizardStore) => {
});
s.setApiUser(approved(true));
};
const ran = (s: WizardStore) => {
const ran = (s: FlowStore) => {
s.setRunPhase(RunPhase.Running);
s.setOutroData({ kind: OutroKind.Success, message: 'done' });
s.setRunPhase(RunPhase.Completed);
Expand All @@ -123,7 +123,7 @@ interface Pair {
program: ProgramId;
integration?: Integration;
screen: string;
arrange: (s: WizardStore) => void;
arrange: (s: FlowStore) => void;
keys: string[];
action: string;
params?: Record<string, unknown>;
Expand Down Expand Up @@ -358,8 +358,8 @@ const PAIRS: Pair[] = [
},
];

function makeStore(pair: Pair): WizardStore {
const store = new WizardStore(flowFor(pair.program).flow);
function makeStore(pair: Pair): FlowStore {
const store = new FlowStore(flowFor(pair.program).flow);
store.version = '0.0.0-test';
setUI(new StoreUI(store));
const session = buildSession({ installDir: '/app', ci: false });
Expand All @@ -378,7 +378,7 @@ interface Snap {
session: Record<string, unknown>;
}

function snap(store: WizardStore): Snap {
function snap(store: FlowStore): Snap {
const session: Record<string, unknown> = {};
for (const [k, v] of Object.entries(store.session)) {
session[k] = k === 'frameworkConfig' ? (v ? '[config]' : null) : v;
Expand Down
88 changes: 56 additions & 32 deletions scripts/__fixtures__/chunk-manifest.ci.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
],
"imports": [
"src/agent/runner/sequence/orchestrator/queue-tools.ts",
"src/store/agent-protocol/agent-env-isolation.ts",
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts",
"src/store/services/steps/add-mcp-server-to-clients/MCPClient.ts"
"src/store/auth-session-state.ts"
]
},
"src/agent/agent-prompt-loader.ts": {
Expand Down Expand Up @@ -78,10 +78,10 @@
"src/agent/agent-prompt-loader.ts",
"src/agent/aio-capture.ts",
"src/agent/runner/sequence/orchestrator/queue-tools.ts",
"src/store/agent-protocol/agent-env-isolation.ts",
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts",
"src/store/programs/ai-opt-in-gate.ts",
"src/store/services/steps/add-mcp-server-to-clients/MCPClient.ts"
"src/store/programs/ai-opt-in-gate.ts"
]
},
"src/agent/aio-capture.ts": {
Expand All @@ -98,9 +98,8 @@
"src/agent/runner/harness/pi/task.ts",
"src/agent/runner/harness/pi/tasks.ts",
"src/agent/runner/harness/pi/tools.ts",
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts",
"src/store/services/steps/add-mcp-server-to-clients/MCPClient.ts"
"src/store/agent-protocol/agent-env-isolation.ts",
"src/store/agent-protocol/agent-signals.ts"
]
},
"src/agent/runner/harness/pi/mcp.ts": {
Expand Down Expand Up @@ -145,9 +144,8 @@
"src/agent/runner/harness/pi/security.ts",
"src/agent/runner/harness/pi/tools.ts",
"src/agent/runner/sequence/orchestrator/queue-tools.ts",
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts",
"src/store/services/steps/add-mcp-server-to-clients/MCPClient.ts"
"src/store/agent-protocol/agent-env-isolation.ts",
"src/store/agent-protocol/agent-signals.ts"
]
},
"src/agent/runner/harness/pi/tasks.ts": {
Expand All @@ -162,9 +160,8 @@
],
"imports": [
"src/agent/aio-capture.ts",
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts",
"src/store/services/steps/add-mcp-server-to-clients/MCPClient.ts"
"src/store/agent-protocol/agent-env-isolation.ts",
"src/store/auth-session-state.ts"
]
},
"src/agent/runner/sequence/orchestrator/queue-tools.ts": {
Expand Down Expand Up @@ -219,11 +216,10 @@
"src/cli/commands/basic-integration/non-interactive.ts",
"src/cli/commands/basic-integration/playground.ts",
"src/cli/control-hooks.ts",
"src/store/agent-protocol/agent-env-isolation.ts",
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts",
"src/store/services/steps/add-mcp-server-to-clients/MCPClient.ts",
"src/tui/App.tsx",
"src/tui/console/headless-ui.ts"
"src/tui/App.tsx"
]
},
"src/cli/commands/basic-integration/ci-install.ts": {
Expand All @@ -233,8 +229,7 @@
"imports": [
"src/cli/control-hooks.ts",
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts",
"src/tui/console/headless-ui.ts"
"src/store/auth-session-state.ts"
]
},
"src/cli/commands/basic-integration/interactive.ts": {
Expand Down Expand Up @@ -273,13 +268,50 @@
],
"imports": [
"src/agent/agent-prompt.ts",
"src/store/agent-protocol/agent-env-isolation.ts",
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts",
"src/store/control/actions.ts",
"src/store/programs/ai-opt-in-gate.ts",
"src/store/services/steps/add-mcp-server-to-clients/MCPClient.ts",
"src/tui/App.tsx",
"src/tui/console/headless-ui.ts"
"src/tui/App.tsx"
]
},
"src/store/agent-protocol/agent-env-isolation.ts": {
"sources": [
"src/store/agent-protocol/agent-env-isolation.ts",
"src/store/agent-protocol/agent-phase.ts",
"src/store/agent-protocol/mcp-prompt.ts",
"src/store/agent-protocol/token-pricing.ts",
"src/store/file-watcher.ts",
"src/store/mcp-project-profile.ts",
"src/store/mcp-role-prompts.copy.json",
"src/store/mcp-role-prompts.ts",
"src/store/mcp-seed-events.ts",
"src/store/safe-tools.ts",
"src/store/services/claude-settings.ts",
"src/store/services/steps/add-mcp-server-to-clients/browser-client.ts",
"src/store/services/steps/add-mcp-server-to-clients/login-client.ts",
"src/store/session/secret-vault.ts",
"src/store/shared/clipboard.ts",
"src/store/shared/custom-headers.ts",
"src/store/shared/env-api-key.ts",
"src/store/shared/environment.ts",
"src/store/shared/terminal-bell.ts",
"src/store/state/run-store.ts",
"src/store/state/store.ts",
"src/store/task-stream/audit-areas.ts",
"src/store/task-stream/destinations/file.ts",
"src/store/task-stream/destinations/posthog.ts",
"src/store/task-stream/event-plan-watcher.ts",
"src/store/task-stream/task-stream-push.ts",
"src/store/tools/handoff.ts",
"src/store/ui/store-ui.ts",
"src/store/ui/wizard-ui.ts",
"src/store/wizard-spellbook.ts"
],
"imports": [
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts"
]
},
"src/store/agent-protocol/agent-signals.ts": {
Expand Down Expand Up @@ -470,9 +502,9 @@
"src/store/programs/run-config.ts"
],
"imports": [
"src/store/agent-protocol/agent-env-isolation.ts",
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts",
"src/store/services/steps/add-mcp-server-to-clients/MCPClient.ts"
"src/store/auth-session-state.ts"
]
},
"src/store/services/steps/add-mcp-server-to-clients/MCPClient.ts": {
Expand Down Expand Up @@ -687,19 +719,11 @@
"src/tui/ui-store.ts"
],
"imports": [
"src/store/agent-protocol/agent-env-isolation.ts",
"src/store/agent-protocol/agent-signals.ts",
"src/store/auth-session-state.ts",
"src/store/programs/ai-opt-in-gate.ts",
"src/store/services/steps/add-mcp-server-to-clients/MCPClient.ts"
]
},
"src/tui/console/headless-ui.ts": {
"sources": [
"src/tui/console/headless-ui.ts",
"src/tui/console/logging-ui.ts"
],
"imports": [
"src/store/auth-session-state.ts"
]
}
}
1 change: 1 addition & 0 deletions scripts/__fixtures__/chunk-manifest.prod.json
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@
"src/store/shared/env-api-key.ts",
"src/store/shared/environment.ts",
"src/store/shared/terminal-bell.ts",
"src/store/state/run-store.ts",
"src/store/state/store.ts",
"src/store/task-stream/audit-areas.ts",
"src/store/task-stream/destinations/file.ts",
Expand Down
Loading
Loading