Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,11 @@ jobs:
# cannot see this topology either.
cargo test -p code-intel --test install_smoke --locked packaged_install_deploys_legacy_pipeline_entrypoint -- --ignored --nocapture
if ($LASTEXITCODE -ne 0) { throw "packaged legacy-pipeline-entrypoint install smoke failed with exit ${LASTEXITCODE}" }
# #394: prove packaged legacy sessions use the installed native
# metrics engine and leave canonical and lite baselines untouched.
cargo test -p code-intel --test install_smoke --locked packaged_install_legacy_sessions_use_native_metrics_and_preserve_baselines -- --ignored --nocapture
if ($LASTEXITCODE -ne 0) { throw "packaged legacy-session install smoke failed with exit ${LASTEXITCODE}" }


- name: Packaged Sentrux capability closure smoke
shell: pwsh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Follow-up fix commit: `aa628e1 fix(cli): complete method selection and proposal
- crates/code-intel-cli/src/design_proposal_contract.rs
- Shared payload parser, shape validators, catalog binding, and error formatting. No validation rule was relaxed.
- crates/code-intel-cli/tests/artifact_ref.rs
- Updates the stale implementation digest 5090efd13c07531c249637d8e5857f0d13f3ecb8f0d02fb6e858747ea7d8c3d8 to 264ed4390fbf70e6d1eaf0365f318b8587e4d2d88aa38dd344e9a0a9fbcc35cc.
- Updates the stale implementation digest 5090efd13c07531c249637d8e5857f0d13f3ecb8f0d02fb6e858747ea7d8c3d8 to 5eb359eee6c1944c8943c5f9b5e257d43e9661314ba7c8eda24e62709e94b352.
- orchestration/method-selection-rules.v1.json
- Adds rules for legacy-characterization-test, legacy-seam-extraction, and refactor-small-step using each card's declared signals and contraindications.
- orchestration/schemas/code-intel-design-proposal-candidate.v1.schema.json
Expand Down
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
gate in the same PR (DR-0001). 3794 checkout-topology tests missed every
installed-topology bug that shipped with v0.7.0; only the topology gate
catches this class.
- This checkout's Windows host is isolation-excluded while issue #403 is open. Do not run
`cargo build`, `cargo test`, `cargo check`, `cargo clippy`, `cargo run`, or `cargo nextest`
here, and do not run `cargo clean`; the suite requirement under Verification is satisfied on
another host or in CI instead. Read-only source, `gh`, and `git` work is unaffected. See
`docs/decisions/DR-0013-affected-host-compilation-isolation.md`.

## Language direction

Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **`scan.ast-grep-security`:原创 ast-grep 安全规则库 + advisory-only 扫描能力**(#345)。`orchestration/ast-grep-rules/<lang>.yaml` 覆盖本管线自身识别的 7 种语言(python/javascript/typescript/go/rust/java/csharp),每语言一份独立编写的 security 规则文件(SQLi、命令注入、eval/exec、不安全反序列化、硬编码密钥、弱哈希等常见 CWE 类别),规则概念来源于 vitali87/code-graph-rag 的规则分类思路但**不 vendor 其源文件**(`orchestration/internalization/ast-grep-security-rules.json` 记录 reimplement rung 与 MIT 义务)。新 capability 走 CLI 版 `ast-grep scan --rule`,产出 `code-intel-ast-grep-security-findings.v1` artifact,`authority.mode: advisory_only`,从不进 `get_gate_verdict`、从不提议改写;MCP 新增第 7 个工具 `scan_security_findings`。
- **`code-intel retirement guard`:合规退役 gate 首次带执行牙齿**(#344)。此前 E00/E01 只产出证据与决策、"从不删代码",没有东西挡住一次普通提交在退役决策仍是 `blocked` 时删除某条已追踪 legacy 分支的代码——`orchestration/retirements/e09-doctor-wrapper` 记录了正是这一实例(`deletionExecuted=true` 但从未获得 E00 批准)。新 guard 接进 CI,紧跟既有 PS1 retirement-packet 套件之后:对每个 `status.json` 未标 `retired: true` 的 packet,复用它自己 `compatibility-retirement-deletion-diff.json` 里记录的 `deletedLines` 做"存在性 oracle"——若某文件全部 hunk 都已从树上消失而 packet 仍称未退役,即命中 E09 模式并使构建失败;仅部分 hunk 消失不触发(e05-publication 的既有测试本就承认这种"marker 已删、staging 仍在"的容忍态)。首次真实跑通即在本仓发现第二例同型未记录退役(e03-provider-preflight),暂记入 `known_findings()` 白名单,后续需补证据物与更新 PS1 测试器。
- **`code-intel verify`:单命令聚合 lint/gate/repin 三闸**(#367/#368)。新增 `code-intel verify <path> [--json]`,把 `lint hardcoded-paths`、`sentrux gate`(ratchet 模式,`save=false`,绝不写 `.sentrux/baseline.json`)、`repin` 的新 check-only 入口(`repin::run_check`,绝不 `--write`)合成一次调用,免去 agent/orchestrator 手动依次跑三条;`cargo test` 故意排除在外(整工作区量级不同)。退出码分层:`0` 全清、`1` 真发现违规、`64` 用法错误、`74` 某子检查引擎自身没跑起来(fail closed,绝不折算进假 `ok`)。
- **huashu-flash measurement ratchet**:新增 `measurement.flash-ratchet`,失败样本不进入分位数;将 5% 容差写入 ceiling,仅更低的 p75 才收紧上限,配对测量要求交替采集;样本、ceiling、报告各有独立 JSON Schema(DR-0012)。

### Fixed

- `verify` 和 `repin` 的 Git 测试夹具显式隔离全局忽略文件,避免 `.sentrux/` 或 `*.bin` 被开发机配置排除后导致空提交或遗漏测试文件(#393)。
- `sentrux` 的模块归属计算借用路径切片,不再为每条边创建临时路径数组和模块字符串;模块度聚合保留原有遍历顺序与评分公式(#393)。
- Legacy Sentrux session gates now forward to the compiled engine and keep their
baseline in `.sentrux/cache/native-session-baseline.json`; canonical and lite
baselines are never read as session metrics or overwritten. Incompatible
baselines report their actual engine/schema instead of a fabricated quality
regression. Session tests exercise the real engine and process-error boundary
rather than copied metric implementations (#394).

- `sentrux gate` 在全新 checkout 上因缺基线硬崩溃:missing-baseline 前置检查原本查的是 native baseline 路径,实际 `sentrux gate` 读的是 lite 引擎的 `.sentrux/cache/lite-baseline.json`,现已对齐,缺失时正确落回 `manual_required`(fixes #322)。
- 修复 workflow recommendation 的 Rust 侧 parity 回归(#314)。
- `sentrux_gate` 全量并行测试踩踏两处根因分开修:(1) `tool_path.rs` 的 `path_search_skips_relative_entries` 探测目录名只用 `module_path!()`,在被 `#[path]` 编入多个 `cargo test` 二进制(`run_commit`/`survival_scan` 等)时对同名父模块编译时相同,跨进程共享同一 `target/tool-path-*` 目录并互相踩踏;现补上 `std::process::id()` + 进程内 `AtomicU64` 计数器,与 #175 的 `unique_temp_dir()` 同一套 pid+nonce 写法(fixes #178)。(2) `sentrux_gate.rs`/`boundary_rules_tests.rs` 里 9 处 `run_check(...).expect(...)`/`run_gate(...).expect(...)` 把"引擎子进程没跑起来"和"仓库真的检测到规则违规"报成同一个红灯;新增仅测试用的 `expect_check_ran`/`expect_gate_ran` helper,`Err` 分支 panic 出明确区分于业务断言的文案,并配 `#[should_panic]` regression 测试直接执行 `Err` 路径验证文案本身(fixes #192)。
Expand Down
18 changes: 18 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,24 @@ _Avoid_: Tool type, permission prompt, implementation language
**Domain Verdict**: Evidence judgment returned by a completed capability: pass, fail, unknown, or not applicable. It is independent of process execution status.
_Avoid_: Exit code, exception, health score

