Skip to content

fix(file): reserve audit-store components in absolute paths - #344

Merged
T-Auto merged 72 commits into
mainfrom
work/329-ccch1mneyyy
Oct 25, 2026
Merged

T-Auto merged 72 commits into
mainfrom
work/329-ccch1mneyyy

Conversation

@ccch1mneyyy

@ccch1mneyyy ccch1mneyyy commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #329

What was wrong

Public file operations could address the reserved .dsh-ops audit-store path. A caller could therefore modify a lifecycle journal that later trusted batch recovery would consume.

The change

Reserve the exact .dsh-ops path component case-insensitively in common public file-path validation, before filesystem effects. Search excludes those components during traversal. Trusted internal audit lifecycle APIs remain available, and similarly named ordinary paths remain usable. Preserve the original contributor's commits and merge current main without rewriting pushed history; the changelog resolution retains both sets of entries.

Validation

Current-head pull_request CI: https://github.com/T-Auto/dsh-ops/actions/runs/40110582568 — CI required, Windows x64, Linux x64, macOS arm64, tools-trial, workflow-lint, source-size and node-floor all passed. Conditional bench-smoke was skipped. GitHub reports head 5da1cf55e63474c400e1eda580969c33eea05dfe mergeable.

npm run build
  passed
cargo test --workspace --locked --manifest-path native/Cargo.toml
  52 passed; 0 failed; 1 ignored (external UNC fixture)
cargo build --release --locked --manifest-path native/Cargo.toml
  passed
node test/run.mjs audit-store-paths search-coverage credential-fence file-operations
  audit-store-paths 63, search-coverage 8, credential-fence 11, file-operations 14 checks passed
  4 suites passed; 0 failed; 0 skipped
node scripts/validate-manifest.mjs
  73 checks passed
node scripts/check-file-size.mjs
  387 files checked; all <= 1000 lines
Red/green: remove only the reserved-component guard, retaining new Rust tests
  2 passed / 2 failed; restore guard: 4 passed / 0 failed
git diff --check
  passed

The local Node 26 full run was stopped after Bash fixture-copy and native-result suites exceeded their 120-second deadlines while multiple Windows runs competed for I/O. No local full-gate pass is claimed. The independent current-head Windows CI job passed. Bilingual documentation and changelog are included; no new dependencies, schema fields or package version changes.

Environment

Windows x64, Node 26.12.1, Cargo 1.99.0; merge of original PR head 97162cc87cc01f8848fac23095423e8afbdb61dd with main 662a38871f2241886343090adda0a1107a50e274.

Richeir and others added 23 commits October 19, 2026 16:38
The report's H1 was derived from the two run labels ("bench compare: base ->
cand"); it is now a fixed title. The compared sides stay named in the 证据
section, and the suite pins both the new title and that evidence.

Refs #262
The report led with a summary bar and a `结论` section; it now opens with
the fixed title and goes straight into the evidence, and the `结论` — pass
rate, paired token Δ, noise floor, direction, gate and reasons — ends the
document, so a reviewer reads the data before the judgement.

Every percent is painted by its sign (a drop or no change green, a rise
red, the same palette as `panel.html`) with inline spans; the digits stay
the core's, including in the gate reasons and the warnings. A value the
core stated as a bare number is printed verbatim and painted the same way
instead of gaining an invented sign.

Two diagnostics join the report: per-task steps and tool calls, summed in
`TOTAL` and read as `min` or `median` by `--aggregate` (one decimal when an
even repeat count halves the median, so a cell never contradicts its own
Δ%), and the 工具调用 table marks a candidate-side call to a tool outside
`ops` in red.

bench/README.md documents the reading order and both colour rules; the
suite pins the layout, the colours and the counts.

Refs #262
On main after #307 the Windows validation leg took 527 / 529 s (482 s
before #307, because npm ci now downloads the 411 MB Windows Bash
payload); Linux took 136–139 s and macOS 168–182 s. Splitting the leg
into shards was measured at 1.5–2.4× the runner minutes and still stayed
above 300 s on a slow runner, so by the approved ">300 s → non-blocking"
rule it becomes a signal instead of a gate.

- split `validate` into blocking `validate-posix` (Linux x64, macOS arm64)
  and `continue-on-error` `validate-windows` (win32-x64); the steps are
  unchanged and Windows still runs on every push, pull request and merge
  group;
