dsh-completion-guard 0.2.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.
@@ -0,0 +1,42 @@
1
+ # Architecture
2
+
3
+ Context Guard separates DSH-owned execution from Guard-owned certification.
4
+
5
+ ## Responsibility boundary
6
+
7
+ | Module | Owns |
8
+ | --- | --- |
9
+ | DSH Goal | Persisted objective, automatic goal rounds, pause/resume/block/complete |
10
+ | DSH Todo | Lightweight current plan display |
11
+ | DSH Compaction | Model-visible history reduction without corrupting tool-call structure |
12
+ | Context Guard | Per-item task contract, revisions, evidence binding, and completion certificate |
13
+
14
+ Context Guard does not own Goal, Todo, Compaction, or continuation. It intervenes when completion is claimed without a valid certificate.
15
+
16
+ ## Durable state model
17
+
18
+ The effective plugin configuration and the DSH Session append-only log are the inputs to the rebuildable Guard projection. Context Guard **appends no custom session event types**: the persisted event vocabulary is harness-owned and the current persistence layer refuses unknown event types. The `activation` configuration supplies the initial enablement state, while all later session state is derived from the natively persisted events DSH already writes:
19
+
20
+ - effective plugin configuration — initial enablement (`opt-in` starts disabled; `always` starts enabled before log replay);
21
+ - `command/run` — later enablement (`/context-guard on|off|clear`) and epoch transitions;
22
+ - `user/message` — captured contract clauses;
23
+ - `tool/call` + `tool/result` — bounded evidence and completion-certificate attempts.
24
+
25
+ The in-memory `GuardProjection` is a rebuildable cache: `deriveProjection` applies the effective activation configuration, replays the native log deterministically, recomputes every contract, evidence, and certificate, and flags `corrupt` when a recorded certificate no longer re-derives from the evidence in the log. The projection and its evidence are session-scoped: a new DSH session starts a new projection and cannot import, look up, or certify evidence IDs from another session. A completed workflow that needs a certificate must therefore produce its evidence and call `context_guard_checkpoint` in the same session. Under `always`, replay begins enabled; changing an existing profile from `opt-in` to `always` can therefore bring earlier persisted user messages into the derived contract. A recorded `/context-guard off` disables capture from that point until a later `on`. A recorded `/context-guard clear` supersedes every pending requirement and acceptance under a `CLEAR:<revision>` sentinel (prohibitions are retained) and bumps the contract revision, so a fresh empty-binding checkpoint can certify while the guard stays enabled. Captured contracts always carry a concrete subject/surface, so no unrelated evidence can close a requirement.
26
+
27
+ ## Synchronization
28
+
29
+ The runtime rebuilds the projection from the log before each step. Before evidence is produced, the runtime awaits `ctx.sessions.flush(session)`; if no durability listener participated, evidence is demoted to `unknown`, which fails closed.
30
+
31
+ Evidence is produced only from persisted `tool/call` + `tool/result` pairs. Guard never inserts context between a Code Mode sub-call and its durable result.
32
+
33
+ ## Domain pipeline
34
+
35
+ 1. `classifyUserInteraction` drops session-layer utterances before capture: bare progression/acknowledgement phrases (`继续`, `continue`), meta questions (`这个收尾具体要做什么`, `是不是bug`), and meta comments/objections. The classifier fails closed — an artifact path, an explicit method, or a non-negated operation verb always keeps the message (or the individual clause inside a mixed message) a captured instruction.
36
+ 2. `classifyClause` / `captureClause` classify the remaining direct human message into requirement, acceptance, or prohibition.
37
+ 3. `evidenceFromPersistedToolResult` maps a persisted tool result to bounded evidence with capability, subject, and surface, using the tool's structured `meta` and parsed arguments.
38
+ 4. `evidenceMatchesItem` requires a verifying capability (filesystem-read, filesystem-edit, web-fetch, deterministic-check) and a matching subject/surface before an enforced item can close.
39
+ 5. `certifyCheckpoint` binds evidence to items and emits a certificate bound to epoch, contract revision, and digests.
40
+ 6. `goalCompletionDenial` rejects `update_goal(action=complete)` without a current certificate. The gate has no bypass; the documented remediation routes are `/context-guard off` (only after the user confirms the work is done), `/context-guard clear` (supersedes pending requirements/acceptances so a fresh checkpoint can certify), or a truthful `update_goal(action=blocked)`.
41
+ 7. `decideTurnStopping` steers a turn that claims whole-task completion without a certificate, capped per turn.
42
+ 8. `renderRecoveryPacket` re-injects open requirements after compaction, resume, enable, rejection, or integrity loss. Injection is content-deduplicated: a re-armed packet with unchanged content is injected once, while resume, compaction, an enablement transition, new evidence, or a new contract revision change or forget the digest and always re-remind.
@@ -0,0 +1,169 @@
1
+ # Compatibility
2
+
3
+ The current development target is pinned, not a floating claim.
4
+
5
+ ## Target
6
+
7
+ - DeepSeek Harness: `0.1.1-rc.2`
8
+ - Cordis: `4.0.1`
9
+ - Node: `>= 22`
10
+ - pnpm: `>= 11`
11
+
12
+ The DSH host is a developer preview that declares breaking changes. A source build does not establish native acceptance; each profile and platform is verified separately.
13
+
14
+ ## Loader contract
15
+
16
+ The package exposes a named `apply(ctx)` function and a named `inject` array (`['sessions', 'commands']`) with no default export. Its `dsh.bundle.patch` points at `cordis.patch.yml`, which inserts the `context-guard` bundle row.
17
+
18
+ The plugin accepts an `activation` configuration value of `opt-in` or `always`. The default is `opt-in`; `always` initializes the projection as enabled before the persisted session log is replayed. Invalid values fail during plugin configuration instead of silently falling back. A DSH profile can select `always` with an ID-targeted `config` override in its `cordis.patch.yml`; see the README quick start for the complete example and the replay implications for existing sessions.
19
+
20
+ ## Peer dependencies
21
+
22
+ Runtime packages are host-provided and declared as peer dependencies: `@deepseek-ai/cordis`, `@deepseek-ai/dsh-agent`, `@deepseek-ai/dsh-commands`, `@deepseek-ai/dsh-llm`, `@deepseek-ai/dsh-session`, `@deepseek-ai/dsh-tools`.
23
+
24
+ ## Terminal outcome contract
25
+
26
+ The pinned DSH `bash` and `pwsh` renderers append terminal markers for sandbox
27
+ denial, timeout, signal termination, and non-zero exit. A completed foreground
28
+ result with none of those markers is the renderer's representation of a clean
29
+ exit; it does not append `[exit code: 0]`. Version 0.1.1 therefore accepts an
30
+ unmarked completed foreground `bash` result as successful evidence, matching the
31
+ existing `pwsh` behavior.
32
+
33
+ This does not make arbitrary shell text authoritative. A result-level error or
34
+ negative terminal marker wins over output text; background commands remain
35
+ unknown; and the generic `shell` alias remains unknown without an explicit exit
36
+ marker because no pinned host renderer contract has been verified for it.
37
+ Outcome classification also remains separate from command certification:
38
+ unsupported or malformed syntax produces no executable or operation facts and
39
+ no certifying subject/capability combination, so it cannot close a contract even
40
+ when the host execution itself succeeded.
41
+
42
+ ## Verified surfaces
43
+
44
+ - `dsh --profile web --dump-config` and `--profile headless --dump-config` both include `context-guard`.
45
+ - A real headless boot loads the plugin (apply, `ctx.sessions` access, and listener registration succeed) and only stops at missing provider credentials.
46
+
47
+ The slash command renders in the Web command directory and its on/off/clear/status/diagnose subcommands produce the expected `command/run`/`command/done`. Version 0.2.1 has 105 domain/core tests and 138 tests overall. The 0.2.0 macOS live acceptance includes a real Web `pnpm test` run with 5 test files and 124 tests passed, followed by a certified checkpoint at contract revision 4; the complete evidence boundary and known gaps are recorded in `LOCAL_ACCEPTANCE.md`. Evidence and certificates are session-scoped: a later DSH session cannot import or certify evidence IDs from an earlier session, so a workflow requiring a certificate must produce its evidence and checkpoint in one session. The published 0.1.0/0.1.1 releases retain separate historical public-package and native-platform evidence. The fail-closed invariants below are asserted as regressions.
48
+
49
+ ## Session-layer capture filter and goal completion (v0.2.1)
50
+
51
+ Not every direct user message becomes a contract item. Informational reports
52
+ (receipts, pasted summaries) were already excluded; v0.2.1 additionally drops
53
+ session-layer utterances: bare progression/acknowledgement phrases (`继续`,
54
+ `好的`, `continue`), meta questions (`这个收尾具体要做什么`, `是不是bug`),
55
+ and meta comments or objections without a task feature. The filter also runs
56
+ per clause, so a conversational opener inside an otherwise actionable message
57
+ (`好的。请修改 src/a.ts`) no longer adds a phantom scope requirement. The
58
+ classifier fails closed: an artifact path, an explicit method, or a
59
+ non-negated operation verb always keeps the message captured, and uncertain
60
+ phrasing stays a captured requirement. Old sessions replay unchanged — a
61
+ contract already polluted by such messages remains historical state and is
62
+ remediated explicitly (below), not by re-derivation.
63
+
64
+ `update_goal(action=complete)` stays denied while the guard is enabled without
65
+ a current completion certificate. The remediation routes are explicit:
66
+ `/context-guard off` disables gating (use only after the user confirms the
67
+ work is actually done), `/context-guard clear` supersedes pending
68
+ requirements/acceptances under a `CLEAR:<revision>` sentinel (prohibitions are
69
+ retained) so an empty-binding checkpoint can certify while the guard stays
70
+ enabled, and `update_goal(action=blocked)` records the blocker truthfully.
71
+ Recovery packet injection is content-deduplicated: an unchanged packet is
72
+ injected once per re-arm, while resume, compaction, an enablement transition,
73
+ new evidence, or a new contract revision always re-remind.
74
+
75
+ ## Certifiable command subset
76
+
77
+ Context Guard v0.2 is **not** a general Bash or PowerShell static analyzer. Only
78
+ the small, auditable grammar below can produce `executable`, `operation` and
79
+ `subject`; any other command parses as `unsupported` (unterminated quotes parse
80
+ as `malformed`) with EMPTY executables and operations, so unrecognized syntax
81
+ can never certify an operation. False negatives are preferred over false
82
+ positives: an uncertain command keeps its item incomplete.
83
+
84
+ The enumerations that define this surface (tools, executables, clause verbs)
85
+ are declared once in `src/domain/manifest.ts`; the parsers and the contract
86
+ capture read from that single data source, which test-time validation keeps
87
+ non-empty and duplicate-free with the documented verb priority order. The
88
+ manifest ships with the package and is not runtime-writable: widening the
89
+ surface lowers the evidence bar, so it changes only through a release.
90
+
91
+ ### Supported POSIX shell (single foreground simple command)
92
+
93
+ - `printf … > literal-path`
94
+ - `echo … > literal-path`
95
+ - `touch literal-path`
96
+ - read-only inspection tools (`cat`, `grep`, `rg`, `head`, `tail`, `wc`,
97
+ `sed` without in-place flags): every pathish argument counts as a read effect
98
+ (v0.2)
99
+ - one whitelisted executable run directly, e.g. `node script.js`,
100
+ `python tool.py`, `pnpm test`, `git pull`,
101
+ `dsh plugin --profile web add dsh-dream-skin@0.3.1`
102
+ - a leading simple environment-assignment prefix, e.g. `CI=1 pnpm test`
103
+ (wrappers such as `env`, `nohup`, `time`, `command` are not supported)
104
+ - diagnostic stream duplication (`2>&1`, `1>&2`, `N>&M`) in any position
105
+ (v0.2); it is a pure fd copy with no filesystem effect
106
+
107
+ Literal paths only: no variables, globs, `~` expansion or command substitution.
108
+
109
+ ### Unsupported → fail-closed (whole command, no partial results)
110
+
111
+ - unquoted LF/CRLF command boundaries, `;`, `&&`, `||`, pipelines (`|`), background (`&`), parentheses/subshells
112
+ - `$(…)`, backtick command substitution, heredoc/here-string (`<<`, `<<<`)
113
+ - unterminated quotes, dynamic `eval`/`source`/`.`-sourcing
114
+ - non-literal (variable/glob) redirect targets or arguments
115
+ - `>>`, `<`, file-target fd redirects (`2>`, `2>>`) and all other redirections
116
+ beyond a single `>` or an `N>&M` stream copy
117
+ - in-place `sed -i`/`sed --in-place` editing
118
+ - executables outside the v0.2 whitelist
119
+
120
+ ### Supported PowerShell (single directly invoked command)
121
+
122
+ - the v0.1 cmdlet set: `Set-Content`, `Add-Content`, `New-Item`, `Out-File`,
123
+ `Get-Content` with the exact documented parameters
124
+ - v0.2: a whitelisted external executable (`git`, `pnpm`, `npm`, `node`,
125
+ `python`, `tsc`, `vitest`, `pytest`, … – the same run-executable set as the
126
+ POSIX side) invoked directly with all-literal arguments, e.g.
127
+ `git push origin main`, `pnpm add pkg@1.0.0`; its run effect carries the
128
+ first pathish argument
129
+ - v0.2: unquoted `N>&M` stream duplication is stripped everywhere (a quoted
130
+ `"2>&1"` remains an ordinary value)
131
+
132
+ Requirements: the command must be unquoted at the command position; the path
133
+ must come from the explicit named path parameter (cmdlets) or be a literal
134
+ argument (external executables); a quoted path is one token (spaces allowed);
135
+ permitted value parameters (`-Value`, `-Encoding`, and `-ItemType`
136
+ where listed above) never contribute subjects;
137
+ `-WhatIf` and `-Confirm` are unsupported because they can avoid or defer the
138
+ claimed effect; positional paths, variables, expressions, `Join-Path`,
139
+ subexpressions, pipelines, `;`, script blocks, `&`, dot sourcing, `Copy-Item`,
140
+ `Move-Item`, `Rename-Item` and `.NET WriteAllText` are unsupported and fail the
141
+ WHOLE command.
142
+
143
+ ### Subject resolution (v0.2)
144
+
145
+ Evidence artifact subjects are resolved against the call's `workdir`; when the
146
+ shell tool carries none (the macOS persistent bash/pwsh tools expose only
147
+ `command`), the session scope cwd is used as the default, so relative paths and
148
+ scope-run attribution match the contract subject derived from the same cwd. A
149
+ pathless `run` operation of a whitelisted executable is attributed to that cwd,
150
+ which is what closes a scope `run` contract; builtins (`echo`, `cat`, …) never
151
+ become a subject-carrying run.
152
+
153
+ ### Binding invariants
154
+
155
+ - `run`: the successful method evidence (method + operation + subject) alone
156
+ closes the contract; no extra read or unrelated deterministic-check is needed.
157
+ - `create`/`write`/`modify`: require one successful effect evidence matching
158
+ operation and subject, plus an independent successful state-verification
159
+ evidence on the same subject. When an explicit method is present, that method
160
+ identity must be carried by the effect evidence itself; without an explicit
161
+ method, any compatible effect evidence may satisfy the effect facet.
162
+ - `read`: a successful read evidence matching method, read operation and
163
+ subject satisfies the method side and the object side at once.
164
+ - `verify`: one evidence must simultaneously provide success, an explicit
165
+ read/verify/deterministic-check capability, the canonical subject and surface,
166
+ and any required method identity; separate method and verification evidence
167
+ cannot be spliced together.
168
+ - an explicit method whose operation cannot be parsed fails closed.
169
+ - prohibitions keep their existing semantics.
@@ -0,0 +1,337 @@
1
+ # Local Acceptance
2
+
3
+ Deterministic checks and an isolated DSH_HOME composition smoke. These establish source correctness and load correctness, not full runtime behavior.
4
+
5
+ ## macOS v0.2.0 acceptance (2026-08-28)
6
+
7
+ Verified source commit: `c107cd8ead97988f6a71cab8182edb16b23b086b`, on `main`, with a clean worktree and `main == origin/main` at the release preflight. Node v25.1.0 and pnpm 11.22.0 were used on macOS.
8
+
9
+ Repository gates passed before publication:
10
+
11
+ - `pnpm install --frozen-lockfile` -> 0.
12
+ - `pnpm test` -> 0; 5 test files, 124 tests passed.
13
+ - `pnpm run typecheck` -> 0.
14
+ - `pnpm run lint` -> 0 errors / 0 warnings.
15
+ - `pnpm run build` -> 0.
16
+ - `pnpm run pack:check` -> 0.
17
+ - `validateManifest()` returned no errors. The semantic checks covered informational receipt filtering, deterministic-check classification, `2>&1` support, and rejection of compound `&&` syntax.
18
+
19
+ Live Web acceptance after installing `dsh-context-guard@0.2.0` into the managed `web` profile and restarting DSH:
20
+
21
+ - The live profile reads installed version `0.2.0`; `dsh --profile web --dump-config` includes the `context-guard` bundle.
22
+ - A real Web session in this repository executed one foreground Bash `pnpm test` call. The persisted result reported 5 test files and 124 tests passed.
23
+ - The next checkpoint bound the successful evidence (`E0001`) to the two current session items. The checkpoint returned `status: certified`, `contract_revision: 4`, with `rejected_bindings: []` and `open_items: []`.
24
+
25
+ Publication and consumer readback:
26
+
27
+ - `npm view dsh-context-guard dist-tags.latest` -> `0.2.0`.
28
+ - npm `gitHead` for `0.2.0` -> `c107cd8ead97988f6a71cab8182edb16b23b086b`.
29
+ - The official `dsh-context-guard-0.2.0.tgz` unpacks to version `0.2.0`; all six packaged `dist/` files are byte-identical to the local build by md5. The local-only `dist/.DS_Store` is not part of the npm package and is excluded from this comparison.
30
+ - Annotated tag `v0.2.0` was pushed. Remote readback returned tag object `dc1b13e00b2e1adadacb2c8de0a533ec8f51ac22` peeling to commit `c107cd8ead97988f6a71cab8182edb16b23b086b`.
31
+ - codex-sync update discovery reported exactly `dsh-context-guard 0.1.2 -> 0.2.0`; the dry run planned one update, apply succeeded, the installed profile package reads `0.2.0`, the bundle contains `context-guard`, and the follow-up dry run returned `No DSH plugin changes needed`.
32
+
33
+ Evidence boundaries:
34
+
35
+ - The live 0.2.0 checkpoint certifies the real `pnpm test` workflow and its bound session items. It does not certify every release requirement in the recovered handoff contract.
36
+ - The rejected compound-command case with an actionable `rejected_bindings[].hint`, and informational receipt filtering, are covered by the 0.2.0 semantic/regression checks and earlier real-session evidence; they were not re-created as additional live Web calls in this acceptance run.
37
+ - Windows native acceptance remains the documented 0.1.x bounded PowerShell result; no Windows 0.2.0 run is claimed here.
38
+
39
+ ## macOS v0.2.1 acceptance (2026-08-28)
40
+
41
+ Verified source commit: `ba8f05dc6a922b8a12f4dc211d9a888d2ece526a` (= annotated tag
42
+ `v0.2.1`, tag object `5bccac9dd77549a929137befd808dc1701d77093`). Repository gates
43
+ and package verification ran on a clean worktree at that commit; the npm
44
+ publication ran from `806aa863234a064b5c42391fa1288998abfc846e` as recorded
45
+ below. Node v25.1.0, pnpm 11.22.0, npm 11.17.0 on macOS 26.6.2 (arm64). The
46
+ pre-publish artifact `dsh-context-guard-0.2.1.tgz` had SHA-256
47
+ `ea2b6a0bc1db82150af9d88494b6c9d2a1e0243d33ed21df48d3c23d7c52a895`.
48
+
49
+ Repository gates passed at `ba8f05d` (each exit code recorded at run time; the
50
+ untracked `docs/PROBLEM_REPORT_v0.2.1.md` was moved out of the worktree for the
51
+ pack steps and restored afterwards):
52
+
53
+ - `pnpm install --frozen-lockfile` -> 0.
54
+ - `pnpm run typecheck` -> 0.
55
+ - `pnpm test` -> 0; 6 test files, 138 tests passed (`tests/domain/conversation.test.ts`
56
+ is the new v0.2.1 conversational-capture matrix with 7 tests).
57
+ - `pnpm run lint` -> 0; 0 warnings / 0 errors (26 files, 96 rules).
58
+ - `pnpm run build` -> 0; 6 files, 151.33 kB total.
59
+ - `pnpm run pack:check` -> 0; `dsh-context-guard-0.2.1.tgz`, 19 files, and the
60
+ untracked problem report is not part of the package.
61
+
62
+ Installed-state verification: the tgz above was added to the real `web` profile
63
+ (`dsh plugin --profile web add file:...`) and to the `headless` profile; both
64
+ installed packages read `0.2.1`, `dsh --profile web --dump-config` still composes
65
+ the `context-guard` bundle, and DSH web was restarted after the install (new
66
+ process PID 97136 started 09:55, listening on 127.0.0.1:3080, after the 09:53
67
+ install) so the live instance loads 0.2.1.
68
+
69
+ ### Live multi-turn Web session (one guarded session, all steps)
70
+
71
+ A brand-new guarded session in the real Web UI (workspace `dsh-context-guard`,
72
+ DeepSeek-V4-Flash-Vision-Exp, workspace-write), driven through a dedicated
73
+ Chrome instance over the Chrome DevTools Protocol — the same browser-automation
74
+ lane this DSH install uses for its own browser skill (`chrome-devtools-mcp`).
75
+ User messages were submitted with CDP-trusted pointer events on the composer's
76
+ send control; every acceptance observable below was double-checked against the
77
+ server-side session log
78
+ (`~/.dsh/sessions/…/session-6dcd1274-d4bb-430f-a07c-bcddda8a3bca/session.jsonl.zstd`).
79
+ The profile's managed patch layer already sets `context-guard` to
80
+ `activation: always`, so the session was guarded from its first event.
81
+
82
+ 1. Baseline: `/context-guard status` -> `{"enabled":true,"epoch":0,
83
+ "contract_revision":0,"pending":0,"passed":0,"evidence":0,
84
+ "integrity":"valid"}`.
85
+ 2. Change 1, clarifying message: `这个收尾具体要做什么` was sent; the model
86
+ answered (and explored the repository, producing 32 evidence entries). The
87
+ next `/context-guard status` returned `pending:0`, `contract_revision:0` —
88
+ the clarifying question was not captured as a contract item.
89
+ 3. Change 1, progression phrase: `继续` was sent; the model continued its
90
+ analysis. `/context-guard status` again returned `pending:0` (evidence 37) —
91
+ the progression phrase was not captured.
92
+ 4. Evidence production and certified checkpoint: the single-clause task
93
+ "在本仓库前台单一命令运行 pnpm test 且不得使用管道分号或重定向,然后用本次运行产生
94
+ 的证据调用 context_guard_checkpoint 绑定全部开放项完成认证" was captured as
95
+ `R001` (checkpoint with empty bindings returned `incomplete`,
96
+ `open_items:["R001"]`); the model executed a clean foreground `pnpm test`
97
+ (single command, no pipes or redirects; 6 files / 138 tests passed), which
98
+ produced durable evidence `E0038` (bash, scope, outcome success, shell +
99
+ deterministic-check), and the binding `{"item_id":"R001",
100
+ "evidence_ids":["E0038"]}` returned `{"status":"certified",
101
+ "contract_revision":1,"open_items":[],"rejected_bindings":[]}`. Both raw
102
+ tool results are persisted in the session log.
103
+ 5. Pre-clear goal-gate denial (fail-closed evidence): a verification message
104
+ was itself captured as `R002` (revision 1 -> 2); the model's empty-binding
105
+ checkpoint returned `incomplete, open_items:["R002"]`, and
106
+ `update_goal(action=complete)` was denied with "Context Guard requires a
107
+ current completion certificate before Goal completion." — the gate denies
108
+ before checking whether a goal exists (`get_goal` returned `{"goal":null}`).
109
+ 6. Clear remediation: `/context-guard clear` returned "Context Guard contract
110
+ cleared: 1 requirement/acceptance item(s) superseded; 0 pending remain
111
+ (prohibitions retained)." A follow-up verification (phrased as a question,
112
+ which the conversational filter does not capture) re-ran both tools:
113
+ the empty-binding checkpoint returned `{"status":"certified",
114
+ "contract_revision":8,"open_items":[],"rejected_bindings":[]}`, and
115
+ `update_goal(action=complete)` was no longer blocked by the guard — it
116
+ reached the goal tool's own argument validation (`goal_id` placeholder
117
+ rejected) because this session has no active goal. The final
118
+ `/context-guard status` read `{"enabled":true,"epoch":0,
119
+ "contract_revision":8,"pending":0,"passed":1,"evidence":43,
120
+ "integrity":"valid"}` — the guard stayed enabled across the clear.
121
+
122
+ Headless cross-checks (fresh guarded session per run, `--patch` overlay with
123
+ `activation: always`, real model turns; server logs under `~/.dsh/sessions/`):
124
+
125
+ - Compound-command rejection: `pnpm test 2>&1 | tee …; echo …` produced
126
+ scope-only evidence and the binding attempt was rejected with `incomplete`
127
+ and per-item hints ("needs a scope run effect: a whitelisted executable …
128
+ without pipes, `;` or `&&`"). No binding rule was changed for it.
129
+ - Recovery-injection dedup: across three headless sessions, six
130
+ `context_guard_checkpoint` rejections (nonexistent evidence `E9999`, both
131
+ missing-item and evidence-mismatch reasons) produced exactly one
132
+ "Open task requirements (recovered after compaction or resume):" plugin
133
+ notice per session — no duplicate recovery packet was ever injected live.
134
+ The step-separated identical-rejection scenario is covered deterministically
135
+ by `tests/runtime.test.ts` ("recovery injection dedup (v0.2.1)").
136
+
137
+ Evidence boundaries:
138
+
139
+ - The live Web session covers the work order's steps 1-5 (status baseline,
140
+ clarifying message, progression phrase, supported-task evidence with a
141
+ certified checkpoint, and clear -> empty-binding certified -> goal-gate
142
+ release with the guard still enabled). The `update_goal` leg ends at the
143
+ goal tool's own argument validation because the acceptance session had no
144
+ active goal; the gate's release is nonetheless demonstrated, and the denial
145
+ path was captured live pre-clear.
146
+ - Evidence remains session-scoped by design; cross-session evidence IDs are
147
+ rejected and no cross-session import exists. Windows native behavior is not
148
+ re-claimed here; the 0.2.0 Windows records stand.
149
+
150
+ ### Publication and consumer readback
151
+
152
+ The npm publication was authorized and executed from
153
+ `806aa863234a064b5c42391fa1288998abfc846e` ("docs: update READMEs to v0.2.1"),
154
+ a post-release README follow-up commit that was already on local `main` (not
155
+ pushed at the time) when the release was approved. Per the maintainer's
156
+ explicit choice, the registry `gitHead` therefore points at `806aa86…` rather
157
+ than the tag commit `ba8f05d…`; the annotated tag `v0.2.1` itself was not
158
+ moved and still peels to `ba8f05d…`.
159
+
160
+ - `npm publish` -> `+ dsh-context-guard@0.2.1` (19 files, package size
161
+ 70.5 kB, shasum `2a32ce46fd00fd87d144011653bd99fe2c5a9bd5`). The account's
162
+ npm token had expired and the publish required npm's EOTP web
163
+ authentication, completed in the browser.
164
+ - `npm view dsh-context-guard dist-tags.latest` -> `0.2.1`; versions sequence
165
+ `0.1.2, 0.2.0, 0.2.1`.
166
+ - `npm view dsh-context-guard@0.2.1 gitHead` -> `806aa863234a064b5c42391fa1288998abfc846e`.
167
+ - The official `dsh-context-guard-0.2.1.tgz` unpacks to version `0.2.1`; all
168
+ six packaged `dist/` files are byte-identical (md5) to the `ba8f05d`
169
+ gate-run build, and both README files are byte-identical to the `806aa86`
170
+ content. No `docs/PROBLEM_REPORT_v0.2.1.md` is part of the package.
171
+
172
+ ## 0.1.1 release candidate (2026-08-27)
173
+
174
+ The candidate was built on macOS from branch
175
+ `codex/0.1.1-bash-success-evidence`. The tested runtime domain bundle is
176
+ `dist/domain-DEXOzCqH.js` with SHA-256
177
+ `e8ad974b8263a2a25c7ef08ca3839097d3312c10d450b8520163c623e54881f9`.
178
+ The exact pre-commit source-tree and tgz digests are recorded in the generated
179
+ candidate manifest rather than embedded here: this document is itself part of
180
+ the npm archive, so embedding that archive's digest would change the digest.
181
+
182
+ Verified for this candidate:
183
+
184
+ - `pnpm install --frozen-lockfile`, typecheck, lint, all 106 tests, build, and
185
+ package-content validation completed successfully on macOS.
186
+ - The candidate tgz composed into fresh isolated `web` and `headless` profiles.
187
+ Both installed packages read back as `0.1.1`; a second identical add reported
188
+ `Already up to date`, and hashes of the profile manifests, lockfile, composed
189
+ patch files, and installed package manifest did not change.
190
+ - The 0.1.1 domain runtime replayed a completed real DSH Web log captured with
191
+ `activation: always` and confirmed durability. Its foreground `bash`
192
+ `pnpm typecheck` result contained ordinary stderr output and no
193
+ `[exit code: 0]` marker; replay derived successful scope evidence and issued a
194
+ certificate for all four matching open items with no rejected bindings.
195
+ - A clean Windows checkout of commit
196
+ `16ea9e7a5d088ce6b7e09617f15acd771f57ff40` passed the frozen install,
197
+ typecheck, lint, all 106 tests, build, and package-content validation with
198
+ DSH `0.1.1-rc.2`. The candidate package was
199
+ `dsh-context-guard@0.1.1` with SHA-256
200
+ `6c0aed77a9fc7f43f6d8bc11e4355d465d1146c81fe10276ad3e523f0abd8a83`.
201
+ Fresh isolated Web and headless profiles both read back version `0.1.1`; a
202
+ second identical installation was a strict no-op with unchanged lockfile
203
+ hashes.
204
+ - A separate minimal Windows real-model session loaded that candidate with
205
+ `activation: always`. One supported foreground `pwsh Set-Content
206
+ -LiteralPath ... -Encoding ascii -NoNewline` call created
207
+ `D:\dsh-pwsh-acceptance\pwsh-acceptance.txt`, and an independent `read`
208
+ returned `guard-test`. The persisted create evidence and read evidence were
209
+ bound to the single current contract; the checkpoint returned `certified`
210
+ at contract revision 1 with no open items or rejected bindings.
211
+
212
+ Evidence boundary:
213
+
214
+ - The macOS Web result is a candidate-runtime replay of a genuine closed Web
215
+ log, combined with isolated Web composition. It is not a claim that the
216
+ unpublished candidate was installed into the user's live Web profile.
217
+ - The Windows certificate covers only the documented PowerShell subset and the
218
+ exact candidate identity above. The first workspace-confined write attempt
219
+ was rejected because the target was outside the checkout; the same single
220
+ command succeeded only after an explicitly approved elevated retry. The
221
+ rejected call was not available for certification. This run does not expand
222
+ the Windows Bash claim or certify compound PowerShell commands.
223
+ - An earlier Windows session completed its model turn without a certificate,
224
+ and a later diagnostic session produced only scope evidence for compound
225
+ PowerShell calls. Neither is counted as acceptance. The successful result is
226
+ the fresh revision-1 session whose supported write and independent read
227
+ produced artifact-matching evidence.
228
+ - These pre-release native results do not by themselves establish CI, an npm
229
+ publication, a tag, or a GitHub Release; those publication identities require
230
+ separate readback.
231
+
232
+ ## Deterministic checks
233
+
234
+ ```sh
235
+ pnpm install
236
+ pnpm run typecheck # tsc --noEmit
237
+ pnpm test # vitest
238
+ pnpm run lint # oxlint
239
+ pnpm run build # tsdown
240
+ pnpm pack --dry-run --json
241
+ ```
242
+
243
+ ## Isolated profile composition (macOS, no real ~/.dsh)
244
+
245
+ ```sh
246
+ export DSH_HOME=/tmp/dsh-context-guard-smoke
247
+ DSH=/path/to/dsh
248
+ "$DSH" plugin --profile web add "file:/abs/path/to/dsh-context-guard"
249
+ "$DSH" --profile web --dump-config | grep context-guard
250
+ "$DSH" plugin --profile headless add "file:/abs/path/to/dsh-context-guard"
251
+ "$DSH" --profile headless --dump-config | grep context-guard
252
+ ```
253
+
254
+ Verified result: both profiles contain `id: context-guard, name: dsh-context-guard` in the composed tree.
255
+
256
+ ## Native load
257
+
258
+ A real headless boot loads the plugin and advances to the model call; it stops at `MISSING_CREDENTIAL` when no provider key is configured. That is the expected boundary for a load check and is unrelated to plugin correctness.
259
+
260
+ ## Verified
261
+
262
+ - Web UI command rendering and the `/context-guard on|off|status|diagnose` subcommands produce the expected `command/run`/`command/done` (round-5 isolated profile); `/context-guard diagnose` was re-verified in round-8.
263
+ - A complete macOS headless task in an isolated profile created one artifact,
264
+ read it back as durable evidence, rejected an incomplete first binding, then
265
+ certified the complete requirement and acceptance set before `turn/end`.
266
+
267
+ ## v0.2.0 Windows acceptance status
268
+
269
+ The GitHub tag `v0.2.0` resolves to release commit `c107cd8`. The GitHub
270
+ Release is published at
271
+ https://github.com/GreenLv/dsh-context-guard/releases/tag/v0.2.0.
272
+
273
+ Windows 0.2.0 native runtime acceptance completed in the separate live DSH
274
+ Web session. The loaded package version was `0.2.0`. The supported PowerShell
275
+ command
276
+
277
+ `Set-Content -LiteralPath 'D:\dsh-pwsh-acceptance\pwsh-acceptance-020.txt' -Value 'guard-test' -Encoding ascii -NoNewline`
278
+
279
+ created the artifact successfully after the documented permission-boundary
280
+ retry. An independent `read` returned exactly `guard-test` with no trailing
281
+ newline. The durable evidence IDs from that session were `E0009` for the
282
+ successful PowerShell write and `E0011` for the independent read.
283
+
284
+ The session's checkpoint attempt was `incomplete`, and a follow-up session
285
+ also rejected `E0009` and `E0011` because those IDs are not present in its
286
+ current session projection. Context Guard currently derives evidence from the
287
+ active DSH event log only; it has no cross-session evidence import or lookup
288
+ contract. The runtime actions and their outputs are therefore recorded as
289
+ completed runtime acceptance, but the v0.2.0 checkpoint remains `incomplete`
290
+ in this later session by design. To obtain a certificate, the commands and
291
+ checkpoint must be performed in one session. The Windows scope is limited to
292
+ the documented PowerShell subset and does not expand to Windows Bash or
293
+ compound PowerShell syntax.
294
+
295
+ ## Native platform acceptance
296
+
297
+ - macOS: an isolated real-model headless task used a supported POSIX shell
298
+ write and an independent read, then persisted a certified checkpoint before
299
+ the completed turn.
300
+ - Windows: the v0.1.1 candidate had an isolated real-model task using
301
+ `pwsh Set-Content -LiteralPath` and an independent read, with a certified
302
+ checkpoint. The v0.2.0 runtime actions are recorded in the dedicated status
303
+ section above, but their cross-session checkpoint repair remains incomplete.
304
+
305
+ Both final-SHA runs used clean public checkouts and isolated `DSH_HOME`
306
+ directories. They establish native behavior for the bounded v0.1 command
307
+ subset; they do not claim support for shell or PowerShell syntax outside the
308
+ subset documented in `COMPATIBILITY.md`.
309
+
310
+ ## Public-package profile readback
311
+
312
+ On macOS, the published `dsh-context-guard@0.1.0` npm package was installed into a real DSH Web profile through the pinned `codex-sync` plugin reconciler. A second dry run was a strict no-op; direct package and bundle readback reported version `0.1.0`; `dsh --profile web --dump-config` included the `context-guard` bundle; and the restarted Web command directory exposed `/context-guard`, whose `status` subcommand returned a valid projection summary.
313
+
314
+ This verifies public-package consumption and real-profile loading on macOS. It does not replace the isolated model-task evidence above and does not claim a second Windows run from the public npm package.
315
+
316
+ ## macOS v0.1.2 acceptance (2026-08-27)
317
+
318
+ Verified commit: `dd402fbaa5d37dd246056d8ecd66430e5f75f412` (annotated tag `v0.1.2`, clean checkout, `main` fast-forwarded to the tag). macOS, Node v25.1.0, pnpm 11.22.0.
319
+
320
+ Gate run (exit codes and summary):
321
+
322
+ - `pnpm install --frozen-lockfile` → 0.
323
+ - `pnpm test` → 0; 5 test files, 107 tests passed.
324
+ - `pnpm run typecheck` → 0.
325
+ - `pnpm run lint` → 0 errors / 0 warnings (23 files, 96 rules).
326
+ - `pnpm run build` → 0; 6 files, 123.60 kB total (`dist/index.js`, `dist/domain/index.js`, `dist/domain-CJulh_RZ.js`, `dist/index.d.ts`, `dist/domain/index.d.ts`, `dist/index-CA7Z-W_A.d.ts`).
327
+ - `pnpm run pack:check` → 0.
328
+
329
+ Artifact check: `shell exited: code` is present in `dist/`. The literal string `persistent bash shell was reset` cannot appear in any build of commit dd402fb, because the implementation parameterizes the reset line as `/^The persistent (?:bash|pwsh) shell was reset;/` to cover both persistent renderers (`src/domain/evidence.ts` `PERSISTENT_RESET_LINE`). Equivalent checks pass: the regex is present in `dist/domain-CJulh_RZ.js` (line 1059), it matches the rendered Bash and pwsh prose lines (run through `RegExp.test`), and the built `dist` module replays all eight 0.1.2 cases (`[shell exited: code 1]`, `[shell killed by signal: SIGTERM]`, `[shell exited]`, timeout intro — each with and without the reset prose; plus `[shell exited: code 0]` → success and reset-prose-only → success) with the expected outcomes.
330
+
331
+ Publication readback: `npm view dsh-context-guard dist-tags.latest` = `0.1.2`; registry `gitHead` = `dd402fbaa5d37dd246056d8ecd66430e5f75f412`; the official tarball `dsh-context-guard-0.1.2.tgz` unpacks to version `0.1.2` with both artifacts above, and all six `dist/` files are byte-identical (md5) to the local build — the published artifact matches the gate-run build.
332
+
333
+ Installed state (macOS, real `~/.dsh`, `codex-sync` managed): pin raised `0.1.1` → `0.1.2` in `config/dsh/plugins.toml`; `--check-updates` reported the pin current; the pre-apply dry run planned exactly one UPDATE; `--apply` ran the single `dsh plugin --profile web add dsh-context-guard@0.1.2` pass; `~/.dsh/profiles/web/node_modules/dsh-context-guard/package.json` reads `0.1.2`, the installed `dist/` carries both vocabulary markers, the package stays in `dsh.profile.bundles`, and a follow-up dry run is a no-op (`No DSH plugin changes needed`). DSH was restarted (process started 23:41:05, after the 23:39:17 install) so the live instance loads 0.1.2.
334
+
335
+ Smoke (in the live guarded session, 0.1.2 loaded): a clean foreground `pnpm test` in this repository completed with 5 files / 107 tests passed and produced no terminal marker; the guard-derived evidence (`E0065`, bash, repo scope) carries outcome `success`, and the checkpoint binding `{R042, [E0065]}` was accepted with no rejected bindings — the clean foreground bash result both scores `success` and certifies its matching item, confirming the 0.1.1 clean-success contract still holds under 0.1.2 (the 0.1.1 → 0.1.2 core regression point). One earlier binding was properly rejected and is recorded, not hidden: the first smoke attempt wrapped the command in `2>&1 | tail -6; echo ...`, which the guard classifies as non-deterministic with no supported operations; the binding `{R041, [E0058]}` failed the run contract, and no binding rule was changed for it. A subsequent clean run was used for the accepted binding.
336
+
337
+ This section records the live-profile acceptance of v0.1.2 on macOS. It does not claim completion of the session's full 55-item contract, which was not part of this smoke; it does not re-claim any Windows result.
@@ -0,0 +1,14 @@
1
+ # Porting Notes
2
+
3
+ The DSH implementation ports deterministic Context Guard semantics from `GreenLv/codex-context-guard` v0.8.8 while replacing the platform layer.
4
+
5
+ | Area | Treatment |
6
+ | --- | --- |
7
+ | canonicalization, hashing, IDs | Port to TypeScript |
8
+ | contract capture and supersession | Port as pure domain functions |
9
+ | evidence and proof binding | Adapt to DSH durable tool-result events |
10
+ | recovery and stop policy | Adapt to DSH agent lifecycle |
11
+ | Codex hooks, cache manager, Python runtime | Delete from DSH runtime |
12
+ | multimodal assets, subagent provenance, rollover | Defer beyond 0.1.0 |
13
+
14
+ The DSH port derives all guard state from natively persisted DSH session events (`command/run`, `user/message`, `tool/call`, `tool/result`, `tool/code-dispatch*`) instead of the removed custom event vocabulary, wires the completion gate to Goal interception and agent scoping, and enforces fail-closed certification. Native isolated real-model acceptance has passed on macOS and Windows, and the public npm package has been loaded and exercised in a real macOS Web profile. These results cover the bounded v0.1 command subset; they do not broaden it into general shell or PowerShell analysis or claim a second Windows run from the public package.
@@ -0,0 +1,23 @@
1
+ # Privacy
2
+
3
+ Context Guard stores only bounded, deterministic facts. It does not persist prompt or tool-output bodies.
4
+
5
+ ## Stored
6
+
7
+ - Normalized clause text (single-line, whitespace-collapsed) and its SHA-256.
8
+ - Stable identifiers (R/A/P/E/C), revision, epoch, and event sequence references.
9
+ - Tool name, call/result seq, outcome enum, capability, subject, and surface.
10
+ - A bounded summary hash (truncated to 240 characters before hashing).
11
+
12
+ ## Never stored
13
+
14
+ - Complete prompts, stdout, stderr, or file contents.
15
+ - Authorization headers, URL query values, credentials, or API keys.
16
+ - Image bytes or binary contents.
17
+ - Authenticated session state or raw transcripts.
18
+
19
+ ## Failure behavior
20
+
21
+ - Unknown, failed, or object-mismatched evidence cannot certify completion.
22
+ - Without a durability checkpoint, evidence is recorded as `unknown`.
23
+ - Corrupt or unknown Guard state refuses certification rather than guessing.
@@ -0,0 +1,22 @@
1
+ # Upstream Base
2
+
3
+ This repository ports deterministic semantics from an existing Codex product; it is a new, independently owned repository with a fresh history.
4
+
5
+ ## Semantic baseline
6
+
7
+ - Repository: `https://github.com/GreenLv/codex-context-guard`
8
+ - Version: `v0.8.8`
9
+ - Tag object: `827602ca96653a53c00e9fae088bb46003509dc6`
10
+ - Peeled source commit: `e661370442183913b717ec2535609377bbb8664a`
11
+ - License: Apache-2.0
12
+ - Key contracts: private state schema 7, Proof protocol 1.0.0, Stop protocol 1.1.0
13
+
14
+ ## Reused vs replaced
15
+
16
+ Reused as behavior: canonicalization, hashing, stable identity, requirement/acceptance/prohibition capture, append-only supersession, evidence outcome classification, subject/surface matching, proof and stop semantics, recovery priority, completion classification.
17
+
18
+ Replaced: the Codex Hook runtime, Python subprocess, plugin cache installer, and `PLUGIN_DATA` state path. The DSH runtime is TypeScript over the Session event log; it does not use the Codex Hooks bridge.
19
+
20
+ ## Not copied
21
+
22
+ Codex installer/manager code, Hook cache lifecycle, private runtime data, transcripts, credentials, and commit history are intentionally absent.