**Measured Operation**: One named, repeatable thing a caller asks to have measured. Opening a page, running a test command, timing a CLI invocation, and reading a binary size are the same kind of thing with different names.
_Avoid_: Page, benchmark suite, delivery path

**Measurement Sample**: One finite number the caller collected for a Measured Operation. The pipeline does not produce it and does not run the operation.
_Avoid_: Timing event, trace interval, observation row

**Sample Group**: The Measurement Samples from one side of a comparison, at least ten finite numbers, summarized as p50, p75, and p95. A failed attempt is recorded with its reason and is not a Measurement Sample.
_Avoid_: Average, single timing, baseline trace

**Flash Ratchet**: The monotonic ceiling for one Measured Operation and one metric, taken from huashu-flash. A new Sample Group may hold it or tighten it. A p75 worse than the ceiling by more than five percent is a Domain Verdict of fail. The ceiling never authorizes publication or deployment.
_Avoid_: Performance budget, schedule commitment, Light-Speed Baseline

**Ratchet Ceiling**: The published record of the best p75 a Flash Ratchet has accepted, together with the metric name and the tolerance used to judge it. The tolerance is five percent and is read from the submitted record. The caller submits the previous record; a check writes the next record into its own report and leaves the previous record unchanged.
_Avoid_: In-repo JSON file, budget comment, code constant