- drop every `continue-on-error` job from `ci-required.needs`, so the
  required check neither waits for nor fails with the slowest leg, and
  print one static note instead of reading results the aggregate no
  longer has;
- teach `scripts/check-workflows.mjs` that the aggregate depends on every
  blocking job, on no non-blocking job, that a job outside the aggregate
  must opt out of blocking explicitly, and that its failure loop covers
  exactly the blocking jobs — a job left in `needs` but dropped from the
  loop is a false green;
- remove two steps that could never run after the split: the Windows Bash
  payload check in `validate-posix` and the Linux ACL install in
  `validate-windows`;
- update the structural test that pinned the old "in needs, not in the
  loop" contract, the CI docs (English and Chinese) and the changelog.
Retitle the report to "DSH-OPS Benchmark Report" and translate every rendered section, table header, direction label and evidence line, plus the matching CLI notes and comments, so generated report.md and comparison artifacts never carry CJK text. Align bench/README's report walkthrough with the English section names and add a guard assertion that fails if CJK returns to a rendered report.

Verified with node test/run.mjs bench- (17 suites, all passing) and npm run check:size.
The default artifact was <cand>/report.md, so a report about a whole sweep was buried inside the arm directory that measured half of it. It now lands in the sweep's group folder as 'DSH-OPS Benchmark Report <UTC>.md': full-sweep-4 keeps its report at bench/runs/full-sweep-4/, a rerun keeps the earlier artifact instead of overwriting it, and a run with no group folder above it keeps the report beside its run.json. --out, --out - and --json are unchanged, and the rendered text stays clock-free and diffable.

The optional benchmark smoke uploads the stamped name as well as report.md.
The per-task table now carries the numbers a reviewer scans for: paired
tokens, steps, tool calls, tool errors and pass, with each Δ% beside the
value it describes. The pairs-usable, excluded, pass, direction and geomean
rows are gone, and no table carries an explanatory line under its heading.

The tool-calls table moves directly under that table: one row per tool with
the sweep-wide base/cand columns kept, then one column per task. Its colour
follows adoption rather than the sign: an ops_* tool rising is green, any
other tool rising is red, and the reverse for a fall. The excluded-pairs,
A/A noise-band and token-attribution sections are gone; the excluded counts
survive in the warnings, and the conclusion still states the floor and the
one direction that is read.

The sweep runner now counts tool results whose status is error, which the
new column reads and the metrics schema already declared.
A read-only replacement (0400) denies setxattr, so restoring the captured
attributes after fchmod reported every one of them as unrestored. On macOS
that covered com.apple.provenance, which the system gives every new file, so
a clean 0400 replace always carried a warning.

Apply the attributes while the replacement is still writable, then the mode
(after chown, which clears setuid and setgid), then the ACL (which chmod
rewrites).

The mode matrix now attaches a user attribute before the final chmod, so the
ordering is asserted on every host rather than only where macOS supplies the
attribute for free.
Enumerate Windows UNC directories by absolute path while retaining handle-based child checks. Detect observable directory identity changes and report PATH_CHANGED. Add glob, grep and replace dry-run regression coverage and run the UNC fixture in Windows CI. Record the behavior change for #326.
Classify unsupported Windows filesystem locks as LOCK_UNSUPPORTED while retaining REVISION_CONFLICT for contention. Integrate with the upstream UpdateLock guard so its binding and sidecar cleanup behavior remain intact. Add classification tests and a bilingual changelog entry for #326.
On Linux hosts where the sandbox selects bwrap, workspace-write children
get a private tmpfs over /tmp. The result cache lives below the host's
tmpdir(), so the confined PTC worker behind ops_result never saw it:
every ref:// page failed with REFERENCE_EXPIRED and the session purge
completed against an empty tmpfs, leaving the cache behind.

Bind exactly that one private cache directory back into the bwrap argv
for page/put and for the session purge. Other runners, read-only bwrap
and Windows keep their argv unchanged.

