Commit Graph
5901 Commits
Author SHA1 Message Date
imccyu db3b12a0f7 feat: launch dsh source with native TypeScript 2026-07-28 23:06:27 +08:00
_Kerman 95574a8ec1 Merge remote-tracking branch 'github/master' into xtr/trajectory-inspection-ui 2026-07-28 22:58:46 +08:00
imccyu 25265b312c feat(web): projection-fed permission chip replaces the Access placeholder
PermissionSelect returns as the Access seat's wired occupant: options and
the current value read from the 'permissions' projection through the
standard-kit useProjection (no fetch, no mount timing — the resident
composer's mount-once fetch bug dies with the fetch), key absence renders
nothing (permission-less host, or a Draft with no session), and a pick
submits the '/permission <preset>' command line through the new
ComposerBarInjected.command callback (Session.command = command.execute
admission; the pushed projection frame lands the confirmed value). The
READONLY_OPTIONS placeholder and its local state leave InputBar.

The connection fixture mirrors the host: a permissions unit fold (three
knob events over the fixture preset table), the projections block +
baseline/push frames carry the key, and /permission joins the command
catalog with the same switch-through-knob-events handler shape.
2026-07-28 22:56:43 +08:00
_Kerman 943ef7403e fix(client): resolve trajectory review follow-ups 2026-07-28 22:54:46 +08:00
imccyu b4bc4f382e refactor(session-projection): compact checkpoint row fields to ver/seq/val
The persisted row (sessionId, key, stateVersion, observedSeq, state)
becomes (sessionId, key, ver, seq, val) — the cache medium repeats these
three names for every unit of every session, so the long forms dominated
the JSON payload. ProjectionCheckpointRow and the checkpointRow zod spec
rename together; the domain spec bumps to v3 (cache semantics: the old
medium is discarded, not migrated). The unit-facing declaration keeps
stateVersion — only the persisted/checkpoint row shape changes.
2026-07-28 22:45:35 +08:00
creatixchu 5f4b809f42 Merge remote-tracking branch 'origin/feat/directory-picker' into feat/workspace-directory-browser 2026-07-28 22:37:44 +08:00
creatixchu 7c9d688a82 test(host): cover the native flow's re-arm guard
A fresh injected face while the same request is open re-fires the effect;
the armed guard must not relaunch the chooser (the uncovered branch CI's
per-file gate flagged).
2026-07-28 22:37:19 +08:00
imccyu afaa9ad828 style: satisfy the eslint lane on the plan surfaces
Drop the assertions eslint proved unnecessary (getByRole gains the element
type parameter instead, keeping tsc satisfied), declare the injected
setPlanMode as a function property (the seat face is this-free), and narrow
the fixture's command args without String()'s object stringification arm.
2026-07-28 22:36:35 +08:00
creatixchu 26ab28083e Merge remote-tracking branch 'origin/feat/directory-picker' into feat/workspace-directory-browser
# Conflicts:
#	packages/host/directory-picker-browse/README.i18n.yaml
2026-07-28 22:31:24 +08:00
Turtle 2f3ac10da0 docs: implement experimental and internal package group 2026-07-28 22:30:12 +08:00
creatixchu 95a8e3f949 fix(client,doc): address review — flow-open busy gating, seam on the architecture map, browse gap documented
- While a picking flow is open (native chooser pending, browse dialog up) or
  its pick is being adopted, every other menu action disables: a late outcome
  must not race a concurrent selection or creation (ds-review-bot warning).
- ctx.directoryPicker joins the architecture Capability Services map (both
  languages); neighboring rows condensed to keep the doc inside its ceiling.
- directory-picker-browse documents that its client half lands in the next
  stacked PR: a -browse composition today hides the picking affordance (the
  documented empty-hole default) rather than misbehaving (ds-review-bot
  critical; the dialog itself ships in #821).
2026-07-28 22:29:34 +08:00
imccyu 931dd934e3 style: clear the lint lane — drop redundant assertions and non-thenable awaits
eslint --fix removed the no-unnecessary-type-assertion hits the review
knives introduced; the two await-thenable errors were vi.runAllTicks()
awaits in the cache spec, replaced with advanceTimersByTimeAsync(0) (the
fake-timer-safe microtask drain). Repo-wide eslint, dual-aggregate tsc,
and the focused 100% coverage set all green.
2026-07-28 22:26:12 +08:00
imccyu 019dd7d894 test,chore: clear the static and coverage lanes for the cache stack
Static: the cache package.json files array matches the workspace
constraint shape, the unused dsh-storage-json devDependency is dropped
(tests run on the memory backend), and docs/module-graph.md is
regenerated for the new package edge.

Coverage: two unreachable branches deleted rather than tested —
coldSnapshot's floor-0 tail reuse (a baseSeq-0 restore never throws and
an unrelated record still carries a usable watermark) and flushSoft's
non-mandatory clean-skip (throttle triggers only fire dirty). New tests
close the real gaps: write() on a never-dirty session and the non-JSON
unit-state rejection, plugin disposal clearing armed interval timers,
cachedSnapshot's all-version-mismatched and cwd-identity arms, the
zero-units empty-log cut, the coordinator seek-hook ladder (suffix /
not-found / plain failure / abort-reason relay), and the superseded-
retirement race proving forget()'s exact-entry guard.
2026-07-28 22:26:12 +08:00
imccyu ee79b7a73a docs: regenerate the cordis catalogs for the reshaped cache read faces
cachedSnapshot/coldSnapshot signature and JSDoc changes from the review
fixes flow into the generated service catalog and model-facing api-catalog.
2026-07-28 22:26:11 +08:00
imccyu c46419cf5c fix(apiproxy,client): the list projection column becomes a seedable watermarked block
Review finding (PR #791): the column carried bare values (no seq), so the
client could not seed its value store without risking a stale list block
outranking newer push frames — and nothing consumed the column at all,
leaving cold titles absent after a restart. SessionSummary.projections is
now the same SessionProjectionsBlock as the history tail (values +
asOfSeq; attached rows cut the live registry, cold rows serve the cache's
identity-checked cachedSnapshot whose asOfSeq is the lowest served-row
watermark). SessionManager.refreshList seeds each row's block into the
per-session projection store via per-key apply — partial-baseline
semantics: an absent key never clears, and higher-seq-wins keeps stale
list blocks beneath push frames and tail baselines — so cold titles
surface in the sidebar without opening a session.
2026-07-28 22:26:11 +08:00
imccyu 27198d3091 fix(session-projection-cache): bind records to the log lifecycle; flush before checkpoint
Review finding (PR #791): rows carried only version/watermark/state, so a
recreated session id, or a persistence store replaced under a surviving
cache, could pass every watermark check and seed state folded from an
unrelated log; a checkpoint racing ahead of an eager log flush could
likewise expose values no stored log contains. Records now store the
header identity (createdAt, cwd) they were folded from — reads validate it
against the live header (listing) or the tail's stored header (cold read)
and discard unrelated records whole (domain version 2 discards v1 media by
the pre-release stance). A live checkpoint additionally flushes the
session's buffered events durably before the cache row lands: the cache
can trail the log, never lead it. cachedValues is reshaped into
cachedSnapshot(meta): the identity witness plus the {asOfSeq, values} cut
the list carrier serves.
2026-07-28 22:26:10 +08:00
imccyu 1ef7c9473c fix(session-projection-cache): coldSnapshot honors not-found with zero registered units
Review finding (PR #791): with no projection definitions registered,
restoreFloor() is undefined and the fast path returned a successful empty
snapshot without touching persistence — a nonexistent session 'succeeded',
violating the documented not-found contract in that supported topology.
The no-unit branch now probes readFrom(id, 0): an absent log rejects with
the seam's not-found, a present one dates the empty cut at its stored end.
2026-07-28 22:26:10 +08:00
imccyu 9ae3e1a9ad docs: regenerate catalogs and graphs for the projection-cache seam; classify its types
gen-cordis-catalog/api, config and persistence catalogs, and doc graphs
regenerated over the new sessionProjectionCache service and the registry's
checkpoint faces. Classifications: ProjectionCheckpoint joins the type-link
exemptions (owned by the projection package source), Partial joins the
foundation names, the cache service gets its capability-seam role row, and
the package takes the one-sentence Model Experience contract (host-side
read-model accelerator, no model surface).
2026-07-28 22:26:09 +08:00
imccyu c0eec9d9e2 docs: bilingual counterparts for the projection-cache README and the touched pair records
The base's bilingual gate now covers this branch's new README: add the
Chinese counterpart of the session-projection-cache package README, the
cache row on the group README's Chinese side, and re-record the touched
pairs (group, cache, session-persistence — whose English side gained the
readFrom rows earlier on this branch). verify-translation-pairing: 541
pairs consistent.
2026-07-28 22:26:07 +08:00
imccyu a6e35c27d4 fix(session-projection): checkpoint hands out detached state clones, never live cell references
The watermark cache is the registry's authoritative mutable state; a
checkpoint consumer holding the live reference could corrupt every
subsequent snapshot and frame through it. structuredClone at the read face
(total, by the unit plain-JSON contract) pins the boundary; a mutation test
proves the cache is unreachable through handed-out rows. restore and
viewCheckpoint only touch caller-owned rows — no other leak path.
2026-07-28 22:25:29 +08:00
imccyu 003b22a157 feat(apiproxy): projection column on session.list — cold titles with zero log loads
SessionSummary grows an optional projections column (whole value per key,
same passthrough posture as the history-tail block): attached rows cut the
live registry watermark cache; cold rows view the persisted projection
cache's stored rows via the new registry viewCheckpoint face (version-
matching keys only, zero I/O) — the RFC's motivating scenario, every
session's title across a listing without loading one event log. The column
is fail-soft and absence-coded: no registry, no cache row, or a throwing
read serve the row without the column, never breaking the listing.
2026-07-28 22:25:29 +08:00
imccyu c330c1cd3e feat: dsh-session-projection-cache — durable projection checkpoints and the cold-read ladder
New package on the domain data form: one session_projcache record per
session (key → {stateVersion, observedSeq, state}), landing beside
workspace.json under the shipped json backend. Write policy: two mandatory
points (turn/end + session disposal) with count/interval throttling between
them (both Config fields required — flush cadence is a deployment choice);
every background write is fail-soft (log + stay stale, self-heal on the
next write or cold read). coldSnapshot(id) runs the read ladder — cached
rows + persistence readFrom from the registry's anchored restore floor +
registry restore + fail-soft write-back — detecting crash-repair-shrunk
logs via the one-below anchor and degrading to a single full re-read.
Mounted in apps/cli/cordis.yml (writeEveryEvents 200 / writeIntervalMs
5000).
2026-07-28 22:25:28 +08:00
imccyu fc4b573ff0 feat(session-projection): checkpoint/restore faces for the persisted projection cache
The registry grows the state-level read ladder the persisted cache builds
on: checkpoint(session) snapshots every unit's {stateVersion, observedSeq,
state} row from the watermark cache; restoreFloor(checkpoint) anchors the
tail read one event below the lowest usable watermark (so a shrunk log is
provable); restore(checkpoint, events, baseSeq) refolds each unit from its
usable row (or from init over a full read), rejects rows a tail read cannot
fix (version mismatch / overreach with baseSeq > 0 => re-read from 0), and
returns both the snapshot and the refreshed rows for durable write-back.
ProjectionCheckpointRow/ProjectionCheckpoint are the persisted-row types
minus the record keys.
2026-07-28 22:25:27 +08:00
_Kerman a245c8a011 Merge branch 'master' into xtr/trajectory-inspection-ui 2026-07-28 22:25:25 +08:00
imccyu a79de44c3b feat(session-persistence): readFrom(seq) primitive for watermark tail reads
SessionPersistence grows readFrom(id, fromSeq, signal?): the non-mutating
read-from-seq primitive for checkpoint consumers (the persisted projection
cache folds only the tail past its watermark). Coordinator owns validation,
per-id serialization, and the sequential fallback (loadStored + forward
skip); SQLite implements the optional seek-capable loadStoredFrom hook
(WHERE seq >= ?), JSONL stays sequential by contract. Contract suite covers
suffix exactness, empty-tail, non-mutation, and cancellation; seam README
(both languages) documents the method and the hook.
2026-07-28 22:25:25 +08:00
imccyu 451b7b0446 feat(permission): permissions projection unit and /permission command
The read side becomes the 'permissions' session projection: src/types.ts is
the key declaration's one home (PermissionSelect = whole select: table
options in declaration order plus a current-only 'custom'), served through
./types and the ./client re-export. The unit folds the three whole-value
knob events (permission/preset, sandbox/mode, approval/policy) into a plain
KnobState and views the select over the composition defaults the service
already owns; current() shares the same derive step, so the fold exists
once. The write side becomes the /permission command (the /plan
registration shape): bare invocation reports the current preset and the
table, a preset argument switches through set() immediately — no turn
anchoring (knob events need no enclosure), no dedicated RPC. Both children
activate only when their registry is composed.
2026-07-28 22:23:39 +08:00
creatixchu 4822622cb7 feat(host,client): ship the in-app directory browser as the browse package's client half
directory-picker-browse becomes dual-face: its browser half fills
ui-workspace's two directory-flow holes with the Select Workspace Directory
dialog (figma Harness 813-23126 family — Miller two-column view, breadcrumb
with click-to-edit path zone, nested New-folder dialog), driving the node
half's host.listDirectory/host.createDirectory and owning its locale
namespace (directory-browser, zh default / en). The dialog moves here from
ui-workspace wholesale — the trigger surfaces keep only the flow-hole owner
conversation.

apps/cli flips its one directory-picker row -native -> -browse, swapping the
host backend and the client interaction together; picking now works for
remote deployments out of the box. The keyless workspace-flow snapshot boots
the browse bundle and drives menu -> dialog -> Documents -> project -> Open
against the fixture tree.
2026-07-28 22:22:14 +08:00
_Kerman f942c30f4b fix(client): address trajectory review feedback 2026-07-28 22:16:45 +08:00
_Kerman b10dad0fcb fix(persistence): restore pre-identity sessions 2026-07-28 22:16:43 +08:00
creatixchu 05b5059dda Merge remote-tracking branch 'origin/feat/directory-picker' into feat/workspace-directory-browser
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-28-directory-picker-capability-seam.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-28-directory-picker-capability-seam.md
#	.agents/notes/implemented/architecture/2026-07-28-directory-picker-capability-seam.zh.md
#	apps/cli/cordis.yml
#	apps/cli/package.json
#	docs/module-graph.md
#	packages/client/ui-workspace/README.i18n.yaml
#	packages/client/ui-workspace/README.md
#	packages/client/ui-workspace/README.zh.md
#	packages/client/ui-workspace/src/client/WorkspaceBrowser.tsx
#	packages/client/ui-workspace/src/client/WorkspacePicker.tsx
#	packages/client/ui-workspace/src/client/contract/slots.ts
#	packages/client/ui-workspace/src/client/index.ts
#	packages/client/ui-workspace/tests/apply.spec.ts
#	packages/client/ui-workspace/tests/workspace-browser.spec.tsx
#	packages/client/ui-workspace/tests/workspace-picker.spec.tsx
#	pnpm-lock.yaml
2026-07-28 22:01:26 +08:00
_Kerman 62dd2ab38e Merge remote-tracking branch 'github/master' into xtr/trajectory-inspection-ui
# Conflicts:
#	packages/client/runtime/src/client/sessions/fold-adapter.ts
#	packages/compact/compact-basic/src/summarizer.ts
2026-07-28 21:56:02 +08:00
creatixchu 43a231458b Merge remote-tracking branch 'origin/doc/host-client-group-readmes' into feat/directory-picker 2026-07-28 21:52:22 +08:00
creatixchu 3c8cd3cb9d doc(packages): keep the groups table inside its word ceiling after the master merge
master's session-projection row landed the table at 874 words against the
870 ceiling this PR set; tighten the host/client rows this PR added instead
of raising the ceiling.
2026-07-28 21:52:05 +08:00
Tianyi Cui 6d389d261e docs(policy): describe constructor-seeded inheritance
The implementation no longer stores inherited policy in SessionHeader or resolves a second baseline chain, but the feature, sandbox, and approval notes still described that machinery. Keeping those claims would make the smaller design look incomplete and invite reintroduction of the generic persistence surface.

Rewrite the owning feature note around the actual delegation snapshot: source-tagged policy events follow the optional fork prefix, ordinary last-event-wins folds establish precedence, and persistence captures the constructor seed with the first materialized batch. Condense the alternatives and consequences to the decisions and coverage that remain load-bearing.

Align the sandbox and approval notes plus the subagent-inprocess consumer README with that contract. Update the four Chinese counterparts minimally and re-record each pairing hash so both languages describe the same shipped mechanism.
2026-07-28 21:51:13 +08:00
creatixchu 85ca8be104 feat(host,client): compose directory picking through slots — dual-face -native, no wire advertisement
ui-workspace's two trigger surfaces each declare a single-kind directory-flow
hole (conversation.hero.workspace.directoryFlow / sidebar.workspaces.directoryFlow,
same owner contract) and keep only the trigger and the adoption: the Open-local-
folder entry renders while the surface's hole is occupied, and the occupant
reports one picked path per open through the hole's owner conversation
(open/busy/onPicked/onCancel/onError).

directory-picker-native becomes dual-face: its browser half fills both holes
with a renderless occupant driving host.pickDirectory, so the cordis.yml row
that mounts the backend also composes the client interaction — a mismatch is
impossible and a second flow package fails at client load.

With composition wiring both sides, the host.describe.directoryPicker
advertisement and the client's kind branching lose their last consumer:
the field, WorkspacesService.directoryPickerKind(), the DirectoryPickerKind
wire type, and the picker's per-open describe read are deleted. The connection
fixture now serves a deterministic pickDirectory path so the keyless snapshot
drives the full pick-then-adopt flow. ui-workspace's hand-rolled declaration
deferral is replaced by the deferRegistration helper it duplicated.
2026-07-28 21:51:01 +08:00
imccyu 76796df39b test: close the two coverage tails on the plan surfaces
The plan unit's same-reference gate for a repeated identical /plan selection
(the one uncovered branch in plan-mode/index.ts) gains an explicit case, and
ui-plan's empty node-half apply is exercised the way sibling surface plugins
do (the ui-conversation no-op precedent). Both files read 100% across all
four axes under the CI coverage lane's per-file thresholds.
2026-07-28 21:49:53 +08:00
imccyu 9be6419cec docs: regenerate catalogs and re-pair bilingual READMEs
Regenerate the cordis/config/persistence catalogs and the module graph for
the ui-plan package and the plan projection unit; add the ui-plan Chinese
README and the Model Experience indirect sentence (allowlisted: the control
dispatches /plan lines, dsh-plan-mode owns the model surface); carry the
QuestionComposer Markdown/scroll improvements into the Chinese ui-question
README; re-record the three touched translation pairs.
2026-07-28 21:46:48 +08:00
Tianyi Cui 4cf7603be4 test(snapshot): enforce portable fixture invariants 2026-07-28 21:45:01 +08:00
Tianyi Cui db0b43bf86 persistence: advance schemas after removing policy columns
The simplification deletes sandbox_mode and approval_policy from the parent branch's SQLite layouts. Restoring master's older version numbers would violate the monotonic schema contract and could make a database created by the parent look current under a different layout.

Advance durable session persistence from schema 11 to 12 and the disposable session-query index from 6 to 7. The former rejects the incompatible parent layout; the latter resets its derived tables through the existing version-mismatch path.

JSONL shares SESSION_FORMAT_VERSION 0 during pre-release, so explicitly reject the retired sandboxMode and approvalPolicy header fields instead of silently dropping the only inherited policy facts from a parent-produced child log. New logs carry those facts as ordinary seeded events.

Focused JSONL, SQLite persistence, and SQLite query suites cover all affected source lines and branches.
2026-07-28 21:40:51 +08:00
imccyu 6e950940ee feat(web): ui-goal package — GoalBar over the goal session projection
New client plugin package. The GoalBar component migrates verbatim from the
original PR (phase labels, inline edit form, resume-when-paused, pending
lockout, inline errors); its data path is rebuilt for the projection model:

- GoalDock adapter reads useProjection('goal') from the standard kit — no
  controller, no store, no refresh chain, no event listener (the original
  PR's Session goal fields, write-revision fence, and coalesced refetch all
  dissolve into the value store's seq rule).
- The inject face carries only the three mutation verbs; each reads the CAS
  ref from the session's current projected value at call time and maps the
  settled RPC result inline (callbacks from inject, live state from
  useProjection).
- Seats at conversation.input.dock order 1 (the slot contract names GoalBar
  as a resident of this strip), below TodoPanel/QueueDock, tucked against
  the composer; hero phase renders nothing for free.
- IconSparkle16 is package-local (sole consumer) — ui-primitives keeps only
  the shared action icons.
- goalbar.spec migrates with GoalSnapshot props (activation is process-local
  and absent from the projection; the strip renders durable phase only).
2026-07-28 21:40:49 +08:00
Turtle 1ac946f747 feat(context): add tmux-context plugin injecting the agent's tmux location
Add @deepseek-ai/dsh-tmux-context: an opt-in per-turn context plugin that
reads which tmux session/window/pane this agent process runs in (plus the
window layout tree) via the ctx.bash seam, and injects it as one durable,
source-attributed user/message when the location changes.

- Pull on the first step of each turn; no tmux hook or background process.
- Detect a real pane by tty, not $TMUX_PANE alone: a terminal launched from
  a tmux shell inherits $TMUX/$TMUX_PANE from that ancestor, so the command
  also matches the pane's #{pane_tty} against this process's controlling
  terminal and emits fields only on a match.
- No-op outside a real pane, without a bash executor, or on a malformed
  reading.
- Own location and layout only: no pane sizes, no sibling-pane scraping.
- Unit tests at 100% per-file coverage, plus a keyless Loader e2e with a
  mock bash provider so it replays without tmux.
- Agent Note: 2026-07-27-tmux-location-context.
2026-07-28 21:40:13 +08:00
imccyu 1c76286472 feat(host): approval pending registry on the api gateway
The approval/request waterfall answerer fills the slot the gateway reserved
('registry absent in this minimal version'): an ask through ctx.approval
becomes an answerable approval/requested mux frame with a stable rpcId,
mux open replays still-pending frames (refresh recovery), respond routes
approvals first by the echoed rpcId and cross-checks the payload's audit
correlation, the ask's abort signal withdraws with a broadcast cancelled,
and approval/resolved settles every subscriber. The answerer pairs each ask
with its approval/asked audit event by scanning for the newest undecided,
unclaimed id (callId-matched when the ask names a call); asks that bypassed
the audit path delegate to the fail-closed default.

The child activates only when ctx.approval is composed; the 275-line spec
carries over verbatim at the gateway's new home.
2026-07-28 21:38:40 +08:00
imccyu c6b552e817 refactor(web): drop the permission RPC pair and turn-anchoring machinery
The session.permissions/setPermission unary pair, the PermissionOption wire
DTO, the client Session wrappers, and the fixture/fake mirrors all leave the
wire: the read side moves to the 'permissions' session projection and the
write side moves to the /permission command in follow-up commits, so the
web protocol gains no permission methods at all.

The pendingSwitches + prompt-submit flush + hasOpenTurn move also goes.
Knob events no longer need turn enclosure: the persistence scanner keeps
standalone events after the last turn/end as part of the preserved prefix
(remove-synthetic-log-only-turns), none of the three knob invariants demand
an open turn, and the setters append bare events. An idle switch commits
immediately; hasOpenTurn stays a user-approval private fold (its audit pair
is the one contract that still requires enclosure).

The old PermissionSelect chip and its mount-time fetch die with the RPCs
(the resident composer broke the mount-once assumption); the projection-fed
replacement lands with the Access seat swap.
2026-07-28 21:35:26 +08:00
Tianyi Cui 39ff4866ac Merge retargeted parent into policy inheritance simplification 2026-07-28 21:35:23 +08:00
Tianyi Cui 5d147735ac Merge latest master into subagent policy inheritance 2026-07-28 21:33:40 +08:00
Tianyi Cui 84d0d92cfb test(snapshot): normalize temporary workspace paths 2026-07-28 21:32:49 +08:00
imccyu c991f76cef feat(goal): split the pure type outlet and register the 'goal' projection unit
dsh-goal/types becomes the client-safe pure outlet (tool-todo dual-outlet
shape): GoalId/GoalRef/GoalPhase/GoalBlockReason/GoalSnapshot, the new
GoalProjection payload, and the SessionProjectionMap 'goal' key merge — zero
host imports. Host-coupled vocabulary (GoalView/activation, change metas,
message source, folds, GoalError codes, the scoped goal/changed event) moves
to src/domain.ts, re-exported from the package root. ./client re-exports the
outlet for client aggregates.

GoalService registers the projection unit under ctx.inject(['sessionProjections']):
applyGoalProjection is a projection-grade last-wins fold — plain-JSON state,
same-reference return on non-goal or malformed events (a throwing apply
would tear down the registry drive; strict validation stays with the write
side and foldGoal). Activation is process-local and deliberately absent from
the projection value.
2026-07-28 21:31:30 +08:00
Tianyi Cui cfceb8452b subagent: seed inherited policy events at creation
The parent implementation introduced sandboxMode and approvalPolicy as generic SessionHeader fields, then propagated those fields through both persistence backends, session-query indexes, collision checks, policy-specific seed-boundary folds, catalogs, and a broad test matrix. That storage plane is unnecessary: Session already accepts a validated constructor seed, and persistence captures that seed when the session is announced before committing its first batch.

Capture each parent override synchronously at delegation, append source-tagged sandbox/mode and approval/policy records after the optional fork prefix, and create the child with that combined seed. Keeping header.seedLength at the original fork-prefix length preserves lineage while ordinary last-event-wins folds make the inherited records outrank stale parent history and remain subordinate to later child switches. Unswitched parents still stamp nothing, so children continue to follow deployment defaults.

Remove the generic header fields and every persistence/query/schema branch built around them. Collapse the inheritance suite from ten leaking scenarios to four owned-context cases covering real filesystem confinement, stale fork precedence, delegation-time capture, and the no-override path. The assembled headless snapshot now asserts the persisted inheritance event directly.

This keeps the security behavior while restoring policy ownership to the existing event log and deleting the speculative durability machinery that the original tests did not exercise.
2026-07-28 21:31:17 +08:00
creatixchu 51402ac7af refactor(util): extract the shared no-shell native-command runner to dsh-native-command
master's toolcall-open extracted runNativeCommand inside apiproxy for the
openPath opener while the picker seam had moved the native chooser (its other
consumer) into directory-picker-native; after the merge the two packages each
carried a verbatim copy. The runner now lives in packages/util/native-command
(zero-dependency library, per the util-group contract) and both native
integrations depend on it.
2026-07-28 21:25:19 +08:00
creatixchu a94df18bcf Merge remote-tracking branch 'origin/doc/host-client-group-readmes' into feat/directory-picker
# Conflicts:
#	packages/client/connection/src/client/fixture.ts
#	packages/client/connection/tests/fake-api.ts
#	packages/client/runtime/src/client/workspaces/service.ts
#	packages/client/runtime/tests/fake-api.ts
#	packages/client/ui-workspace/src/client/WorkspaceBrowser.tsx
#	packages/client/ui-workspace/src/client/WorkspacePicker.tsx
#	packages/client/ui-workspace/tests/workspace-picker.spec.tsx
#	packages/host/apiproxy/README.i18n.yaml
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/host.schema.ts
#	packages/host/apiproxy/src/api/host.ts
#	packages/host/apiproxy/src/api/rpc-map.ts
#	packages/host/apiproxy/src/fetch/client.ts
#	packages/host/apiproxy/src/fetch/handler.ts
#	packages/host/apiproxy/tests/api-proxy-workspace.spec.ts
#	packages/host/apiproxy/tests/client-handler.spec.ts
#	packages/host/apiproxy/tests/fetch-carrier.spec.ts
2026-07-28 21:21:21 +08:00