**Paired Comparison**: An optional second Sample Group plus the order in which the two groups were collected. The order must strictly alternate. When it does, the report states the fractional drop in p75 from the first group to the second. Any other order is rejected and states no drop.
_Avoid_: Unpaired rerun, required benchmark mode, a drop computed across separate sessions

**Run Commit**: Transactional publication boundary that promotes validated staged artifacts and writes `run-complete.json` last.
_Avoid_: Git commit, timestamp directory, successful subprocess

Expand Down
74 changes: 74 additions & 0 deletions autoresearch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FIXTURE="$(mktemp -d "${TMPDIR:-/tmp}/codenexus-bench.XXXXXX")"
OUT="$FIXTURE/context.json"
trap 'rm -rf "$FIXTURE"' EXIT

mkdir -p "$FIXTURE/src" "$FIXTURE/src/target" "$FIXTURE/src/.git" "$FIXTURE/src/node_modules"
cat > "$FIXTURE/src/large.rs" <<'EOF'
// deterministic large source fixture
pub fn alpha() { println!("alpha"); }
pub fn beta() { println!("beta"); }
pub fn gamma() { println!("gamma"); }
pub fn delta() { println!("delta"); }
pub fn epsilon() { println!("epsilon"); }
pub fn zeta() { println!("zeta"); }
pub fn eta() { println!("eta"); }
pub fn theta() { println!("theta"); }
EOF
cat > "$FIXTURE/src/medium.ts" <<'EOF'
export function medium() {
return "medium";
}
EOF
cat > "$FIXTURE/src/small.py" <<'EOF'
def small():
return "small"
EOF
cat > "$FIXTURE/src/target/generated.rs" <<'EOF'
pub fn generated() { panic!("must be excluded"); }
EOF
cat > "$FIXTURE/src/.git/ignored.rs" <<'EOF'
pub fn ignored() { panic!("must be excluded"); }
EOF
cat > "$FIXTURE/src/node_modules/vendor.js" <<'EOF'
module.exports = "must be excluded";
EOF

cargo run --quiet --release --manifest-path "$ROOT/Cargo.toml" -- \
codenexus generate \
--repo "$FIXTURE" \
--target "$FIXTURE/src/.." \
--out "$OUT" \
--observed-at 0 \
--max-files 2 \
--max-references-per-file 2