Refs #337
T-Auto and others added 13 commits October 21, 2026 15:08
fix(bash-ipc): retry a transiently refused quarantine (#352)
[Draft] fix(file): restore extended attributes before the final mode
Updated image sizes in README for better display.
…atch

bench/llm.patch.example.yml, the README and setup all promised that every dsh
call carries bench/llm.patch.yml; the runner never did. A sweep then ran both
arms on the profiles' own routes - identical on both sides, so the report could
not show the difference and the run still looked complete.

Resolve the overlay before any spawn: default to the file setup creates, accept
--llm-patch <path> for another one, --no-llm-patch to state that the profiles'
own routes are meant, and refuse a missing overlay with exit 2. The archived
argv records the overlay the operator did not type, and the plan prints it.
[Benchmark] 增加 Benchmark Report 的可读性,修复 LLM 配置项问题 (#262)
FastCtx was removed in 0.3.2, so the composite MIT AND Apache-2.0 statement no longer describes the current code. Declare the current distribution as MIT and keep FastCtx's Apache-2.0 text and required attribution in licenses/fastctx/ and NOTICE for the earlier releases that shipped it.
chore(license): relicense the current distribution as MIT
* fix(policy): name the shell tool by its published name

The tooling policy called the shell 'bash' in the routing heading and in
the prefer-for-command-execution line, but the registry publishes
'ops_bash'. The model read a tool name it could not call: #298 recorded 15
'unknown tool bash' calls in one session before it switched on retry.

Build both strings from BASH_TOOL so they cannot drift from the published
name again, and state outright that no bash tool exists, so a model that
leans on the Claude Code vocabulary has an explicit rule to read.

A new assertion fails if any model-visible line other than that prohibition
names bash; reverting the source turns it red.

* fix(policy): name the shell ops_bash and stop claiming bash is absent (#306)

The routing heading and the "prefer for command execution" line named a tool
the registry does not publish.

The prohibition line added in #306 is dropped: the renderer only receives
`published` filtered to the plugin's own names, and under the default
`shellPolicy: advise` the host `bash` stays visible on Linux and macOS, so the
claim would be false there. A denied host shell reports a policy denial, not
`unknown tool`.

The test added in #306 is rewritten: it rejects a bare `bash` (case
insensitive) without depending on that sentence.

Co-authored-by: sueqet <[email protected]>

---------

Co-authored-by: sueqet <[email protected]>
Co-authored-by: ViscaOwO <[email protected]>
A selected replacement is verified through owned native providers, which a
run_code scope never has: the counterpart is an SDK function there. Readiness
therefore could not pass, and every PTC session failed prompt assembly with
READINESS_BLOCKED as soon as replaceTools named one tool. The scope was then
left with the official tools visible but refused at dispatch, so the model's
first read fell back to ops_read_files after burning a call.

Judge the assembled surface instead of the registry view: a scope whose only
tool is run_code is collapsed, has no native duplicate to replace, and owns no
mask and no error. A native scope that really kept a selected official tool
still fails closed.
Thatgfsj
Thatgfsj previously approved these changes Oct 23, 2026

@Thatgfsj Thatgfsj left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

111

dependabot Bot and others added 4 commits October 24, 2026 04:32
Bumps [zip](https://github.com/zip-rs/zip2) from 9.0.1 to 9.0.5.
- [Release notes](https://github.com/zip-rs/zip2/releases)
- [Changelog](https://github.com/zip-rs/zip2/blob/master/CHANGELOG.md)
- [Commits](zip-rs/zip2@v9.0.1...v9.0.5)

---
updated-dependencies:
- dependency-name: zip
  dependency-version: 9.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
A collapsed scope keeps only the transport callable: the selected official tools stay refused, directly and when dispatched from a program, so the credential fence in the file worker still applies. Adds a regression that a later tools/change does not put the transport back behind the readiness gate.
fix(hide-official): stop gating run_code scopes on native readiness
chore(deps): bump zip from 9.0.1 to 9.0.5 in /native
T-Auto
T-Auto previously approved these changes Oct 25, 2026
@ccch1mneyyy
ccch1mneyyy dismissed T-Auto’s stale review October 25, 2026 03:14

The merge-base changed after approval.

@T-Auto T-Auto left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved for merge per maintainer decision.

@T-Auto
T-Auto merged commit 7549377 into main Oct 25, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] ops_write_file 可写入 .dsh-ops 审计存储,伪造 manifest 经 ops_batch resume 驱动真实删除

10 participants