@chanlerdev/scorel 0.0.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/README.md +110 -0
- package/dist/index.js +6675 -0
- package/dist/index.js.map +7 -0
- package/docs/CHANGELOG.md +12 -0
- package/docs/README.md +116 -0
- package/docs/ROADMAP.md +669 -0
- package/docs/SHIP.md +242 -0
- package/docs/spec/channels.md +156 -0
- package/docs/spec/client.md +326 -0
- package/docs/spec/daemon.md +408 -0
- package/docs/spec/events.md +423 -0
- package/docs/spec/extensions.md +255 -0
- package/docs/spec/relay.md +391 -0
- package/docs/spec/runtime.md +251 -0
- package/docs/spec/session.md +380 -0
- package/docs/spec/ship/S0001-docs-baseline.md +41 -0
- package/docs/spec/ship/S0002-package-skeleton.md +56 -0
- package/docs/spec/ship/S0003-protocol-contracts.md +49 -0
- package/docs/spec/ship/S0004-session-core.md +50 -0
- package/docs/spec/ship/S0005-runtime-loop.md +48 -0
- package/docs/spec/ship/S0006-embedded-daemon-client.md +51 -0
- package/docs/spec/ship/S0007-cli-alpha.md +49 -0
- package/docs/spec/ship/S0008-coding-tools.md +107 -0
- package/docs/spec/ship/S0009-code-discovery-tools.md +82 -0
- package/docs/spec/ship/S0010-todo-tool-and-cli.md +81 -0
- package/docs/spec/ship/S0011-coding-agent-alpha-smoke.md +110 -0
- package/docs/spec/ship/S0012-coding-tools-maturity.md +143 -0
- package/docs/spec/ship/S0013-local-daemon-protocol.md +57 -0
- package/docs/spec/ship/S0014-local-daemon-lifecycle.md +64 -0
- package/docs/spec/ship/S0015-local-attach-and-broadcast.md +58 -0
- package/docs/spec/ship/S0016-local-daemon-resync-smoke.md +60 -0
- package/docs/spec/ship/S0017-grep-files-output-mode.md +49 -0
- package/docs/spec/ship/S0018-daemon-entrypoint-smoke.md +48 -0
- package/docs/spec/ship/S0019-remote-transport-contract.md +59 -0
- package/docs/spec/ship/S0020-remote-websocket-server.md +56 -0
- package/docs/spec/ship/S0021-remote-websocket-client-transport.md +55 -0
- package/docs/spec/ship/S0022-remote-daemon-cli-lifecycle.md +60 -0
- package/docs/spec/ship/S0023-remote-control-e2e-validation.md +66 -0
- package/docs/spec/ship/S0024-remote-attach-interactive-stream.md +49 -0
- package/docs/spec/ship/S0025-remote-attach-session-event-view.md +57 -0
- package/docs/spec/ship/S0026-attach-project-cache-and-dual-seq-reconnect.md +87 -0
- package/docs/spec/ship/S0027-session-diagnostics-log.md +77 -0
- package/docs/spec/ship/S0028-client-attach-diagnostics-log.md +70 -0
- package/docs/spec/ship/S0029-project-index-for-session-lookup.md +119 -0
- package/docs/spec/ship/S0030-webui-product-intent.md +73 -0
- package/docs/spec/ship/S0031-daemon-projectslug-rule.md +72 -0
- package/docs/spec/ship/S0032-daemon-protocol-completion.md +123 -0
- package/docs/spec/ship/S0033-webui-skeleton-routing.md +92 -0
- package/docs/spec/ship/S0034-webui-device-settings.md +121 -0
- package/docs/spec/ship/S0035-webui-device-handshake.md +83 -0
- package/docs/spec/ship/S0036-webui-project-session-sync.md +70 -0
- package/docs/spec/ship/S0037-webui-chatbox-v1.md +97 -0
- package/docs/spec/ship/S0038-webui-cancel-multiclient.md +65 -0
- package/docs/spec/ship/S0039-webui-e2e-newchat.md +74 -0
- package/docs/spec/ship/S0040-webui-codex-visual-tokens.md +227 -0
- package/docs/spec/ship/S0041-webui-markdown-and-tool-block.md +248 -0
- package/docs/spec/ship/S0042-webui-streaming-ux-autoscroll.md +130 -0
- package/docs/spec/ship/S0043-startup-ergonomics.md +278 -0
- package/docs/spec/ship/S0044-webui-chatbox-rebuild.md +556 -0
- package/docs/spec/ship/S0045-webui-card-sidebar-and-session-fixes.md +469 -0
- package/docs/spec/ship/S0046-webui-empty-composer-and-lazy-session.md +428 -0
- package/docs/spec/ship/S0047-webui-project-hover-newchat-and-dynamic-greeting.md +176 -0
- package/docs/spec/ship/S0048-device-level-host-project-registry.md +253 -0
- package/docs/spec/ship/S0049-webui-add-project-directory-browser.md +217 -0
- package/docs/spec/ship/S0050-instruction-snapshot-and-agents-assembly.md +338 -0
- package/docs/spec/ship/S0051-harness-item-and-system-reminder.md +190 -0
- package/docs/spec/ship/S0052-follow-up-queue-and-dual-loop.md +195 -0
- package/docs/spec/ship/S0053-skill-index-and-skill-tool.md +252 -0
- package/docs/spec/ship/S0054-webui-running-message-behavior.md +72 -0
- package/docs/spec/ship/S0055-webui-composer-acceptance-and-queue-strip.md +68 -0
- package/docs/spec/ship/S0056-relay-and-hosted-webui-contract.md +106 -0
- package/docs/spec/ship/S0057-relay-service-protocol-skeleton.md +161 -0
- package/docs/spec/ship/S0058-host-outbound-relay-and-pair-command.md +138 -0
- package/docs/spec/ship/S0059-relay-transport-and-hosted-webui-connector.md +140 -0
- package/docs/spec/ship/S0060-relay-hosted-webui-e2e-validation.md +132 -0
- package/docs/spec/ship/S0060-relay-hosted-webui-e2e-validation.verification.md +90 -0
- package/docs/spec/ship/S0061-hosted-defaults-and-cli-command-surface.md +208 -0
- package/docs/spec/ship/S0062-npm-package-and-release-workflow.md +166 -0
- package/docs/spec/tools.md +173 -0
- package/package.json +51 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# S0025: Remote Attach Session Event View
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Fix `scorel attach` so every attached terminal behaves as a consistent session event view.
|
|
6
|
+
|
|
7
|
+
User messages, final assistant messages, tool results, and recoverable events must be visible to all attached clients. A reconnect must recover missed persistent session state from the daemon instead of relying only on live transient deltas.
|
|
8
|
+
|
|
9
|
+
## Scope
|
|
10
|
+
|
|
11
|
+
- Render `user_message` events in attached terminals so all clients see the same submitted prompts.
|
|
12
|
+
- Render missed persistent `assistant_message` and `tool_result` events returned by `load_session` / `resync_events`.
|
|
13
|
+
- Keep live `text_delta` rendering for in-flight assistant output.
|
|
14
|
+
- Avoid duplicating final assistant text when a client already rendered its live deltas.
|
|
15
|
+
- Add terminal line boundary handling so passive clients do not leave the next user input prompt on the same line as assistant output.
|
|
16
|
+
- Make explicit `create_session` idempotent enough for concurrent attach clients racing to create the same session id.
|
|
17
|
+
- Keep local socket attach and remote WebSocket attach on the same CLI code path.
|
|
18
|
+
- Validate with real daemon/client processes and the real provider path.
|
|
19
|
+
|
|
20
|
+
## Not In Scope
|
|
21
|
+
|
|
22
|
+
- Byte-for-byte replay of transient text deltas that were emitted before a client connected.
|
|
23
|
+
- Automatic network reconnect loop after a socket closes.
|
|
24
|
+
- Full TUI/editor prompt management.
|
|
25
|
+
- Per-client scrollback preferences.
|
|
26
|
+
- Cancel/interrupt propagation.
|
|
27
|
+
|
|
28
|
+
## Acceptance Criteria
|
|
29
|
+
|
|
30
|
+
- Two remote `scorel attach` clients connected to one session both display a submitted `user_message`.
|
|
31
|
+
- A client that reconnects after a turn completes can display missed persistent assistant output from JSONL-backed daemon state.
|
|
32
|
+
- A client that reconnects while a turn is still running recovers persisted events already committed and continues to receive future live events.
|
|
33
|
+
- Two clients attaching to the same missing session at the same time do not leave either client stuck waiting for `create_session`.
|
|
34
|
+
- Passive terminal output has clean line boundaries between session events and user input.
|
|
35
|
+
- `pnpm check` passes.
|
|
36
|
+
|
|
37
|
+
## Tests
|
|
38
|
+
|
|
39
|
+
- Add focused CLI tests for persistent event rendering and terminal boundaries.
|
|
40
|
+
- Run `pnpm --filter @scorel/app-cli test`.
|
|
41
|
+
- Run `pnpm check`.
|
|
42
|
+
- Run manual real-process validation with one `scorel-daemon serve` process and two `scorel attach --remote` clients sharing one session.
|
|
43
|
+
|
|
44
|
+
## Affected Paths
|
|
45
|
+
|
|
46
|
+
- `apps/cli/src/index.ts`
|
|
47
|
+
- `apps/cli/src/index.test.ts`
|
|
48
|
+
- `packages/daemon/src/index.ts`
|
|
49
|
+
- `packages/daemon/src/embedded/embedded.test.ts`
|
|
50
|
+
- `docs/ROADMAP.md`
|
|
51
|
+
- `self/discussions/2026-05-29-m4-remote-control-planning.md`
|
|
52
|
+
|
|
53
|
+
## Risks And Boundaries
|
|
54
|
+
|
|
55
|
+
- The reliable recovery source is persistent session JSONL. Transient events remain best-effort live UI events.
|
|
56
|
+
- The CLI must not add a hidden test-only mode, fake transport, or fake protocol branch.
|
|
57
|
+
- Rendering should be idempotent by event id so reconnect/resync does not duplicate already displayed persistent messages.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# S0026: Attach Project Cache And Dual-Seq Reconnect
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Fix attach recovery so local and remote project sessions can resume from a client-owned persistent cache, while reconnect semantics remain aligned with daemon authority.
|
|
6
|
+
|
|
7
|
+
This spec closes the gap left by S0024/S0025: reconnect must distinguish between durable client state and previously seen stream state, support project-scoped session storage for both local and remote projects, and continue live streaming after persistent fallback.
|
|
8
|
+
|
|
9
|
+
## Scope
|
|
10
|
+
|
|
11
|
+
- Introduce a project-scoped session storage model for attach-visible session persistence instead of treating all sessions as flat global files.
|
|
12
|
+
- Define local and remote project identity at the same abstraction level:
|
|
13
|
+
- local projects under a local scope
|
|
14
|
+
- remote projects under a remote device scope
|
|
15
|
+
- Remote attach cache identity is `deviceId + projectSlug + sessionId`. The connection URL is a transport endpoint and may be used only as a fallback before daemon identity is known.
|
|
16
|
+
- Daemon connection metadata must expose a stable `deviceId`, optional user-facing `deviceDisplayName`, and a stable `projectSlug` for the served project.
|
|
17
|
+
- Store client-visible persistent session backlog under the project scope so attach can render local persistent history before daemon reconciliation.
|
|
18
|
+
- Store in-progress assistant transient text under the same project scope when the client has durable stream anchors, so a process restart can display the already-seen prefix before asking daemon to continue from `streamLastSeq`.
|
|
19
|
+
- Define dual reconnect anchors:
|
|
20
|
+
- `persistentLastSeq`: highest seq guaranteed by locally persisted persistent events
|
|
21
|
+
- `streamLastSeq`: highest seq the client has actually observed in the event stream
|
|
22
|
+
- Upgrade reconnect/resync contract so daemon can distinguish:
|
|
23
|
+
- stream resume from buffer
|
|
24
|
+
- persistent-only fallback
|
|
25
|
+
- full reload
|
|
26
|
+
- Define persistent fallback semantics precisely:
|
|
27
|
+
- daemon only replays missing persistent events
|
|
28
|
+
- client immediately returns to live subscription after fallback completes
|
|
29
|
+
- lost transient continuity before the fallback boundary is treated as unrecoverable, not silently reconstructed
|
|
30
|
+
- Define the cutover boundary between fallback replay and subsequent live stream so fallback does not skip live events produced during recovery.
|
|
31
|
+
- Define cache mismatch behavior for stdout-only clients that cannot visually roll back pre-rendered history.
|
|
32
|
+
- Keep local attach and remote attach on the same product path and cache model.
|
|
33
|
+
- Update spec/docs language so `lastSeq` is no longer treated as a single sufficient reconnect anchor once client-owned cache exists.
|
|
34
|
+
|
|
35
|
+
## Not In Scope
|
|
36
|
+
|
|
37
|
+
- Full byte-for-byte reconstruction of transient events after client process restart.
|
|
38
|
+
- Full TUI scrollback manager or editor-like terminal persistence.
|
|
39
|
+
- Automatic daemon crash recovery beyond current daemon-owned session persistence.
|
|
40
|
+
- Relay/tunnel/public remote service features.
|
|
41
|
+
- Background reconnect daemon running outside the CLI attach process.
|
|
42
|
+
|
|
43
|
+
## Acceptance Criteria
|
|
44
|
+
|
|
45
|
+
- A local attach client and a remote attach client both map their session persistence through a project-scoped directory instead of a flat global session file assumption.
|
|
46
|
+
- Remote project sessions are separated from local project sessions by `deviceId + projectSlug` scope and do not collide with same-path local workspaces.
|
|
47
|
+
- If the same remote daemon project is reached through a different URL, attach can still reuse cache when daemon reports the same `deviceId + projectSlug`.
|
|
48
|
+
- `deviceDisplayName` is metadata for user-facing labels only; it must not replace stable `deviceId` in cache identity.
|
|
49
|
+
- Reconnect protocol explicitly carries both `persistentLastSeq` and `streamLastSeq`.
|
|
50
|
+
- If daemon buffer covers `streamLastSeq`, reconnect resumes the stream from `streamLastSeq + 1`.
|
|
51
|
+
- If daemon buffer does not cover `streamLastSeq` but client has persistent cache, daemon falls back to replaying only missing persistent events after `persistentLastSeq`, then the connection continues receiving future live transient and persistent events.
|
|
52
|
+
- Client can tell whether reconnect result was `stream_resume`, `persistent_fallback`, or `full_reload`; the mode is not inferred implicitly.
|
|
53
|
+
- Daemon proves buffer coverage by checking that the buffered stream continuously covers `streamLastSeq + 1`; having any later buffered event is not enough.
|
|
54
|
+
- In `persistent_fallback`, `throughSeq` is the highest replayed persistent seq, not blindly the daemon current seq. Future live events with higher seq remain deliverable after the replay response.
|
|
55
|
+
- CLI attach pre-renders only cache entries whose project/session metadata match the requested attach target; if daemon reconciliation reports `full_reload`, stale printed cache is separated from authoritative replay instead of being silently treated as current history.
|
|
56
|
+
- Cold-start attach does not claim stream resume from a transient seq unless the client has durable transient anchors for that stream. Without such anchors, it uses the persistent anchor and accepts fallback semantics.
|
|
57
|
+
- Resynced transient events returned in `resync_events.events` are delivered to subscribers/renderers, not only folded into internal client state.
|
|
58
|
+
- CLI attach reads input into a queue and serializes sends, so lines typed or pasted while a turn is running are queued instead of being hidden behind the pending `sendMessage` await.
|
|
59
|
+
- `pnpm typecheck && pnpm test` passes.
|
|
60
|
+
- Manual validation covers one real remote daemon and one local attach client reconnecting through the new semantics.
|
|
61
|
+
|
|
62
|
+
## Tests
|
|
63
|
+
|
|
64
|
+
- Add focused protocol/client/CLI tests for dual-seq reconnect semantics.
|
|
65
|
+
- Add tests for project-scope session directory resolution for local and remote projects.
|
|
66
|
+
- Add tests proving persistent fallback returns to live event streaming instead of leaving the client in replay-only mode.
|
|
67
|
+
- Add tests for buffer gap detection, fallback `throughSeq` cutover, same `sessionId` under different project scopes, and duplicate-free CLI rendering from cache + daemon replay.
|
|
68
|
+
- Run `pnpm typecheck && pnpm test`.
|
|
69
|
+
- Run one manual real-process validation with real provider path, real temporary workspace, real JSONL session, and remote reconnect.
|
|
70
|
+
|
|
71
|
+
## Affected Paths
|
|
72
|
+
|
|
73
|
+
- `docs/spec/client.md`
|
|
74
|
+
- `docs/spec/daemon.md`
|
|
75
|
+
- `docs/spec/session.md`
|
|
76
|
+
- `docs/architecture.md`
|
|
77
|
+
- `docs/ROADMAP.md`
|
|
78
|
+
- `docs/spec/ship/S0026-attach-project-cache-and-dual-seq-reconnect.md`
|
|
79
|
+
- `self/discussions/2026-05-29-attach-project-cache-dual-seq.md`
|
|
80
|
+
|
|
81
|
+
## Risks And Boundaries
|
|
82
|
+
|
|
83
|
+
- Project key design must stay readable without using fragile reversible path encoding as the source of truth; metadata must preserve the real locator.
|
|
84
|
+
- `deviceId` is sufficient as a remote namespace only if project metadata also stores the original remote workspace locator.
|
|
85
|
+
- Dual-seq reconnect adds protocol complexity; daemon and client must share one exact recovery-state model to avoid hidden divergence.
|
|
86
|
+
- Persistent cache is a client-side acceleration and recovery aid, not a replacement for daemon session authority.
|
|
87
|
+
- Terminal stdout cannot retract stale cache output. CLI must prefer conservative rendering and explicit recovery markers over optimistic UI tricks that only work in GUI clients.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# S0027: Session Diagnostics Log
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Add a per-session diagnostics log so provider, runtime, daemon, and reconnect failures are visible without overloading session JSONL or attach cache.
|
|
6
|
+
|
|
7
|
+
Session JSONL remains the replayable product record. Attach cache remains a client-side terminal recovery aid. Diagnostics logs are daemon-owned debugging evidence stored beside the daemon session file.
|
|
8
|
+
|
|
9
|
+
## Scope
|
|
10
|
+
|
|
11
|
+
- Store a diagnostics log beside each daemon-owned session JSONL file:
|
|
12
|
+
- session: `<sessionsDir>/<sessionId>.jsonl`
|
|
13
|
+
- diagnostics log: `<sessionsDir>/<sessionId>.log`
|
|
14
|
+
- Use append-only plain text `.log` lines, one log entry per line.
|
|
15
|
+
- Keep lines human-readable and grep-friendly, with stable key/value fields where useful.
|
|
16
|
+
- Record enough detail to debug failed real-provider turns:
|
|
17
|
+
- session create/load
|
|
18
|
+
- client connect/disconnect identity
|
|
19
|
+
- `send_message` start/end
|
|
20
|
+
- runtime turn start/end
|
|
21
|
+
- provider-visible assistant result summary
|
|
22
|
+
- runtime/provider errors with message and short stack
|
|
23
|
+
- resync mode and anchor values
|
|
24
|
+
- Keep logs on the machine that owns the daemon session:
|
|
25
|
+
- embedded/local daemon logs live beside local session JSONL
|
|
26
|
+
- remote daemon logs live beside remote session JSONL
|
|
27
|
+
- local attach cache does not store daemon diagnostics
|
|
28
|
+
- Add a minimal CLI read path for local files, enough to inspect the current machine's session diagnostics.
|
|
29
|
+
|
|
30
|
+
## Not In Scope
|
|
31
|
+
|
|
32
|
+
- Log levels, log rotation, retention policy, compression, or upload.
|
|
33
|
+
- GUI log viewer.
|
|
34
|
+
- Remote log retrieval over the daemon protocol.
|
|
35
|
+
- Logging full prompt text, full tool results, full provider payloads, or secrets.
|
|
36
|
+
- Changing the session JSONL event schema.
|
|
37
|
+
- Making attach cache authoritative or diagnostic.
|
|
38
|
+
|
|
39
|
+
## Acceptance Criteria
|
|
40
|
+
|
|
41
|
+
- Creating or loading a session can create/use `<sessionsDir>/<sessionId>.log` beside `<sessionId>.jsonl`.
|
|
42
|
+
- `send_message` writes start and finish log lines including `sessionId`, `clientId`, and resulting event ids.
|
|
43
|
+
- Runtime/provider errors write a line containing the error message and a short stack excerpt.
|
|
44
|
+
- Assistant result log lines include `stopReason`, text block count, tool call count, and usage when present.
|
|
45
|
+
- `resync_events` writes a line with recovery mode, `persistentLastSeq`, `streamLastSeq`, `throughSeq`, and returned event count.
|
|
46
|
+
- Connect/disconnect logs include client id, daemon `deviceId`, optional display name, and project slug when available.
|
|
47
|
+
- Logs do not include bearer tokens or API keys.
|
|
48
|
+
- `scorel logs --session <id>` can print the local `<sessionId>.log`; `--tail <n>` limits output to the last `n` lines.
|
|
49
|
+
- `pnpm typecheck && pnpm test` passes.
|
|
50
|
+
|
|
51
|
+
## Tests
|
|
52
|
+
|
|
53
|
+
- Add core session tests for log file path derivation beside session JSONL.
|
|
54
|
+
- Add daemon tests proving `send_message`, runtime error, and resync write diagnostics lines.
|
|
55
|
+
- Add CLI tests for `scorel logs --session <id>` and `--tail <n>`.
|
|
56
|
+
- Run targeted package tests.
|
|
57
|
+
- Run `pnpm typecheck && pnpm test`.
|
|
58
|
+
|
|
59
|
+
## Affected Paths
|
|
60
|
+
|
|
61
|
+
- `docs/ROADMAP.md`
|
|
62
|
+
- `docs/spec/session.md`
|
|
63
|
+
- `docs/spec/daemon.md`
|
|
64
|
+
- `docs/spec/ship/S0027-session-diagnostics-log.md`
|
|
65
|
+
- `packages/core/src/session/index.ts`
|
|
66
|
+
- `packages/core/src/session/session.test.ts`
|
|
67
|
+
- `packages/daemon/src/index.ts`
|
|
68
|
+
- `packages/daemon/src/protocol.test.ts`
|
|
69
|
+
- `apps/cli/src/index.ts`
|
|
70
|
+
- `apps/cli/src/index.test.ts`
|
|
71
|
+
|
|
72
|
+
## Risks And Boundaries
|
|
73
|
+
|
|
74
|
+
- Logs can leak sensitive data if they capture raw prompts, tool results, provider payloads, tokens, or API keys. S0027 must prefer summaries and explicit error messages over raw payload dumps.
|
|
75
|
+
- Plain `.log` is intentionally less structured than session JSONL. Keep key names stable enough for grep, but do not turn this into a second event protocol.
|
|
76
|
+
- Remote diagnostics remain on the remote daemon host until a future spec adds remote log retrieval. S0027 should not silently copy remote logs into local attach cache.
|
|
77
|
+
- Rich logging can become noisy. Keep the first version focused on lifecycle, recovery, result summaries, and errors.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# S0028: Client Attach Diagnostics Log
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Add a client-side attach diagnostics log so local clients can debug remote attach, reconnect, cache, and rendering behavior without SSH access to the remote daemon host.
|
|
6
|
+
|
|
7
|
+
S0027 added daemon-owned session diagnostics beside daemon session JSONL. S0028 adds the complementary client-owned attach diagnostics beside the local attach cache.
|
|
8
|
+
|
|
9
|
+
## Scope
|
|
10
|
+
|
|
11
|
+
- Store attach diagnostics beside the local attach cache file:
|
|
12
|
+
- cache: `<stateDir>/attach-cache/<scopeKey>/<sessionId>.json`
|
|
13
|
+
- attach diagnostics: `<stateDir>/attach-cache/<scopeKey>/<sessionId>.log`
|
|
14
|
+
- Use append-only plain text `.log` lines, one log entry per line.
|
|
15
|
+
- Keep remote and local attach on the same logging path.
|
|
16
|
+
- Record client-side attach lifecycle and transport-visible behavior:
|
|
17
|
+
- cache scope resolution
|
|
18
|
+
- cache read/write summaries
|
|
19
|
+
- connect start/success/failure, with token redacted
|
|
20
|
+
- daemon connection identity (`deviceId`, `deviceDisplayName`, `projectSlug`)
|
|
21
|
+
- load/create session result
|
|
22
|
+
- resync anchors and resync mode
|
|
23
|
+
- inbound events rendered by attach, including event type and seq
|
|
24
|
+
- outbound user input send start/finish/error
|
|
25
|
+
- disconnect/exit
|
|
26
|
+
- Permit richer payload logging than S0027 because session JSONL already stores product data, but never log bearer tokens, API keys, or local secret tokens.
|
|
27
|
+
- Add a CLI read path for attach logs.
|
|
28
|
+
|
|
29
|
+
## Not In Scope
|
|
30
|
+
|
|
31
|
+
- Remote retrieval of daemon-side `<sessionId>.log`.
|
|
32
|
+
- Log rotation, retention, compression, upload, or GUI.
|
|
33
|
+
- Making attach logs authoritative replay state.
|
|
34
|
+
- Changing attach cache JSON shape beyond metadata needed to find the sibling log.
|
|
35
|
+
- Recording raw secrets.
|
|
36
|
+
|
|
37
|
+
## Acceptance Criteria
|
|
38
|
+
|
|
39
|
+
- Running `scorel attach --remote ...` writes `<stateDir>/attach-cache/<scopeKey>/<sessionId>.log` next to the attach cache JSON.
|
|
40
|
+
- The attach log includes cache scope identity, connect success, daemon identity, resync mode, rendered inbound events, send start/finish, and disconnect.
|
|
41
|
+
- Token values are not present in attach diagnostics.
|
|
42
|
+
- Local attach also writes a sibling attach diagnostics log under its local scope.
|
|
43
|
+
- `scorel logs --attach --session <id> --remote <url>` can print the local attach diagnostics log for the matching remote `deviceId + projectSlug` scope after at least one connect has resolved that identity.
|
|
44
|
+
- `scorel logs --attach --session <id> --tail <n>` can print local attach diagnostics for local attach scope.
|
|
45
|
+
- Existing `scorel logs --session <id>` keeps reading daemon-side session diagnostics.
|
|
46
|
+
- `pnpm typecheck && pnpm test` passes.
|
|
47
|
+
|
|
48
|
+
## Tests
|
|
49
|
+
|
|
50
|
+
- Add CLI tests that run remote attach twice through different endpoints with the same daemon identity and verify the attach log is reused beside the cache.
|
|
51
|
+
- Add CLI tests that assert attach logs contain lifecycle entries and do not contain the token.
|
|
52
|
+
- Add CLI tests for `scorel logs --attach --session <id> --remote <url> --tail <n>`.
|
|
53
|
+
- Run targeted CLI tests.
|
|
54
|
+
- Run `pnpm typecheck && pnpm test`.
|
|
55
|
+
|
|
56
|
+
## Affected Paths
|
|
57
|
+
|
|
58
|
+
- `docs/ROADMAP.md`
|
|
59
|
+
- `docs/spec/client.md`
|
|
60
|
+
- `docs/spec/session.md`
|
|
61
|
+
- `docs/spec/ship/S0028-client-attach-diagnostics-log.md`
|
|
62
|
+
- `apps/cli/src/index.ts`
|
|
63
|
+
- `apps/cli/src/index.test.ts`
|
|
64
|
+
|
|
65
|
+
## Risks And Boundaries
|
|
66
|
+
|
|
67
|
+
- Attach logs can grow quickly if every event is logged in full. S0028 should log enough payload context to debug, but keep one-line entries grep-friendly.
|
|
68
|
+
- Attach logs are local client evidence. They can prove what the client saw and rendered, but not provider/runtime internals on the remote daemon host.
|
|
69
|
+
- Remote URL alone is not stable identity. When daemon identity is known, attach diagnostics must use the same `deviceId + projectSlug` scope as attach cache.
|
|
70
|
+
- Secret redaction must be explicit and tested.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# S0029: Project Index For Session Lookup
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Add a lightweight project index so CLI and future GUI surfaces can organize local and remote sessions by project instead of by storage path shape.
|
|
6
|
+
|
|
7
|
+
Session JSONL, daemon diagnostics, attach cache, and attach diagnostics already live in different physical locations. S0029 adds one lookup file that maps project identity to those existing session assets without migrating or duplicating them.
|
|
8
|
+
|
|
9
|
+
## Scope
|
|
10
|
+
|
|
11
|
+
- Add one index file:
|
|
12
|
+
- `<stateDir>/project-index.json`
|
|
13
|
+
- Do not add a `projects/` directory.
|
|
14
|
+
- Do not move existing files:
|
|
15
|
+
- `<stateDir>/sessions/<sessionId>.jsonl`
|
|
16
|
+
- `<stateDir>/sessions/<sessionId>.log`
|
|
17
|
+
- `<stateDir>/attach-cache/<scopeKey>/<sessionId>.json`
|
|
18
|
+
- `<stateDir>/attach-cache/<scopeKey>/<sessionId>.log`
|
|
19
|
+
- Treat project as the user-facing organization unit:
|
|
20
|
+
- local project identity is the canonical CLI `workDir`
|
|
21
|
+
- remote project identity is the remote daemon `projectSlug`
|
|
22
|
+
- `deviceId` is a namespace/disambiguator for remote devices with the same `projectSlug`
|
|
23
|
+
- `deviceDisplayName` and project display names are UI metadata, not identity
|
|
24
|
+
- remote URL is only the latest connection endpoint, not identity
|
|
25
|
+
- Update the project index from:
|
|
26
|
+
- `scorel chat` for local sessions
|
|
27
|
+
- local `scorel attach` for local attach cache/logs
|
|
28
|
+
- remote `scorel attach` for remote attach cache/logs
|
|
29
|
+
- Use the project index for attach log lookup before falling back to legacy attach-cache scanning.
|
|
30
|
+
|
|
31
|
+
## Not In Scope
|
|
32
|
+
|
|
33
|
+
- GUI project browser.
|
|
34
|
+
- Moving session/cache/log files into project directories.
|
|
35
|
+
- Remote retrieval of daemon-owned session JSONL or daemon diagnostics.
|
|
36
|
+
- Global search, retention, rotation, or compaction of index data.
|
|
37
|
+
- Making the index authoritative session state.
|
|
38
|
+
|
|
39
|
+
## Index Shape
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"version": 1,
|
|
44
|
+
"projects": [
|
|
45
|
+
{
|
|
46
|
+
"projectKey": "local:/Users/chanler/Scorel",
|
|
47
|
+
"kind": "local",
|
|
48
|
+
"workDir": "/Users/chanler/Scorel",
|
|
49
|
+
"displayName": "Scorel",
|
|
50
|
+
"lastSeenAt": 1716000000000,
|
|
51
|
+
"sessions": {
|
|
52
|
+
"ses_local": {
|
|
53
|
+
"sessionId": "ses_local",
|
|
54
|
+
"source": "local-session",
|
|
55
|
+
"sessionPath": "sessions/ses_local.jsonl",
|
|
56
|
+
"logPath": "sessions/ses_local.log",
|
|
57
|
+
"lastSeenAt": 1716000000000
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"projectKey": "remote:device_vps:scorel",
|
|
63
|
+
"kind": "remote",
|
|
64
|
+
"deviceId": "device_vps",
|
|
65
|
+
"deviceDisplayName": "Tokyo VPS",
|
|
66
|
+
"projectSlug": "scorel",
|
|
67
|
+
"displayName": "scorel",
|
|
68
|
+
"lastRemoteUrl": "wss://example.invalid",
|
|
69
|
+
"lastSeenAt": 1716000000000,
|
|
70
|
+
"sessions": {
|
|
71
|
+
"ses_remote": {
|
|
72
|
+
"sessionId": "ses_remote",
|
|
73
|
+
"source": "attach-cache",
|
|
74
|
+
"cachePath": "attach-cache/abc123/ses_remote.json",
|
|
75
|
+
"logPath": "attach-cache/abc123/ses_remote.log",
|
|
76
|
+
"lastSeenAt": 1716000000000
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The index stores relative paths from `<stateDir>` so it remains portable across test temp dirs and product roots.
|
|
85
|
+
|
|
86
|
+
## Acceptance Criteria
|
|
87
|
+
|
|
88
|
+
- `scorel chat --cwd <dir> --session <id>` records a local project entry keyed by the canonical `workDir`.
|
|
89
|
+
- local `scorel attach --session <id>` records a local project/session entry with attach cache and attach log paths.
|
|
90
|
+
- remote `scorel attach --remote <url> --session <id>` records a remote project entry keyed by `remote:<deviceId>:<projectSlug>`.
|
|
91
|
+
- Remote project display/organization uses `projectSlug`; `deviceId` only disambiguates devices.
|
|
92
|
+
- `lastRemoteUrl` is recorded but does not participate in identity.
|
|
93
|
+
- `scorel logs --attach --session <id> --remote <url>` can resolve the attach diagnostics log through `project-index.json`.
|
|
94
|
+
- If index lookup is unavailable, legacy attach-cache scanning remains as a compatibility fallback.
|
|
95
|
+
- Existing session and attach cache/log paths remain unchanged.
|
|
96
|
+
- `pnpm typecheck && pnpm test` passes.
|
|
97
|
+
|
|
98
|
+
## Tests
|
|
99
|
+
|
|
100
|
+
- Add CLI tests for local chat writing `project-index.json` with canonical workDir and session log path.
|
|
101
|
+
- Add CLI tests for remote attach writing remote project index entries with `projectSlug`, `deviceId`, `lastRemoteUrl`, cache path, and log path.
|
|
102
|
+
- Add CLI tests for `scorel logs --attach` reading via project index.
|
|
103
|
+
- Run targeted CLI tests.
|
|
104
|
+
- Run `pnpm typecheck && pnpm test`.
|
|
105
|
+
|
|
106
|
+
## Affected Paths
|
|
107
|
+
|
|
108
|
+
- `docs/ROADMAP.md`
|
|
109
|
+
- `docs/spec/client.md`
|
|
110
|
+
- `docs/spec/session.md`
|
|
111
|
+
- `docs/spec/ship/S0029-project-index-for-session-lookup.md`
|
|
112
|
+
- `apps/cli/src/index.ts`
|
|
113
|
+
- `apps/cli/src/index.test.ts`
|
|
114
|
+
|
|
115
|
+
## Risks And Boundaries
|
|
116
|
+
|
|
117
|
+
- Index writes must not make session/cache writes authoritative or fragile. If the index is missing or corrupt, commands should keep working where possible.
|
|
118
|
+
- Multiple projects may contain the same random `sessionId`. Lookup must prefer matching remote URL/project metadata where available and avoid silently selecting the wrong project when ambiguity is detectable.
|
|
119
|
+
- The index can be rebuilt later from existing files and metadata; S0029 only creates and updates it opportunistically on product paths.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# WebUI Product Intent
|
|
2
|
+
|
|
3
|
+
This note captures the intended WebUI product shape after rolling back the first M5 implementation attempts. It is not an implementation spec.
|
|
4
|
+
|
|
5
|
+
## Core Idea
|
|
6
|
+
|
|
7
|
+
WebUI is a remote-only chatbox client. It should feel like Codex App / Alma, not like a dashboard, diagnostics page, or connection form.
|
|
8
|
+
|
|
9
|
+
The product hierarchy is:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
Device -> Project -> Session -> Chatbox
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Device
|
|
16
|
+
|
|
17
|
+
A remote endpoint is user-facing as a Device.
|
|
18
|
+
|
|
19
|
+
A Device has:
|
|
20
|
+
|
|
21
|
+
- `Name`: user-visible device name.
|
|
22
|
+
- `Link`: remote daemon WebSocket endpoint.
|
|
23
|
+
- `Token`: remote daemon auth token.
|
|
24
|
+
|
|
25
|
+
Devices are managed in a dedicated Settings page. The primary chat sidebar should not contain endpoint/token fields.
|
|
26
|
+
|
|
27
|
+
## Sidebar
|
|
28
|
+
|
|
29
|
+
The main sidebar should follow the Codex App / Alma interaction pattern:
|
|
30
|
+
|
|
31
|
+
- top-level actions such as New Chat, Search, Skills, Plugins, Automations
|
|
32
|
+
- a Projects section
|
|
33
|
+
- within Projects, show Device roots
|
|
34
|
+
- under each Device, show Projects
|
|
35
|
+
- under each Project, show Sessions
|
|
36
|
+
- a bottom Settings entry
|
|
37
|
+
|
|
38
|
+
The sidebar must not show fake projects or fake sessions.
|
|
39
|
+
|
|
40
|
+
## Sync Model
|
|
41
|
+
|
|
42
|
+
WebUI cannot embed or manage a local daemon. It only connects to remote daemons.
|
|
43
|
+
|
|
44
|
+
After a Device connects:
|
|
45
|
+
|
|
46
|
+
1. read remote identity from daemon handshake
|
|
47
|
+
2. sync the Project index
|
|
48
|
+
3. sync Session lists under each Project
|
|
49
|
+
4. lazy-load Session content when the user clicks a Session
|
|
50
|
+
|
|
51
|
+
Session content should not be eagerly loaded for every session.
|
|
52
|
+
|
|
53
|
+
Browser-side storage should use `localStorage` only. WebUI must not write JSONL files or daemon attach caches.
|
|
54
|
+
|
|
55
|
+
## Chatbox
|
|
56
|
+
|
|
57
|
+
Opening a Session should show a normal chatbox:
|
|
58
|
+
|
|
59
|
+
- transcript/event stream in the main area
|
|
60
|
+
- user/assistant/tool/status events in chronological order
|
|
61
|
+
- bottom composer
|
|
62
|
+
- send/cancel controls
|
|
63
|
+
- shared remote daemon session state with other clients
|
|
64
|
+
|
|
65
|
+
Settings and connection management are not the main chat surface.
|
|
66
|
+
|
|
67
|
+
## Out Of Scope For M5
|
|
68
|
+
|
|
69
|
+
- GUI / Tauri / Electron
|
|
70
|
+
- local daemon process manager
|
|
71
|
+
- account auth / OAuth / relay / NAT traversal
|
|
72
|
+
- IDE-style file explorer or monitoring dashboard
|
|
73
|
+
- full rewind/fork/compact UI
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# S0031: Daemon ProjectSlug Generation Rule
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Lock how `EmbeddedDaemon` generates the `projectSlug` it exposes to clients, so daemon-side identity becomes self-determined instead of opaque options pass-through.
|
|
6
|
+
|
|
7
|
+
S0026 / S0029 already require `projectSlug` to be a stable, daemon-owned identifier. Neither spec defines the string-construction rule. Today `EmbeddedDaemon` accepts `projectSlug?` as a constructor option and forwards it verbatim through handshake / event metadata / diagnostics; whatever the embed host hands in becomes the slug. That is fragile and forces every entry point (CLI / future remote daemon CLI / future GUI host) to invent the same rule independently.
|
|
8
|
+
|
|
9
|
+
This spec adopts the codebuddy-style rule (`/Users/chanler/personal/Scorel` → `Users-chanler-personal-Scorel`) inside `@scorel/daemon`, removes slug construction from embed hosts, and makes the slug deterministic from the daemon working directory.
|
|
10
|
+
|
|
11
|
+
## Scope
|
|
12
|
+
|
|
13
|
+
- Add `packages/daemon/src/projects/slug.ts` exporting:
|
|
14
|
+
- `toProjectSlug(absolutePath: string): string`
|
|
15
|
+
- `fromProjectSlug(slug: string): string | null` (best-effort `-` → `/` reverse with leading `/`; returns null if obviously invalid)
|
|
16
|
+
- Replace `EmbeddedDaemon` constructor option `projectSlug?: string` with `workDir: string`. The daemon computes `projectSlug = toProjectSlug(workDir)` internally.
|
|
17
|
+
- Keep `deviceId` / `deviceDisplayName?` constructor options unchanged.
|
|
18
|
+
- Update `apps/cli/src/index.ts` (every `EmbeddedDaemon` instantiation) to pass `workDir` instead of `projectSlug`.
|
|
19
|
+
- Keep handshake / event metadata / diagnostics shapes unchanged: they continue to carry `projectSlug` over the wire.
|
|
20
|
+
- Slug rule:
|
|
21
|
+
1. Resolve input to absolute path. POSIX paths only on day one (Windows pass-through ok, but documented as best-effort: drive letter `:` removed, `\` and `/` both treated as separator).
|
|
22
|
+
2. Strip leading `/`.
|
|
23
|
+
3. Replace every remaining `/` with `-`.
|
|
24
|
+
4. Empty input → throw; `/` (root) → `root` (single segment fallback).
|
|
25
|
+
5. No hashing, no URL-encoding, no truncation.
|
|
26
|
+
|
|
27
|
+
## Not In Scope
|
|
28
|
+
|
|
29
|
+
- Changing `~/.scorel/sessions/` directory layout. Sessions remain flat; per-S0029 "do not move existing files".
|
|
30
|
+
- Daemon-side `list_projects` / `list_sessions` protocol (lives in S0032).
|
|
31
|
+
- Reverse-lookup correctness when `-` appears inside a path segment. Daemon must persist `workDirHint` separately if it ever needs accurate reverse mapping (out of S0031 scope; covered by future spec when `list_projects` is added).
|
|
32
|
+
- WebUI / CLI client-side slug computation. Clients consume slugs from daemon, never compute them.
|
|
33
|
+
- TLS / auth / session creation behavior.
|
|
34
|
+
|
|
35
|
+
## Acceptance Criteria
|
|
36
|
+
|
|
37
|
+
- `packages/daemon/src/projects/slug.ts` exposes `toProjectSlug` with the rule above; unit tests cover:
|
|
38
|
+
- `/Users/chanler/personal/Scorel` → `Users-chanler-personal-Scorel`
|
|
39
|
+
- `/home/alice/repo` → `home-alice-repo`
|
|
40
|
+
- `/` → `root`
|
|
41
|
+
- empty / non-string → throws
|
|
42
|
+
- relative paths get resolved to absolute through `path.resolve`; tests pin behavior with a `cwd` fixture
|
|
43
|
+
- `EmbeddedDaemonOptions.projectSlug` removed; `workDir: string` added and required.
|
|
44
|
+
- All `EmbeddedDaemon` constructions in `apps/cli/src/index.ts` and tests pass `workDir`. No CLI-side slug construction remains.
|
|
45
|
+
- `connect` result, `connected` daemon message, `client_connected` diagnostics all carry the daemon-computed `projectSlug`.
|
|
46
|
+
- `pnpm typecheck && pnpm test` passes.
|
|
47
|
+
- Manual check: start `scorel chat --cwd /tmp/scorel-fixture-foo-bar`; resulting connection reports `projectSlug: "tmp-scorel-fixture-foo-bar"`.
|
|
48
|
+
|
|
49
|
+
## Tests
|
|
50
|
+
|
|
51
|
+
- New unit tests `packages/daemon/src/projects/slug.test.ts` cover the rule cases above plus idempotence (`toProjectSlug(toProjectSlug(p))` is identity for clean inputs that contain no `-`).
|
|
52
|
+
- Update `packages/daemon` integration / embedded daemon tests to construct with `workDir` and assert the emitted `projectSlug` matches the rule.
|
|
53
|
+
- Update `apps/cli` tests where `EmbeddedDaemon` is instantiated.
|
|
54
|
+
- Run `pnpm typecheck && pnpm test`.
|
|
55
|
+
|
|
56
|
+
## Affected Paths
|
|
57
|
+
|
|
58
|
+
- `packages/daemon/src/projects/slug.ts` (new)
|
|
59
|
+
- `packages/daemon/src/projects/slug.test.ts` (new)
|
|
60
|
+
- `packages/daemon/src/index.ts`
|
|
61
|
+
- `packages/daemon/src/index.test.ts` (if present)
|
|
62
|
+
- `apps/cli/src/index.ts`
|
|
63
|
+
- `apps/cli/src/index.test.ts`
|
|
64
|
+
- `docs/spec/daemon.md` (note the slug rule, point at `slug.ts`)
|
|
65
|
+
- `docs/ROADMAP.md` (M5 step entry for S0031)
|
|
66
|
+
|
|
67
|
+
## Risks And Boundaries
|
|
68
|
+
|
|
69
|
+
- Hosts that previously fed exotic `projectSlug` values lose that hook. Acceptable: per S0026 the slug must be daemon-owned; no production caller relies on a non-path slug.
|
|
70
|
+
- `-` collisions (`/pi-mono` vs `/pi/mono`) are accepted; daemon must never reverse a slug to derive identity. Display layer keeps `workDirHint` separately when displaying paths (introduced alongside `list_projects` in S0032, not S0031).
|
|
71
|
+
- Windows: day-one rule is best-effort. If the project ever runs on native Windows, a follow-up spec hardens the rule; not blocking M5.
|
|
72
|
+
- Slug changes if a project gets moved on disk. Acceptable v1: the daemon-side identity tracks current `workDir`; clients invalidate cache on new slug like any other identity change.
|