node - "$OUT" <<'NODE'
const fs = require('fs');
const file = process.argv[2];
const doc = JSON.parse(fs.readFileSync(file, 'utf8'));
const selected = (doc.files || []).map((entry) => entry.path);
const refs = (doc.files || []).reduce((sum, entry) => sum + (entry.references || []).length, 0);
const forbidden = selected.filter((name) => /(^|\/)(work|artifact|artifacts|staging|\.code-intel|\.git|node_modules|target|dist|build|\.venv|__pycache__)(\/|$)/i.test(name));
const path_rendering = selected[0] === 'src/large.rs' && (doc.files || []).every((entry) =>
(entry.references || []).every((reference) => !reference.includes('//?/') && !reference.includes('\\?\\')),
);
const checks = [
doc.tool === 'codenexus-lite',
doc.generatedAt === '1970-01-01T00:00:00.000Z',
selected.length === 2,
path_rendering,
forbidden.length === 0,
refs <= 4,
];
if (refs > 4) throw new Error(`reference bound exceeded: ${refs}`);
const quality = checks.filter(Boolean).length;
console.log(`METRIC codenexus_context_quality=${quality}`);
console.log(`METRIC codenexus_generated_path_leaks=${forbidden.length}`);
console.log(`METRIC codenexus_context_files=${selected.length}`);
console.log(`METRIC codenexus_reference_matches=${refs}`);
console.log(`METRIC codenexus_context_bytes=${fs.statSync(file).size}`);
NODE
49 changes: 49 additions & 0 deletions crates/code-intel-cli/src/artifact_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ pub(crate) fn registered_contract(artifact: &Value) -> Result<ArtifactContract,
.or_else(|| advisory_family_contract(schema, artifact_type))
.or_else(|| retirement_family_contract(schema, artifact_type))
.or_else(|| run_delivery_family_contract(schema, artifact_type))
.or_else(|| measurement_family_contract(schema, artifact_type))
.or_else(|| method_decision_family_contract(schema, artifact_type))
.or_else(|| {
native_code_contract(schema, artifact_type).map(
Expand Down Expand Up @@ -532,6 +533,54 @@ fn run_delivery_family_contract(schema: &str, artifact_type: &str) -> Option<Art
}
}

fn measurement_family_contract(schema: &str, artifact_type: &str) -> Option<ArtifactContract> {
match (schema, artifact_type) {
("code-intel-flash-samples.v1", "measurement.flash-samples") => Some(ArtifactContract {
artifact_schema: "code-intel-flash-samples.v1",
artifact_type: "measurement.flash-samples",
max_bytes: 8 * 1024 * 1024,
validate_payload: validate_flash_samples,
}),
("code-intel-flash-ratchet-ceiling.v1", "measurement.flash-ratchet-ceiling") => {
Some(ArtifactContract {
artifact_schema: "code-intel-flash-ratchet-ceiling.v1",
artifact_type: "measurement.flash-ratchet-ceiling",
max_bytes: 64 * 1024,
validate_payload: validate_flash_ceiling,
})
}
_ => None,
}
}

fn validate_flash_samples(bytes: &[u8]) -> Result<(), String> {
let value = parse_contract_json(bytes, "flash samples")?;
if value["schema"] != "code-intel-flash-samples.v1" {
return Err("flash samples schema mismatch".into());
}
Ok(())
}

fn validate_flash_ceiling(bytes: &[u8]) -> Result<(), String> {
let value = parse_contract_json(bytes, "flash ratchet ceiling")?;
exact_object_keys(
&value,
&[
"schema",
"operation",
"metric",
"direction",
"tolerance",
"p75",
],
"flash ratchet ceiling",
)?;
if value["schema"] != "code-intel-flash-ratchet-ceiling.v1" || value["direction"] != "lower" {
return Err("flash ratchet ceiling is not a lower-is-better record".into());
}
Ok(())
}

fn method_decision_family_contract(schema: &str, artifact_type: &str) -> Option<ArtifactContract> {
match (schema, artifact_type) {
("code-intel-method-catalog.v1", "method.catalog") => Some(ArtifactContract {
Expand Down
2 changes: 1 addition & 1 deletion crates/code-intel-cli/src/capability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::artifact_ref::{self, VerifiedArtifact};
mod content_contract;
pub(crate) use content_contract::{
is_digest, is_run_identity, reject_duplicate_json_keys, require_exact_keys, sha256_hex,
validate_artifact_ref_shape, MAX_JSON_BYTES,
validate_artifact_ref_shape, Sha256, MAX_JSON_BYTES,
};

const ZERO_DIGEST: &str = "0000000000000000000000000000000000000000000000000000000000000000";
Expand Down
3 changes: 3 additions & 0 deletions crates/code-intel-cli/src/capability_inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub(crate) mod design_proposal;
// Crate-visible so `doctor bootstrap --require-provider-conformance` can reuse
// the node's own provider rows instead of restating the predicate.
pub(crate) mod doctor_adapter;
#[path = "flash_ratchet.rs"]
mod flash_ratchet;
#[path = "hospital_diagnosis.rs"]
mod hospital_diagnosis;
#[path = "native_code_evidence.rs"]
Expand Down Expand Up @@ -112,6 +114,7 @@ pub(crate) fn execute(
"delivery.light-speed-measure.compat" => {
delivery_light_speed::execute(request, verified_inputs, out)
}
"measurement.flash-ratchet.compat" => flash_ratchet::execute(request, verified_inputs, out),
"advisory.design-proposal.compat" => {
design_proposal::execute(request, verified_inputs, out)
}
Expand Down
1 change: 1 addition & 0 deletions crates/code-intel-cli/src/cli/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,7 @@ Commands:
lint hardcoded-paths [<repo-path>] [--json]
route|routes [--action List|Plan|Validate] [--provider repowise|understand] [--operation <name>] [--repo <path>] [--json]
sentrux <dsm|scan|health|check|gate|check_rules|gate_save|hotspots> <path> [--no-ratchet]
sentrux <session_save|session_gate> <path> (isolated .sentrux/cache/native-session-baseline.json; never replaces canonical baseline)
sentrux capabilities [<path>] [--json] (read-only capability matrix audit)
(--no-ratchet: `check` only, skip the .sentrux/baseline.json ratchet)
capability exec <id> --request <request.json|-> --out <staging-dir> [--artifact-root <directory>] [--manifest <integrations.json>]
Expand Down
Loading
Loading