refactor(ci): port the stable wrapper E2E to Rust and drop its PowerShell call point (#78) - #80
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
Warning Review limit reached
Next review available in: 42 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe legacy PowerShell stable-wrapper E2E test was deleted. CI no longer runs or parser-checks it. Rust integration tests now cover successful and failed wrapper runs, artifact publication, manifest resolution, and authoritative indexing. ChangesStable wrapper E2E coverage
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
crates/code-intel-cli/tests/stable_wrapper_e2e.rs (4)
156-159: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAssert the outcome on one line instead of two independent substrings.
outputis the concatenation of stdout and stderr. The current check passes whenOutcome:andcompletedappear anywhere in that text, including on different lines. The tokencompletedis common in run identities, node status text, and log lines. The assertion can therefore pass while the summary printsOutcome: process_failed.The PR keeps this test specifically to cover the summary lines that
main.rsprints. Matching a single line preserves that guarantee.♻️ Proposed line-scoped assertion
- assert!( - output.contains("Outcome:") && output.contains("completed"), - "summary lacks the completed outcome: {output}" - ); + assert!( + output + .lines() + .any(|line| line.contains("Outcome:") && line.contains("completed")), + "summary lacks the completed outcome: {output}" + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/code-intel-cli/tests/stable_wrapper_e2e.rs` around lines 156 - 159, Update the assertion in the stable-wrapper end-to-end test to match a single complete output line containing both the “Outcome:” label and “completed,” rather than checking independent substrings across output. Preserve the test’s coverage of the summary emitted by main.rs and avoid matches from unrelated run identities, statuses, or log lines.
89-92: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd context to the marker unwrap.
The doc comment states that this helper exists so the test fails when the marker stops binding the manifest. If
manifest.pathis missing or is not a string,unwrap()panics with a generic message and does not show the marker contents. Every other fallible step in this file usesunwrap_or_elsewith a descriptive panic. Matching that pattern makes the guarded contract self-reporting.♻️ Proposed diagnostic message
fn manifest_of(run: &Path) -> Value { let marker = read_json(&run.join("run-complete.json")); - read_json(&run.join(marker["manifest"]["path"].as_str().unwrap())) + let relative = marker["manifest"]["path"] + .as_str() + .unwrap_or_else(|| panic!("marker does not bind a manifest path: {marker}")); + read_json(&run.join(relative)) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/code-intel-cli/tests/stable_wrapper_e2e.rs` around lines 89 - 92, Update manifest_of so the manifest.path extraction uses unwrap_or_else with a descriptive panic that includes the marker value, while preserving the existing read_json flow. Match the file’s established fallible-step diagnostic pattern and ensure missing or non-string paths report the marker contents.
31-43: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider isolating the
gitinvocations from developer global configuration.The commit invocations set
user.nameanduser.emailinline, so identity is safe. Global configuration can still break the fixture. If a developer setscommit.gpgsign=trueglobally, the fixture commit fails and the test reports agiterror instead of a wrapper defect. A hook template frominit.templateDircan also run duringgit init.Setting the environment once in the helper keeps every call hermetic.
♻️ Proposed hermetic git helper
fn git(repo: &Path, args: &[&str]) { let output = Command::new("git") .arg("-C") .arg(repo) + .env("GIT_CONFIG_GLOBAL", "/dev/null") + .env("GIT_CONFIG_SYSTEM", "/dev/null") + .env("GIT_CONFIG_NOSYSTEM", "1") .args(args) .output() .unwrap_or_else(|error| panic!("git {args:?} could not start: {error}"));Note that
/dev/nullis not portable to Windows; useNULthere, or point both variables at a file inside the fixture root.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/code-intel-cli/tests/stable_wrapper_e2e.rs` around lines 31 - 43, Update the git helper to isolate all Git invocations from developer configuration by setting the appropriate environment variables once, including disabling global config, commit signing, and hook templates. Use a portable null-device value or fixture-local file instead of hardcoding /dev/null, while preserving the existing command execution and failure reporting.
244-249: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winPin the process-failure exit code.
assert_ne!(code, Some(0))only rejects success; it still passes when the child receives a signal (codeisNone). This invalid UTF-8 fixture already expectsprocess_failed, anddag_coordinator.rsreturns exit code70forProcessFailedandIncomplete. AssertSome(70)to cover the documentedrun executeprocess-failure exit-code contract.♻️ Proposed exit-code assertion
- assert_ne!( - code, - Some(0), - "wrapper hid an authoritative failure: {output}" - ); + assert_eq!( + code, + Some(70), + "wrapper did not report the documented process-failure exit code: {output}" + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/code-intel-cli/tests/stable_wrapper_e2e.rs` around lines 244 - 249, Update the exit-code assertion in the run_wrapper test to require Some(70) rather than merely rejecting Some(0), preserving the existing output message and validating the documented ProcessFailed/Incomplete exit-code contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/code-intel-cli/tests/stable_wrapper_e2e.rs`:
- Around line 66-78: Update latest_core_run to identify the newest run by its
runIdentity marker or manifest before selecting its -core directory, rather than
relying on lexicographic sorting and runs.pop(). Account for commit() placing
final_name directly under the authority directory, and exclude completed_run if
that is the established non-run directory.
---
Nitpick comments:
In `@crates/code-intel-cli/tests/stable_wrapper_e2e.rs`:
- Around line 156-159: Update the assertion in the stable-wrapper end-to-end
test to match a single complete output line containing both the “Outcome:” label
and “completed,” rather than checking independent substrings across output.
Preserve the test’s coverage of the summary emitted by main.rs and avoid matches
from unrelated run identities, statuses, or log lines.
- Around line 89-92: Update manifest_of so the manifest.path extraction uses
unwrap_or_else with a descriptive panic that includes the marker value, while
preserving the existing read_json flow. Match the file’s established
fallible-step diagnostic pattern and ensure missing or non-string paths report
the marker contents.
- Around line 31-43: Update the git helper to isolate all Git invocations from
developer configuration by setting the appropriate environment variables once,
including disabling global config, commit signing, and hook templates. Use a
portable null-device value or fixture-local file instead of hardcoding
/dev/null, while preserving the existing command execution and failure
reporting.
- Around line 244-249: Update the exit-code assertion in the run_wrapper test to
require Some(70) rather than merely rejecting Some(0), preserving the existing
output message and validating the documented ProcessFailed/Incomplete exit-code
contract.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: afa14ee1-7303-4b0b-8fe3-e4b9481b1c82
📒 Files selected for processing (4)
.github/workflows/ci.ymlcrates/code-intel-cli/tests/stable_wrapper_e2e.rsdocs/ps1-exit/contract-inventory.mdlegacy/scripts/tests/test-stable-wrapper-e2e.ps1
💤 Files with no reviewable changes (2)
- .github/workflows/ci.yml
- legacy/scripts/tests/test-stable-wrapper-e2e.ps1
| fn latest_core_run(authority: &Path) -> PathBuf { | ||
| let mut runs: Vec<PathBuf> = fs::read_dir(authority) | ||
| .unwrap_or_else(|error| panic!("no authority at {}: {error}", authority.display())) | ||
| .filter_map(|entry| { | ||
| let path = entry.unwrap().path(); | ||
| let name = path.file_name()?.to_str()?.to_string(); | ||
| (path.is_dir() && name.ends_with("-core")).then_some(path) | ||
| }) | ||
| .collect(); | ||
| runs.sort(); | ||
| runs.pop() | ||
| .unwrap_or_else(|| panic!("no authoritative run under {}", authority.display())) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Find how authoritative `-core` run directory names are composed.
set -euo pipefail
# Locate the publication/commit code that builds the final run name.
rg -nP --type=rust -C6 '"-core"|-core\b|final_name|FinalName' crates | head -200
# Look for the timestamp/stamp formatting used for run identities.
rg -nP --type=rust -C4 'fn .*(run_name|final_name|stamp|run_identity)' crates | head -120Repository: 2233admin/code-intel-pipeline
Length of output: 22074
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Relevant test snippet =="
sed -n '50,90p;240,270p' crates/code-intel-cli/tests/stable_wrapper_e2e.rs
echo
echo "== latest_core_run callers and artifact helpers =="
rg -n --type=rust -C5 'latest_core_run|latest_run_dir|utc_run_stamp|final_name' crates/code-intel-cli/src | head -260
echo
echo "== RunCommitBuilder/final_name construction sites =="
rg -n --type=rust -C5 'final_name\s*:|final_name:|RunCommitBuilder|run commit' crates/code-intel-cli/src crates/code-intel-cli/tests/stable_wrapper_e2e.rs crates/code-intel-cli/tests/run_commit.rs | head -360
echo
echo "== Stable wrapper final_name passes =="
rg -n --type=rust -C8 'final_name|stable_wrapper|completed_run|failed_run|latest_core_run' crates/code-intel-cli/tests/stable_wrapper_e2e.rsRepository: 2233admin/code-intel-pipeline
Length of output: 42339
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import re
src = Path("crates/code-intel-cli/src/run_commit.rs").read_text()
m = re.search(r"fn commit\(.*?\n\}\n\nfn validate_final_name", src, re.S)
if not m:
print("commit function not found")
raise SystemExit(1)
body = m.group(0)
print("commit body length:", len(body))
print("uses final_name:")
print(" final_path:", "final_path = authority_root.join(final_name)" in body)
print(" rename_directory_no_replace:", "rename_directory_no_replace(&stage_path, &final_path)" in body)
print(" utc_run_stamp:" in body)
# Programmatically check whether the commit function directly consumes any timestamp/stamp helper.
print("contains utc_run_stamp call expression:", "utc_run_stamp(" in body)
print("contains utc_now() call expression:", "utc_now(" in body)
print("contains SystemTime::now() expression:", "SystemTime::now()" in body)
PYRepository: 2233admin/code-intel-pipeline
Length of output: 404
Select the latest run by run identity before picking a -core directory.
run commit moves final_name directly to the authoritative directory, so commit() does not generate the utc_run_stamp name used by latest_run_dir(). If final_name is not guaranteed chronologically monotonic, runs.pop() can return the wrong run. Select by runIdentity marker/manifest instead, or explicitly exclude completed_run.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/code-intel-cli/tests/stable_wrapper_e2e.rs` around lines 66 - 78,
Update latest_core_run to identify the newest run by its runIdentity marker or
manifest before selecting its -core directory, rather than relying on
lexicographic sorting and runs.pop(). Account for commit() placing final_name
directly under the authority directory, and exclude completed_run if that is the
established non-run directory.
|
🔒 Repowise is not analyzing this repository The PR bot is free on public repositories. This one is private, which needs a Pro plan. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/code-intel-cli/tests/primary_entry.rs`:
- Around line 128-141: The skip condition in the test around run_wrapper must
inspect the doctor failure’s diagnostic, not merely output.contains("Domain
failure: doctor"). Only return early when the output explicitly identifies a
missing host toolchain/tool diagnostic; preserve the authoritative
run/index/query assertions for doctor bootstrap, manifest/config, provider
conformance, and other domain failures.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 33a810ff-223f-4022-96fe-6a38a7623e75
📒 Files selected for processing (2)
.sentrux/baseline.jsoncrates/code-intel-cli/tests/primary_entry.rs
* fix(sentrux): coupling must not measure the PowerShell share of the tree (#78) `coupling_score` is import lines per file. The scanner reads import/from/use/mod/require(/#include/using, none of which is how PowerShell declares a dependency — it dot-sources and calls Import-Module. Counting .ps1/.psm1 in the denominator therefore made the score fall whenever PowerShell grew and rise whenever it shrank. Under the PS1 retirement campaign that inverts the gate. PR #80 deleted one PowerShell test, added the Rust test that replaces it, raised quality_signal by 60, and still failed `coupling_increased` 45.64 -> 45.73. Every one of the ~43 remaining call points would have failed the same way, so the ratchet was measuring the campaign rather than regression. Numerator and denominator now both cover only languages whose imports the scanner models. A tree with none of the unmodelled languages scores exactly as before; this one measures 74.41 (1064 edges over 143 modelled files) where dilution reported 45.48. Everything else — size, functions, complexity, god files — still covers every collected extension. Consequences, all in this commit: - baseline re-saved; schema -> code-intel-sentrux-baseline.v3, so a v2 baseline fails closed as `baseline_engine_mismatch` with the re-baseline instruction instead of reporting a fabricated ~30-point coupling regression on first run after upgrade. - max_coupling accepts a bare number as well as an A..D grade. The ladder tops out at D = 6 imports per file, which no idiomatic Rust tree stays under, so keeping "D" would mean a permanently red rule. .sentrux/rules.toml records the measured 76.0 as a ratchet; tightening is tracked with the other threshold debt in #14. - the PowerShell shim mirrors both changes, so a shim injected through options.toolPathPrefix cannot compare an old-formula score against a new-formula baseline. - [coupling_basis] and metrics.import_modeled_files report the denominator rather than leaving it to be derived from the ratio. Verified: cargo test 2633 passed / 46 suites; cargo fmt clean; retirement packet suite 8 packets + 2 audits PASS; authoritative self-scan puts diagnosis.hospital back to succeeded/pass on this tree. With #80's diff applied on top, the gate reads 74.41 -> 74.31 and passes. Refs #78 * fix(sentrux): re-pin the capability toolchain digest for sentrux_gate.rs `provider.sentrux-adapt` carries the gate source digest in two places: the internalization record and `orchestration/integrations.json`'s toolchainDigests. The first commit updated only the record, so test-atomic-capability-contract.ps1 failed on all four CI lanes with "provider.sentrux-adapt toolchain digest is stale for crates/code-intel-cli/src/sentrux_gate.rs". test-atomic-capability-contract.ps1 now passes locally; the gate still reports no degradation. Refs #78 * fix(compatibility): refreeze the six packets that pin orchestration/integrations.json E02, E03, E04, E07, E08 and E10 all carry integrations.json in their frozen source set, so re-pinning the sentrux_gate.rs toolchain digest made every one of them stale. Same mechanism the E10 verifier documents for #48's edit to the same file. Regenerated with each packet's own generator at its recorded EvaluatedAt (1785441780), so the only fields that move are snapshotIdentity, artifact ref sha256s and the request/approval digest payloads that carry them. Blockers, decisions, evidence classes, window timestamps and file sets are byte-identical — verified field by field before installing. Also removes the generators' rollback scratch under legacy/work/ — it is gitignored but not invisible to the scanner, and three copies of run-code-intel.ps1 left there pushed the tree to 242 files / 36 god files and failed the gate on quality. Refs #78
…hell call point (#78) `test-stable-wrapper-e2e.ps1` never tested PowerShell. Every assertion in it was already about the compiled binary: the default route with no subcommand, the `*-core` run it publishes, what the authoritative index does with a run that failed, and the human-facing summary lines. But no Rust test asserted those summary lines — `[PASS]`, `[FAIL]`, `Outcome:`, `Cause:`, `Run evidence:` are printed from `main.rs:470` and nothing else covered them — so dropping the step would have silently removed the only cover for the binary's own user-facing output. Ported verbatim to `tests/stable_wrapper_e2e.rs`, keeping every assertion: - a clean fixture (including an unsupported binary file, which must not be grounds for rejection) publishes a completed run whose `evidence.graph`, `evidence.sentrux` and `diagnosis.hospital` nodes all pass - the doctor observation is published and the default route's repowise skip reaches the authoritative doctor policy - the completed run becomes the single A08 entry, and a provider payload query closes on it as `current` - invalid UTF-8 in a source file yields `process_failed`, the failed run is retained for audit, the index keeps pointing at the last completed run, and the failure is classified `non_completed` in the diagnostics - an invalid repository path returns one concise line with no source location The manifest is now reached through the marker rather than by name, so the test fails if the marker ever stops binding it. This test now runs on ubuntu and macos too, where the PowerShell version never did — the campaign wants those lanes first-class (#53), so CI proving it is the point rather than a side effect. Refs #78, #47
…f host toolchain state Two follow-ups on the port, both found by CI. **Coupling.** The self-scan failed with `coupling_increased` (45.64 -> 45.67). Deleting a 198-line PowerShell file removes a low-coupling node from a repository-wide average, so the average rises. Measured both ways on this branch: with `test-stable-wrapper-e2e.ps1` restored and the same Rust changes in place, coupling moves *down* to 45.48 and the gate passes. Nothing here got more coupled. Folding the test into `tests/primary_entry.rs` instead of a new file halved the delta (45.73 -> 45.67) but could not remove it, because the cause is the deletion, not the addition. The baseline is re-saved; no threshold in `rules.toml` moved, only the comparison point. Expect this on every batch that deletes a PowerShell file — that layer has been diluting this average, and retiring it makes the remaining Rust average look worse without any code getting worse. **Host toolchain.** The test now tolerates a doctor-only domain failure the way `dag_run.rs` already does: the default route passes the doctor no flags, so on a machine missing a pinned tool the failure describes the host, not the wrapper. CI installs ripgrep and ast-grep pinned, so the assertions still run where it counts; every other failure still fails the test. Verified: `cargo test` 2632 passed / 45 suites, `cargo fmt --check` clean, retirement packet suite 8 packets + 2 audits, and a local self-scan whose hospital triage is now green (`clean snapshot`, no failing rules). Refs #78, #47
… causes The skip condition swallowed every doctor domain failure. `doctor_adapter.rs`'s `diagnosis` emits three distinct causes and only two of them describe the machine: bootstrap readiness and provider conformance. The third, manifest reconciliation, is about this repository's own orchestration manifest, so a regression there was being tolerated as if a tool were missing. The tolerance now requires the failure to name one of the two host causes, to not name manifest reconciliation, and to be the only domain failure in the run. Refs #78
cdf83c8 to
0299c98
Compare
… a speed budget `wait_record_pair` killed its two child processes after ten seconds of wall clock. That deadline exists to catch a store-lock deadlock, not to assert how fast `decision record` runs, and ten seconds is not a deadlock — it is a busy machine. The two-core Windows runner failed on it while the rest of the suite, now including the ported wrapper E2E that drives the whole pipeline twice, ran alongside it. Sixty seconds still catches a deadlock and stops reporting load as a defect. Refs #78
Install-MissingTool 的判据一直是「命令在不在 PATH 上」,不是「版本对不对」。 Get-Command 找到工具就记 already_present 并 return,那个 $Installer scriptblock 永远不会被调用。对 repowise 来说这意味着 `repowise==0.36.0` 这个 pin 从来没有在 一台装过 repowise 的机器上生效过——本机实测 0.32.0,落后 pin 四个 minor,而安装 报告与一台正确的机器完全一样。能力(Invoke-PipInstall 支持精确版本)早就有了, 闸门没加。 Get-InstallMetadata 现在带 pinnedVersion;新增 Get-ToolVersion 读工具自报版本; 不匹配报 version_drift,-InstallMissing 下报 upgraded / upgrade_failed。没有 pin 的工具行为完全不变。 探测遵守 crates/code-intel-cli/src/tool_path.rs 为本项目定下的启动规则("only ever launches by absolute path"、"relative PATH entries are skipped outright"): Test-ToolVersionProbeAllowed 拒绝非 rooted、不存在、或脚本类的源,因为 PATH 上的 repowise.ps1 会被 `& $Source` 在安装器自己的进程里执行。被拒绝不等于探测失败—— 回落到原本的 presence-only 行为,所以一个不可验证的源永远无法诱发重装。子进程用 Start-Process -PassThru -Wait 启动并读它自己的 ExitCode,而不是读 $LASTEXITCODE (只有原生命令会设,否则要么读到陈旧值,要么在 StrictMode 下抛错中止整个安装器)。 只解析 stdout,并在知道工具名时锚定匹配,所以 banner 里的 `setuptools 3.11.0` 既不能伪造通过也不能伪造漂移。 确认的漂移现在会让安装失败。ok 只由 checks 计算,所以只进 installActions 的状态 对所有消费者都不可见——bootstrap-new-machine.ps1 只读 installResult.ok,一台漂移 的机器本会报 Install OK: True。Add-VersionComplianceChecks 从 actions 派生 version:<tool> check。探测被拒或读不出时该 check 不 required:不确定要被看见,但 不能因为一个没测出来的版本让安装失败。 code-intel --version(含 -V 与 --version --json / code-intel-version.v1):装机的 二进制此前无法报告自己是什么。bin/repo.json 记的是安装器从哪跑的,不是它产出了 什么,所以一台跑着旧构建的机器和一台当前的看起来完全一样——实测一个 v0.6.0 的装机 二进制跑 snapshot identity 要 10.9s,含 git cat-file --batch 修复的构建是 0.28s, 而机器上没有任何东西能分辨这两者。这是自报的构建身份,不是 provenance;安装器 记录的 sha256= 才是。 测试按 #78/#80 的方向落在 Rust 侧:driver 由测试生成到临时目录,仓里不新增 .ps1 (AGENTS.md)。12 个场景覆盖解析格式、拒绝规则、banner 噪音、漂移/升级/升级失败、 合规 check 派生,以及真实 Get-InstallMetadata switch 确实带着 pin——最后这条是 regression-proof:删掉那一行,只有它会失败,其余全过。 Refs #59
批次 2。切
test-stable-wrapper-e2e.ps1(ci L263)。为什么不能直接删步骤
它从来没测 PowerShell。每条断言都是关于编译出的二进制:无子命令的默认路线、发布的
*-corerun、失败 run 在权威索引里的待遇、以及打给人看的摘要行。但 Rust 侧没有覆盖那些摘要行——
[PASS]/[FAIL]/Outcome:/Cause:/Run evidence:由main.rs打印,没有任何测试断言过。直接删步骤等于静默丢掉二进制自身用户可见输出的唯一覆盖。做法
逐条搬进
tests/primary_entry.rs——主入口行为本来就是它的地盘,不新开文件:evidence.graph/evidence.sentrux/diagnosis.hospital三个节点全部 succeeded + passcurrent收口process_failed,失败 run 保留待审计,索引仍指向上一个 completed,诊断里被分类为non_completedroot_entry_rejects_a_missing_repository_with_usage_exit_code)manifest 改为经 marker 取路径而非按名字取,marker 哪天不再绑定它,测试就会红。
doctor 容忍:
doctor_adapter.rs::diagnosis发三种 cause,只有bootstrap readiness failed和provider conformance failed描述的是宿主工具,而这条路线不给 doctor 传任何 flag。第三种manifest reconciliation failed是本仓自己的 orchestration manifest 状态,绝不容忍。跳过条件要求:命中前两种之一、不含第三种、且整个 run 只有这一个 domain failure。CI 装了 pinned rg / ast-grep,断言仍在该生效的地方生效。这个测试现在也会在 ubuntu / macos 上跑,PowerShell 版本从来没有。#53 要的就是这两条 lane 一等公民。
关于 coupling
本 PR 早前一版曾因删 PS1 触发
coupling_increased而重存过 baseline。#81 把 coupling 口径改成只算 import-modelled 语言,从根上解掉了这个对立,所以那次重存已 rebase 掉——本 PR 不再改动任何.sentrux/状态。rebase 后本地闸门:[coupling_basis] 143 of 238 files in import-modelled languages,Coupling 74.41 → 74.41,No degradation detected。没切的三条(分类见 #78)
test-atomic-capability-contract.ps1—— 41 条断言校验 schema / contract 常量 / registry policy / toolchain digest,需逐条比对tests/capability_exec.rs,单开一批test-project-management-support.ps1—— 被tests/internalization_record.rs:1490当作三个 advisory 记录的local-boundary-test-sha256边界证据,删前须 re-pointcheck-hardcoded-paths.ps1—— 是 lint 工具不是测试验证
cargo test2668 passed / 45 suitescargo fmt --all -- --check干净test-retirement-packets.ps1:8 packets + 2 audits 全 PASSsentrux gate无退化同时把
test-stable-wrapper-e2e.ps1从两处 PowerShell parser 检查清单里摘掉,并更新docs/ps1-exit/contract-inventory.md的-SkipRepowise行。Refs #78, #47