dashboard-concurrency-guard、dashboard-safety-ack-required、deactivate-reviewer-ack-required(各 5/5 PASS)| PR | 類型 | 內容 |
|---|---|---|
| #46 | fix | retrospective audit fixes(PR #46 內補 3 個 spec drift) |
| #47 | docs | PR-A spec realignment + audit correction(Layer 0/7/8 spec 註記 + audit Layer 4 標 PASS) |
| #48 | fix | PR-B safety + privacy(Layer 5 safety metadata、evidence_ref_omitted_upstream、Layer 8 deactivate ack、Layer 0 env guard、active_path_summary redact) |
| #49 | feat | PR-C Layer 3 typed evidence + reflect/recall 路徑分離 + dedupe canonical + rule_version namespace split |
| #50 | feat | PR-D Layer 6 dashboard 升級到 spec(wire model、envelope、detail view、XSS hardening、file split) |
| #51 | feat | 新 eval scenarios: safety_ack + deactivate ack |
| #52 | fix | PR-E Layer 5 validator hardening(7 dead rejection codes + batch_hash check + rejection-on-missing-manifest) |
| #53 | feat | PR-F Layer 4 daemon failure manifest(transport_error / timeout / cli_not_found→transport_error) |
| Scenario | Trials | Verdict | 對應 PR |
|---|---|---|---|
dashboard-concurrency-guard | 5/5 PASS | SHIP | PR-D Layer 6 optimistic concurrency |
dashboard-safety-ack-required | 5/5 PASS | SHIP | PR-D Layer 6 safety_ack gate |
deactivate-reviewer-ack-required | 5/5 PASS | SHIP | PR-B Layer 8 Blocker #3 |
| 狀態 | 檢查項目 | 證據 |
|---|---|---|
| PASS | shouldObserve() 串接 ARCFORGE_OBSERVE_SKIP_PATHS | hooks/observe/main.js:61-73 |
| 已修 (PR-B) | ARCFORGE_OBSERVE_EXPLICIT_SKIP=1 guard | main.js:80 |
| 已修 (PR-B) | ARCFORGE_OBSERVE_SELF_ANALYSIS=1 guard | main.js:81 |
| PASS | Eval-trial 路徑 regex | main.js:57-58 |
| PASS | Disabled-by-default + fail-closed | learning.js:75-76 |
| 已 codified (PR-A) | Spec 寫入 env var 正式命名 | layer-0-*.md:39-48 |
| first-slice accept | Daemon spawn 自己 claude 沒 export SELF_ANALYSIS=1(dev plugin disabled 緩解) | defer to v2 |
| 狀態 | 檢查項目 | 證據 |
|---|---|---|
| 已修 (#46) | Skeleton 必填欄位 schema_version + source | main.js:408-420 |
| PASS | 不持久化 raw tool_input / skill args | main.js:431-440 |
| PASS | PostToolUse 只記 outcome + output_bytes | main.js:447-453 |
| PASS | Per-tool collection contract(全 10 tool) | main.js:157-294 |
| PASS | Append errors 不 crash session(silent catch) | main.js:470-472 |
| first-slice accept | observation.skill 在 pre+post 都設(spec 只描述 tool_start) | low impact |
| 狀態 | 檢查項目 | 證據 |
|---|---|---|
| PASS | EVIDENCE_STATUS 凍結 + 4 值 | sanitize-observation.js:174-179 |
| PASS | Decision 5 全 keyword + value form 覆蓋 | sanitize-observation.js:30-94 |
| PASS | Per-tool persistence contract(Bash/Read/Edit/Write/Grep/Glob/NotebookEdit/Skill/Web/PostToolUse) | main.js:198-291 |
| PASS | 欄位名 operation_kind | 全 9 處正確 |
| PASS | summarizeToolInput read-time only | learning-observation-view.js |
| PASS | Fail-closed: raw fallback 用 OMITTED_NO_INPUT | main.js:435-440 |
| PASS | 無 raw-fallback;sanitizer always applied | 全 per-tool branches |
| first-slice accept | WebSearch 把 query 寫進 url 欄位(命名小不一致) | low impact |
| 狀態 | 檢查項目 | 證據 |
|---|---|---|
| 已修 (PR-C) | Reflect + Recall 已讀 — MAX_REFLECTS=10, MAX_RECALLS=10 | batch-assembler.js:35-36, 469-475 |
| 已修 (PR-C) | Diaries 回傳 DiaryEvidenceItem[] | :177-215 |
| 已修 (PR-C) | source_windows.{diaries,reflects,recalls} 寫 manifest | :584-595 |
| PASS | readRecentEvidence(kind, ...) 三合一 helper | :146-219 |
| 已修 (PR-C) | 新 reader:~/.arcforge/reflections/ + ~/.arcforge/recalls/ 分離儲存 | :57-63 |
| PASS | One-way(不讀 Layer 5-8) | 無相關 import |
| PASS | Manifest 持久化路徑正確 + atomic | :555, 617 |
| PASS | Safety raw_*_included: false + sanitizer_policy_version | :522-531 |
| 已修 (PR-B) | evidence_status_by_id 持久化(給 Layer 5 omitted_upstream 用) | :610-612 |
| 已修 (PR-E) | evidence_type_by_id 持久化(給 Layer 5 evidence_type_mismatch 用) | batch-assembler.js |
| PASS | batch_id + batch_hash deterministic format | :485, 540 |
| PASS | 記錄 path-separated 操作(reflect/recall 不再循環餵回) | spec §1.1 設計 |
| 狀態 | 檢查項目 | 證據 |
|---|---|---|
| PASS | Daemon 不直接讀 observations.jsonl 內容 | observer-daemon.sh:97-105 |
| PASS | Bash daemon + Node CLI 分工 | :158, 296 |
| PASS | body_source: "llm_curator" 三層強制 | prompt + ingestor + validator |
| PASS | First-slice allowed_artifact_types: ["instinct"] | observer-prompt.md:18, 70, 102 |
| 已修 (PR-A) | sanitizer_module 在 metadata 不在 prompt 文字(audit 措辭修正) | proposal-ingestor.js:175 |
| 已修 (PR-C) | observer-prompt 改用 4 種 evidence_type cite | observer-prompt.md:34-40 |
| PASS | Failure modes 不建 queue state | proposal-ingestor.js:330-372 |
| 已修 (PR-F) | CuratorRunManifest 在 daemon transport/timeout/cli_not_found 失敗時都會寫 | proposal-ingestor.js:575-614 + observer-daemon.sh:287-321 |
| 已修 (PR-F) | 新 record-run-failure CLI subcommand | cli.js:118-155 |
| 已修 (PR-F) | last_was_timeout flag 防止 duplicate failure manifest | observer-daemon.sh:292-294 |
| 狀態 | 檢查項目 | 證據 |
|---|---|---|
| 已修 (PR-B) | Full safety metadata — 3 versions + 3 scans + 6 raw flags | proposal-ingestor.js:172-185 |
| 已修 (PR-B) | evidence_ref_omitted_upstream emit | proposal-ingestor.js:437-456 |
| 已修 (PR-C) | Canonical dedupe_basis + superseded transition | proposal-ingestor.js:188-212, 478-489 |
| 已修 (PR-C) | rule_version namespace 分離(sanitizer vs evidence-quality) | schema.js:535 |
| 已修 (PR-E) | artifact_type_not_allowed emit(之前 collapse to schema_invalid) | schema.js:200, 530 |
| 已修 (PR-E) | scope_not_allowed emit | schema.js:216, 531 |
| 已修 (PR-E) | evidence_type_mismatch emit | proposal-ingestor.js:490 |
| 已修 (PR-E) | too_few_evidence_refs + too_many_evidence_refs(MIN=2, MAX=5 pin 到 prompt) | schema.js:314, 320 |
| 已修 (PR-E) | source_hash_mismatch emit — batch_hash round-trip check | proposal-ingestor.js:386-395 |
| 已修 (PR-E) | source_manifest_missing rejection(不再 throw) | proposal-ingestor.js:291-292 |
| PASS | INSERTION_STATUSES + isLegalInsertionStatus() guard | lifecycle.js:51-58 |
| PASS | VALIDATOR_VERSION + EVIDENCE_QUALITY_RULE_VERSION 常數 | schema.js:18, 535 |
| PASS | Body source 4-value enum | schema.js:26 |
| PASS | promoted_from_* 在 scope 上拒收 | schema.js:214-228 |
| PASS | Action × Status matrix 8×7 | lifecycle.js:79-88 |
| PASS | applyTransition 對 promote/evolve throw | lifecycle.js:128-134 |
| PASS | Evidence-quality v1 formula | schema.js:74-86 |
| PASS | Atomic queue + rejections + lock | queue-writer.js:51-117 |
| PASS | Replay 容忍 corrupted trailing line | queue-writer.js:270-277 |
| 狀態 | 檢查項目 | 證據 |
|---|---|---|
| 已修 (PR-D) | Wire model 加 evidence_quality_chip + relationships | learning-dashboard.js:109-112, 125, 145 |
| 已修 (PR-D) | evidence_counts {total, by_type} | :90-98, 139 |
| 已修 (PR-D) | risk_note_count + uncertainty_note_count | :140-143 |
| 已修 (PR-D) | expected_current_status optimistic concurrency → HTTP 409 | :370-374 + http.js:144-146 |
| 已修 (PR-D) | safety_ack 必填 activate/deactivate | :382-393 |
| 已修 (PR-D) | actor 預設 + reason 寫 audit | :317, 345 |
| 已修 (PR-D) | Detail view 4 個 block: evidence_summaries / llm_assessment / materialization / activation | :175-205 |
| 已修 (PR-D) | Detail blocks 全走 sanitizer(無 secret leak) | :215-246 |
| 已修 (PR-D) | HTML XSS-safe(0 innerHTML,全 textContent/createElement) | learning-dashboard.html:97-285 |
| 已修 (PR-D) | File size 拆分 — dashboard.js 559 + http.js 197(< 700 hard limit) | file sizes |
| PASS | Privacy invariant — 4 adversarial fixtures redacted | tests:253-313 |
| PASS | project_id 從 wire model 剔除 | :80-88 |
| PASS | Server-side Action × Status matrix 強制 | :377-379 |
| PASS | actions.jsonl audit log(accept + reject) | :270-278 |
| PASS | Layer 6 不 call LLM、不寫 skill、不寫 CLAUDE.md | 無相關 import |
| PASS | Promote 建新 global candidate,source 狀態不變 | :397-423 |
| PASS | Token-gated POST(24-byte random) | http.js:66-70 |
| SHIP | Eval: dashboard-concurrency-guard 5/5 PASS | 已執行 |
| SHIP | Eval: dashboard-safety-ack-required 5/5 PASS | 已執行 |
| 狀態 | 檢查項目 | 證據 |
|---|---|---|
| 已 codified (PR-A) | render_policy.include_evidence_summaries: false 寫進 spec | materialize.js:84 + layer-7 L128-135 |
| PASS | 只接受 approved + deactivated | materialize.js:327-330 |
| PASS | 只寫 inactive draft(無 active path) | materialize.js:56-66 |
| PASS | Path-containment 防逃逸 | :399-403 |
| PASS | MaterializationRecord 先寫完再回報 Layer 5 | :464-468 |
| PASS | Atomic + lock-protected | :380, 406, 464, 478 |
| PASS | Idempotent on (hash, policy_version) | :260-288, 361-371 |
| PASS | Body secret scan(strict equality) | :355-358 |
| 狀態 | 檢查項目 | 證據 |
|---|---|---|
| 已修 (PR-B) | deactivate() 驗 reviewer_ack(shared helper) | activate.js:197-203, 266, 481 |
| 已修 (PR-B) | active_path_summary 不洩 project_id(sha256[:12]) | :211-213, 372, 527 |
| 已 codified (PR-A) | Spec 寫入 redaction rule | layer-8 L251-269 |
| 已 codified (PR-A) | Spec 寫入 hash-verify 順序等價 | layer-8 L271-273 |
| PASS | 只接受 materialized + deactivated | :255-258 |
| PASS | Materialization record hash check | :290-298 |
| PASS | Activate 路徑要求 reviewer_ack | :266-269 |
| PASS | Per-target-kind overwrite policy | :86-93, 343-358 |
| PASS | claude_md_addition 不自動 apply(double block) | :271-280 |
| PASS | Allowed roots allowlist + path-resolve containment | :303-326 |
| PASS | Atomic write + lock + supersede backup | :331-359 |
| PASS | ActivationRecord 先寫完再回報 Layer 5 | :419-424, :562-568 |
| PASS | SessionStart 不 auto-load instincts | inject-context.js:271-273 + e2e test |
| PASS | 失敗不建 activated event | fail() 在 transition 前 return |
| PASS | Hash 算一次重用(PR-B simplify) | :366, 372 |
| SHIP | Eval: deactivate-reviewer-ack-required 5/5 PASS | 已執行 |
整體 PASS 率 100%(82/82 layer 項)。
Spec realignment complete。後續若有新 layer 變更,這份 final report 可當基準。
evidence-ref-omitted-upstream、dedupe-superseded-transition、typed-evidence-cite-chain)— 已有 unit test 守ARCFORGE_OBSERVE_SELF_ANALYSIS export — dev plugin disabled 緩解llm_assessment propagation + evidence_quality_metadata.basis 其他欄位 — spec 標 optional