[CLAUDE] Docs: Harness-11 double-check ×2 + finalize report (anh giao)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
- DOUBLE-CHECK wf_a0b68d2f-30e (3× reviewer): committed-state e70c046 PASS — B1 ×11 exact, root CLAUDE.md:53 tail byte-identical, broadcasts hash recompute khớp, single-writer clean. Over-suppression regression CLEAN: DA1 no-return → em-main self-gate fake-drift "99 migration" CAUGHT (runtime) + DA2/DA3 độc-lập confirm
- CHECKLIST-VERIFY wf_39cd4cbe-f07 (3× investigator-codebase): completeness-gate H11 FORMAL ĐẠT — B 4/4 + C 5/5 + D 11/11 đủ-trọn (function-floor MET), A 🟡 tailored; D5/D6/D7 explicit + D8 one-direction codify = YES
- detector refine: +C2 "test project" skip (27→26); tree-skip reverted (gotcha #30 box-glyph trap, kể cả qua Edit render-normalize); detector pure-ASCII verified
- agents/README "(pending)"→run-id; adap-report + outbox email +double-check section (hash 2316773229f2)
- 0 production code; state THẬT giữ nguyên (Mig 55 · 88 bảng · 339 test · gotcha 69 · bundle BYF5vIMJ/CB-tiRxd)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -0,0 +1,39 @@
|
||||
# CHECKLIST-VERIFY SYNTHESIS — Harness-11 (2026-06-18-h11-checklist-verify · `wf_39cd4cbe-f07`)
|
||||
|
||||
> 3× investigator-codebase (read-only ∥, evidence-mapping). Em-main scribe @P3. **VERDICT: ✅ completeness-gate H11 ĐẠT — B+C+D đủ-trọn, A 🟡 tailored.** Rà từng item bằng bằng-chứng thật (run-output/file:line), KHÔNG trí-nhớ.
|
||||
|
||||
## CL1 — PHẦN A (🟡) + PHẦN B (🔴) → PASS
|
||||
**A1-A7 PRESENT (🟡 tailored), runtime qua `memory-archive-gate.ps1`:**
|
||||
| Item | Nấc | Loại | Evidence |
|
||||
|---|---|---|---|
|
||||
| A1 byte-gate | exec+runtime | mechanized | cap 25600 echoed; flag 3 over-cap (cicd 26798·inv 31502·reviewer 38755) |
|
||||
| A2 additive MOVE | exec (design) | convention | DRY-RUN plan-only, MOVE thật = em-main D5 (no auto-move memory canonical) |
|
||||
| A3 _INDEX pointer | exec+runtime | mechanized | A7 đọc 4 _INDEX, 186 pointer |
|
||||
| A4 hysteresis 0.85 | exec+runtime | mechanized | low-water 21760 echoed |
|
||||
| A5 keep-floor 5 | exec+runtime | mechanized | WARN fired inv+reviewer (oldest-movable exhausted trước lowMark) |
|
||||
| A6 2-strike | exec / runtime-PARTIAL | mechanized | **legit-gap by-design:** cần 2× `-Apply` (DRY-RUN strike=1 WATCH, `.archive-strikes.json` absent); script self-doc [TAILOR] |
|
||||
| A7 NO-API L1-eval | exec+runtime | mechanized | **GATE PASS 186/186 resolve, 0 fail, exit 0** |
|
||||
|
||||
**B1-B4 PRESENT (🔴 floor MET), completeness B PASS:**
|
||||
- B1 ✅ 5/5 derived docs ≥1 STATUS pointer (CLAUDE.md:53/66/87 · ef-core SKILL:3/19 · skills/README:20). Caveat: residual soft-net FP (module-local "6 test"/"4 bảng Budget") — B2 tradeoff, KHÔNG B1-fail.
|
||||
- B2 ✅ readable giữ (ef-core SKILL:85-120 table inline, không pointer-soup).
|
||||
- B3 ✅ exec+runtime (C2 ran, canonical mig55/test339/gotcha69/table88 == disk, FLAG 10 stale = detect-works).
|
||||
- B4 ✅ GATED (engine:42 FLAG→em-main + git-diff backstop + D9 single-writer).
|
||||
|
||||
## CL2 — PHẦN C (🔴 MANDATE) → ĐẠT 5/5, completeness-gate CỨNG met
|
||||
26 flag, exit 0, qua `governance-detectors.ps1`:
|
||||
- C1 ✅ exec+runtime mechanized (gotcha-ref 0 broken + 13 dangling-wikilink LOW).
|
||||
- C2/B3 ✅ exec+runtime mechanized (canonical 55/339/69/88 + disk cross-check [OK] + 10 MED).
|
||||
- C3 ✅ exec+runtime mechanized (CẢ 3 fork: wave↔run-trace 15/19f · Dự trù↔Ngân sách PRO 7/6f · two-tier↔all-inherit 17/10f).
|
||||
- C4 ✅ exec+runtime mechanized (self-match=0, 5 paths excluded ALL exist, leaked=0).
|
||||
- C5 ✅ resolve 26/26 + 2-strike HONEST-scoped (convention em-main, detector stateless — KHÔNG over-claim).
|
||||
- NO-API grep 0-hit · 0-auto-write grep 0-hit.
|
||||
|
||||
## CL3 — PHẦN D (🔴) → ĐẠT 11/11, completeness-gate D PASS
|
||||
- D1 session-start.md:83 (detector) · D2 session-end.md:48 (archive-gate) · D3 ultra-on.md:35 (per-turn) · **D4 hmw.js:76-78 THROW MECHANIZED** (verify dòng throw tồn-tại ✓).
|
||||
- **D5/D6/D7 explicit-label = YES** (engine:62-69 table NHÃN-HOÁ EXPLICIT — H11 chuẩn-hoá-mới).
|
||||
- **D8 one-direction codify = YES** (engine:72 'codify mới H11' canonical→derived KHÔNG ghi ngược).
|
||||
- D9 store_memory strip MECHANIZED (grep tools-line 0-hit) · D10 file-tool-write convention (engine tự nhận Bash chưa block cứng) · **D11 byte-0-loss RUNTIME** (h910-curate md5sum+grep-Fxf 10/10 proven).
|
||||
|
||||
## TỔNG: completeness-gate H11 ĐẠT
|
||||
**B (4/4) + C (5/5) + D (11/11) đủ-trọn** = function-floor MET. **A 🟡 tailored** (A6 runtime cần 2× -Apply = legit-gap có-chủ-đích, đã self-doc). Honest residual: B1 soft-net FP (advisory), A6 runtime-partial (by-design), C3 console mojibake (display-only). KHÔNG bộ-khung nào thiếu → KHÔNG phải "áp một phần".
|
||||
@ -0,0 +1,25 @@
|
||||
# RUN — 2026-06-18-h11-checklist-verify (Harness-11 adap · CHECKLIST self-verify, anh giao)
|
||||
|
||||
> **Harness-10 FLAT run-trace** (TRACKED). 3× investigator-codebase (read-only ∥, evidence-mapping). Synthesis → `checklist-verify-synthesis.md`.
|
||||
|
||||
- **Workflow:** Harness-11 CHECKLIST formal self-verify (anh giao "workflow double check lại checklist 1 lần nữa")
|
||||
- **Mode:** hmw RUN-TRACE. Rà TỪNG item checklist H11 broadcast → chấm nấc + bằng-chứng. "Completeness-gate: bằng chứng thật, KHÔNG bằng trí nhớ."
|
||||
- **Khác double-check #1:** DC#1 = adversarial correctness/regression. Cái này = formal checklist scorecard từng-item theo đúng rubric checklist H11 (Hành-động · Tự-verify · Nấc · Loại).
|
||||
|
||||
## Rubric (theo checklist H11)
|
||||
- **Nấc:** executed-file (file tĩnh có trên đĩa) / runtime (đã chạy-quan-sát) / executed-file+runtime.
|
||||
- **Loại:** mechanized (artifact/cổng-máy bảo-chứng) / convention (người tuân-thủ, không cổng máy).
|
||||
- **Completeness-gate:** B+C+D phải hiện-diện ĐỦ-TRỌN; thiếu 1 = CHƯA-ĐẠT. A = 🟡 tailorable.
|
||||
|
||||
## 3 lane
|
||||
| Lane | Role | Checklist section |
|
||||
|---|---|---|
|
||||
| CL1 | investigator-codebase | PHẦN A (A1-A7 🟡) + PHẦN B (B1-B4 🔴) |
|
||||
| CL2 | investigator-codebase | PHẦN C (C1-C5 🔴 mandate) — chạy detector |
|
||||
| CL3 | investigator-codebase | PHẦN D (D1-D11 🔴) — D.1 nhịp + D.2 3-tier + D.3 4-chốt |
|
||||
|
||||
## Acceptance
|
||||
Mỗi item: status + evidence (file:line / run-output) + nấc + loại, KHÔNG trí-nhớ. Section verdict ĐẠT/CHƯA. Completeness-gate cuối: B+C+D đủ-trọn?
|
||||
|
||||
## Run-id
|
||||
`wf_39cd4cbe-f07`
|
||||
14
.claude/workflows/runs/2026-06-18-h11-doublecheck/_patch.py
Normal file
14
.claude/workflows/runs/2026-06-18-h11-doublecheck/_patch.py
Normal file
@ -0,0 +1,14 @@
|
||||
p=r"D:/Dropbox/CONG_VIEC/SOLUTION/SOLUTION_ERP/.claude/workflows/runs/2026-06-18-h11-doublecheck/_scratch-det.ps1"
|
||||
lines=open(p,encoding='utf-8').read().split('\n')
|
||||
out=[];n=0
|
||||
for ln in lines:
|
||||
s=ln
|
||||
if "if ($line -match '^\s*\|') { continue }" in ln:
|
||||
s=" if ($false) { continue } #DIS-tablerow"; n+=1
|
||||
elif "baseline|" in ln and "S\d{2}" in ln and "{ continue }" in ln:
|
||||
s=" if ($false) { continue } #DIS-historical"; n+=1
|
||||
elif "if ($pre -match" in ln and "phase|session" in ln:
|
||||
s=" if ($false) { continue } #DIS-versionprefix"; n+=1
|
||||
out.append(s)
|
||||
open(p,'w',encoding='utf-8').write('\n'.join(out))
|
||||
print("patched lines:",n)
|
||||
@ -0,0 +1,406 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
governance-detectors.ps1 - Harness-11 PHAN C + B3 governance drift detectors.
|
||||
|
||||
.DESCRIPTION
|
||||
NO-API, DETECT-and-FLAG-only grep net (Harness-11 mandate):
|
||||
(1) NO-API - only Select-String + byte/file-exist measure. NEVER calls model/API.
|
||||
(2) FLAG-only - prints FLAGs, NEVER edits files (auto-WRITE of rules = top hazard, forbidden).
|
||||
(3) PowerShell 5.1 compatible. Run offline. ASCII-only script body (gotcha #30);
|
||||
target-file content is read -Encoding UTF8 so Vietnamese count-tokens
|
||||
(bay / bang / Du tru) match correctly.
|
||||
(5) DETECT-only LOWERING NET, not a hard build gate. Exit code always 0.
|
||||
|
||||
Detectors:
|
||||
C2/B3 - derived-staleness : canonical counts from STATUS.md (cross-checked vs disk),
|
||||
then derived docs scanned for stale count-tokens.
|
||||
C1 - broken-pointer : (a) gotcha #N refs > max-gotcha or missing "### N." anchor
|
||||
(b) dangling [[wikilink]] in user-memory / agent-memory.
|
||||
C3 - vocab-fork : alias-sets where >=2 variants live side-by-side.
|
||||
C4 - self-line exclusion: pattern-describing files removed from every scan
|
||||
(else the detector self-matches).
|
||||
|
||||
Each FLAG line:
|
||||
[DETECTOR] severity | file:line | description | resolve: <un-flag condition> (C5)
|
||||
|
||||
.PARAMETER RepoRoot
|
||||
Repo root. Default = resolved 2 levels up from this script (scripts/ -> repo root).
|
||||
|
||||
.EXAMPLE
|
||||
powershell.exe -ExecutionPolicy Bypass -File scripts/governance-detectors.ps1
|
||||
#>
|
||||
param(
|
||||
[string]$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Continue'
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
$script:FlagCount = 0
|
||||
|
||||
function Write-Flag {
|
||||
param(
|
||||
[ValidateSet('HIGH', 'MED', 'LOW')] [string]$Severity,
|
||||
[string]$Where, # file:line
|
||||
[string]$Desc,
|
||||
[string]$Resolve
|
||||
)
|
||||
$color = switch ($Severity) { 'HIGH' { 'Red' } 'MED' { 'Yellow' } default { 'Gray' } }
|
||||
Write-Host ("[DETECTOR] {0,-4} | {1} | {2} | resolve: {3}" -f $Severity, $Where, $Desc, $Resolve) -ForegroundColor $color
|
||||
$script:FlagCount++
|
||||
}
|
||||
|
||||
function Write-Section($title) {
|
||||
Write-Host ''
|
||||
Write-Host ("===== $title =====") -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
# Make a path repo-relative for readable FLAG output (forward slashes).
|
||||
function Rel($full) {
|
||||
$r = $full
|
||||
if ($full.StartsWith($RepoRoot, [StringComparison]::OrdinalIgnoreCase)) {
|
||||
$r = $full.Substring($RepoRoot.Length).TrimStart('\', '/')
|
||||
}
|
||||
return ($r -replace '\\', '/')
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Unicode-token builder (gotcha #30 mojibake guard).
|
||||
# This .ps1 is ASCII-only on disk. PowerShell 5.1 decodes a BOM-less .ps1 with
|
||||
# the system ANSI codepage (NOT UTF-8) when launched via -File, which corrupts
|
||||
# any inline Vietnamese literal (e.g. "bay" -> mojibake) so it can no longer
|
||||
# match correctly-decoded UTF-8 file content. We therefore build every
|
||||
# Vietnamese token from Unicode code points at RUNTIME -> encoding-independent.
|
||||
function U { param([int[]]$cp) -join ($cp | ForEach-Object { [char]$_ }) }
|
||||
|
||||
# Vietnamese tokens used by detectors:
|
||||
$VN_BAY = U @(0x62, 0x1EAB, 0x79) # "bay" (gotcha synonym)
|
||||
$VN_BANG = U @(0x62, 0x1EA3, 0x6E, 0x67) # "bang" (table synonym)
|
||||
$VN_DUTRU_PRO = U @(0x44, 0x1EF1, 0x20, 0x74, 0x72, 0xF9, 0x20, 0x50, 0x52, 0x4F) # "Du tru PRO"
|
||||
$VN_NGANSACH_PRO = U @(0x4E, 0x67, 0xE2, 0x6E, 0x20, 0x73, 0xE1, 0x63, 0x68, 0x20, 0x50, 0x52, 0x4F) # "Ngan sach PRO"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# C4 - self-line exclusion (BUILT FIRST so every scan can apply it)
|
||||
# These files DESCRIBE the patterns the detectors look for; without exclusion
|
||||
# the detector would flag itself. Glob-style suffix/substring rules.
|
||||
# ---------------------------------------------------------------------------
|
||||
$ExcludeExact = @(
|
||||
(Join-Path $RepoRoot 'scripts\governance-detectors.ps1'),
|
||||
(Join-Path $RepoRoot 'docs\governance\harness-11-engine.md')
|
||||
) | ForEach-Object { $_ -replace '/', '\' }
|
||||
|
||||
$ExcludeDirFragments = @(
|
||||
'\broadcasts\inbox\',
|
||||
'\broadcasts\outbox\',
|
||||
'\.claude\workflows\runs\',
|
||||
'\.claude\workflows\scripts\'
|
||||
)
|
||||
|
||||
function Test-Excluded($full) {
|
||||
$p = ($full -replace '/', '\')
|
||||
foreach ($ex in $ExcludeExact) { if ($p -ieq $ex) { return $true } }
|
||||
foreach ($frag in $ExcludeDirFragments) { if ($p -ilike "*$frag*") { return $true } }
|
||||
return $false
|
||||
}
|
||||
|
||||
# Resolve which excluded paths actually exist on disk (for the audit line).
|
||||
$ExcludedActual = @()
|
||||
foreach ($ex in $ExcludeExact) { if (Test-Path $ex) { $ExcludedActual += $ex } }
|
||||
foreach ($frag in $ExcludeDirFragments) {
|
||||
$probe = Join-Path $RepoRoot ($frag.Trim('\'))
|
||||
if (Test-Path $probe) { $ExcludedActual += $probe }
|
||||
}
|
||||
|
||||
# Gather governance MD set ONCE (docs/** + .claude/** *.md), minus excluded.
|
||||
function Get-GovernanceMd {
|
||||
$dirs = @((Join-Path $RepoRoot 'docs'), (Join-Path $RepoRoot '.claude'))
|
||||
$all = @()
|
||||
foreach ($d in $dirs) {
|
||||
if (Test-Path $d) {
|
||||
$all += Get-ChildItem -Path $d -Recurse -Filter *.md -File -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
return $all | Where-Object { -not (Test-Excluded $_.FullName) }
|
||||
}
|
||||
|
||||
$GovMd = Get-GovernanceMd
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Canonical values from docs/STATUS.md + disk cross-check
|
||||
# ---------------------------------------------------------------------------
|
||||
function Get-StatusValue {
|
||||
param([string]$StatusPath, [string]$RowLabel)
|
||||
# Match a CURRENT-STATE table row: | <label> | **<number>** |
|
||||
$pat = '^\|\s*' + [regex]::Escape($RowLabel) + '\s*\|\s*\*\*(\d+)'
|
||||
$m = Select-String -Path $StatusPath -Pattern $pat -Encoding UTF8 | Select-Object -First 1
|
||||
if ($m) { return [int]$m.Matches[0].Groups[1].Value }
|
||||
return $null
|
||||
}
|
||||
|
||||
Write-Section 'C2/B3 - canonical resolve + disk cross-check'
|
||||
|
||||
$statusPath = Join-Path $RepoRoot 'docs\STATUS.md'
|
||||
$canonical = [ordered]@{}
|
||||
$canonicalOk = $true
|
||||
|
||||
if (-not (Test-Path $statusPath)) {
|
||||
Write-Flag 'HIGH' (Rel $statusPath) 'docs/STATUS.md not found - cannot resolve canonical counts' 'create docs/STATUS.md CURRENT STATE table'
|
||||
$canonicalOk = $false
|
||||
}
|
||||
else {
|
||||
$canonical['mig'] = Get-StatusValue $statusPath 'Migrations'
|
||||
$canonical['test'] = Get-StatusValue $statusPath 'Tests'
|
||||
$canonical['gotcha'] = Get-StatusValue $statusPath 'Gotchas'
|
||||
$canonical['table'] = Get-StatusValue $statusPath 'SQL tables'
|
||||
|
||||
Write-Host (" STATUS.md canonical: mig={0} test={1} gotcha={2} table={3}" -f `
|
||||
$canonical['mig'], $canonical['test'], $canonical['gotcha'], $canonical['table'])
|
||||
|
||||
# ---- disk cross-check: canonical must not itself be stale ----
|
||||
# mig = migration .cs files (exclude *Designer.cs / *ModelSnapshot.cs), recursive
|
||||
# so it survives Migrations/ vs Persistence/Migrations/ layout differences.
|
||||
$migDirs = Get-ChildItem -Path (Join-Path $RepoRoot 'src') -Recurse -Directory -Filter 'Migrations' -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.FullName -notmatch '\\(bin|obj|node_modules)\\' }
|
||||
$diskMig = 0
|
||||
foreach ($md in $migDirs) {
|
||||
$diskMig += (Get-ChildItem -Path $md.FullName -Filter *.cs -File -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.Name -notlike '*Designer.cs' -and $_.Name -notlike '*ModelSnapshot.cs' }).Count
|
||||
}
|
||||
|
||||
# gotcha = highest N from "### N." headings in docs/gotchas.md
|
||||
$gotchasPath = Join-Path $RepoRoot 'docs\gotchas.md'
|
||||
$diskGotcha = $null
|
||||
if (Test-Path $gotchasPath) {
|
||||
$nums = Select-String -Path $gotchasPath -Pattern '^### (\d+)\.' -Encoding UTF8 |
|
||||
ForEach-Object { [int]$_.Matches[0].Groups[1].Value }
|
||||
if ($nums) { $diskGotcha = ($nums | Measure-Object -Maximum).Maximum }
|
||||
}
|
||||
|
||||
Write-Host (" disk cross-check: mig={0} gotcha={1}" -f $diskMig, $diskGotcha)
|
||||
|
||||
if ($null -ne $canonical['mig'] -and $diskMig -gt 0 -and $canonical['mig'] -ne $diskMig) {
|
||||
Write-Flag 'HIGH' (Rel $statusPath) `
|
||||
("canonical-itself-stale: STATUS Migrations=**{0}** but disk has {1} migration .cs" -f $canonical['mig'], $diskMig) `
|
||||
("re-ground STATUS.md Migrations row to {0}" -f $diskMig)
|
||||
$canonicalOk = $false
|
||||
}
|
||||
if ($null -ne $canonical['gotcha'] -and $null -ne $diskGotcha -and $canonical['gotcha'] -ne $diskGotcha) {
|
||||
Write-Flag 'HIGH' (Rel $statusPath) `
|
||||
("canonical-itself-stale: STATUS Gotchas=**{0}** but docs/gotchas.md max anchor is {1}" -f $canonical['gotcha'], $diskGotcha) `
|
||||
("re-ground STATUS.md Gotchas row to {0}" -f $diskGotcha)
|
||||
$canonicalOk = $false
|
||||
}
|
||||
if ($canonicalOk) {
|
||||
Write-Host ' [OK] canonical matches disk (mig + gotcha) - safe baseline for derived scan' -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# C2/B3 - derived-staleness scan
|
||||
# Derived docs that summarize counts; each should match canonical OR be a pointer.
|
||||
# ---------------------------------------------------------------------------
|
||||
Write-Section 'C2/B3 - derived-doc staleness'
|
||||
|
||||
# token-regex -> canonical key. Vietnamese tokens built from code points (ASCII source).
|
||||
$countPatterns = @(
|
||||
@{ Rx = '(\d+)\s*migration'; Key = 'mig'; Label = 'migration' },
|
||||
@{ Rx = '(\d+)\s*test'; Key = 'test'; Label = 'test' },
|
||||
@{ Rx = ('(\d+)\s*(?:' + $VN_BAY + '|gotcha)'); Key = 'gotcha'; Label = 'gotcha/bay' },
|
||||
@{ Rx = ('(\d+)\s*(?:' + $VN_BANG + '|table)'); Key = 'table'; Label = 'table/bang' }
|
||||
)
|
||||
|
||||
$derivedDocs = @(
|
||||
'CLAUDE.md',
|
||||
'docs\CLAUDE.md',
|
||||
'.claude\skills\ef-core-migration\SKILL.md',
|
||||
'.claude\skills\README.md',
|
||||
'.claude\skills\dependency-audit-erp\SKILL.md'
|
||||
) | ForEach-Object { Join-Path $RepoRoot $_ }
|
||||
|
||||
foreach ($doc in $derivedDocs) {
|
||||
if (-not (Test-Path $doc)) { continue }
|
||||
if (Test-Excluded $doc) { continue }
|
||||
$lines = Get-Content -Path $doc -Encoding UTF8
|
||||
for ($i = 0; $i -lt $lines.Count; $i++) {
|
||||
$line = $lines[$i]
|
||||
# C2 FP-reduction (R2 refinement S75): per-item table rows + frozen-historical lines are NOT state-count claims
|
||||
if ($false) { continue } #DIS-tablerow
|
||||
if ($false) { continue } #DIS-historical
|
||||
foreach ($cp in $countPatterns) {
|
||||
$canon = $canonical[$cp.Key]
|
||||
if ($null -eq $canon) { continue }
|
||||
foreach ($m in [regex]::Matches($line, $cp.Rx)) {
|
||||
$pre = $line.Substring([Math]::Max(0, $m.Index - 12), [Math]::Min(12, $m.Index))
|
||||
if ($false) { continue } #DIS-versionprefix
|
||||
$n = [int]$m.Groups[1].Value
|
||||
if ($n -ne $canon) {
|
||||
$sev = if ([math]::Abs($n - $canon) -ge 10) { 'MED' } else { 'LOW' }
|
||||
Write-Flag $sev ("{0}:{1}" -f (Rel $doc), ($i + 1)) `
|
||||
("derived-stale: writes {0} {1} but canonical={2}" -f $n, $cp.Label, $canon) `
|
||||
("update to {0} OR replace with pointer '-> docs/STATUS.md'" -f $canon)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Host ' (note: count-token grep is a soft net - module-local phrases like "4 bang Budget" / "71 test (Phase 8)" can false-positive; treat LOW sev as review-not-fail)' -ForegroundColor DarkGray
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# C1 - broken-pointer: gotcha #N refs
|
||||
# ---------------------------------------------------------------------------
|
||||
Write-Section 'C1 - broken gotcha-ref'
|
||||
|
||||
$maxGotcha = $canonical['gotcha']
|
||||
$gotchasPath = Join-Path $RepoRoot 'docs\gotchas.md'
|
||||
$gotchaAnchors = @{}
|
||||
if (Test-Path $gotchasPath) {
|
||||
Select-String -Path $gotchasPath -Pattern '^### (\d+)\.' -Encoding UTF8 |
|
||||
ForEach-Object { $gotchaAnchors[[int]$_.Matches[0].Groups[1].Value] = $true }
|
||||
}
|
||||
|
||||
if ($null -eq $maxGotcha -or $gotchaAnchors.Count -eq 0) {
|
||||
Write-Host ' [skip] no canonical max-gotcha or no anchors parsed - cannot validate gotcha refs' -ForegroundColor DarkGray
|
||||
}
|
||||
else {
|
||||
# Match "gotcha #N", "gotcha N", and bare "#N" tokens.
|
||||
$refRx = '(?:gotcha[s]?\s*#?(\d+))|(?<![A-Za-z0-9])#(\d+)'
|
||||
foreach ($f in $GovMd) {
|
||||
$lines = Get-Content -Path $f.FullName -Encoding UTF8
|
||||
for ($i = 0; $i -lt $lines.Count; $i++) {
|
||||
foreach ($m in [regex]::Matches($lines[$i], $refRx)) {
|
||||
$num = if ($m.Groups[1].Success) { [int]$m.Groups[1].Value } else { [int]$m.Groups[2].Value }
|
||||
$isGotchaWord = $m.Groups[1].Success
|
||||
# bare "#N": only treat as gotcha-ref candidate when N is in gotcha numeric range
|
||||
# to avoid PR/issue/run numbers. gotcha-word form always validated.
|
||||
if (-not $isGotchaWord) {
|
||||
if ($num -le 0 -or $num -gt ($maxGotcha + 50)) { continue }
|
||||
# bare #N with N <= maxGotcha and anchor exists -> fine, skip silently
|
||||
if ($num -le $maxGotcha -and $gotchaAnchors.ContainsKey($num)) { continue }
|
||||
# bare #N > maxGotcha is ambiguous (could be Run #312) -> skip to avoid noise
|
||||
if ($num -gt $maxGotcha) { continue }
|
||||
}
|
||||
if ($num -gt $maxGotcha) {
|
||||
Write-Flag 'MED' ("{0}:{1}" -f (Rel $f.FullName), ($i + 1)) `
|
||||
("broken-gotcha-ref: cites #{0} but max gotcha is {1}" -f $num, $maxGotcha) `
|
||||
'fix the number or add the gotcha to docs/gotchas.md'
|
||||
}
|
||||
elseif ($isGotchaWord -and -not $gotchaAnchors.ContainsKey($num)) {
|
||||
Write-Flag 'LOW' ("{0}:{1}" -f (Rel $f.FullName), ($i + 1)) `
|
||||
("broken-gotcha-ref: 'gotcha #{0}' has no '### {0}.' anchor in gotchas.md" -f $num) `
|
||||
'fix ref or create the missing gotcha anchor'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# C1 - broken-pointer: dangling [[wikilink]] (user-memory + agent-memory)
|
||||
# ---------------------------------------------------------------------------
|
||||
Write-Section 'C1 - dangling wikilink'
|
||||
|
||||
# user-memory dir (outside repo). Derive from this machine's project slug; if not
|
||||
# reachable, fall back to in-repo agent-memory only + emit a note.
|
||||
$userMemDir = 'C:\Users\pqhuy\.claude\projects\D--Dropbox-CONG-VIEC-SOLUTION-SOLUTION-ERP\memory'
|
||||
$agentMemDir = Join-Path $RepoRoot '.claude\agent-memory'
|
||||
|
||||
$memScopes = @()
|
||||
if (Test-Path $userMemDir) { $memScopes += [pscustomobject]@{ Name = 'user-memory'; Dir = $userMemDir; Recurse = $false } }
|
||||
else { Write-Host " [note] user-memory path not reachable ($userMemDir) - scanning in-repo agent-memory only" -ForegroundColor DarkGray }
|
||||
if (Test-Path $agentMemDir) { $memScopes += [pscustomobject]@{ Name = 'agent-memory'; Dir = $agentMemDir; Recurse = $true } }
|
||||
|
||||
foreach ($scope in $memScopes) {
|
||||
$gp = if ($scope.Recurse) {
|
||||
Get-ChildItem -Path $scope.Dir -Recurse -Filter *.md -File -ErrorAction SilentlyContinue
|
||||
} else {
|
||||
Get-ChildItem -Path $scope.Dir -Filter *.md -File -ErrorAction SilentlyContinue
|
||||
}
|
||||
# Build the set of existing target basenames in this scope.
|
||||
$targets = @{}
|
||||
foreach ($g in $gp) { $targets[$g.BaseName] = $true; $targets[($g.BaseName -replace '[-_]', '')] = $true } # C1 refinement (R2 S75): also index separator-normalized form (hyphen<->underscore fork)
|
||||
|
||||
foreach ($g in $gp) {
|
||||
$lines = Get-Content -Path $g.FullName -Encoding UTF8
|
||||
for ($i = 0; $i -lt $lines.Count; $i++) {
|
||||
foreach ($m in [regex]::Matches($lines[$i], '\[\[([a-z0-9_-]+)\]\]')) {
|
||||
$tgt = $m.Groups[1].Value
|
||||
if (-not ($targets.ContainsKey($tgt) -or $targets.ContainsKey(($tgt -replace '[-_]', '')))) {
|
||||
Write-Flag 'LOW' ("{0}/{1}:{2}" -f $scope.Name, $g.Name, ($i + 1)) `
|
||||
("dangling-wikilink: [[{0}]] -> {0}.md not found in {1}" -f $tgt, $scope.Name) `
|
||||
'fix the link target or create the file (note: hyphen vs underscore basename fork is common)'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# C3 - vocab-fork
|
||||
# ---------------------------------------------------------------------------
|
||||
Write-Section 'C3 - vocab-fork'
|
||||
|
||||
# Seed alias-sets (hard-coded from audit; extend over time). Vietnamese variants
|
||||
# built from code points so the .ps1 stays ASCII-only (gotcha #30) yet matches
|
||||
# correctly-decoded UTF-8 content.
|
||||
$aliasSets = @(
|
||||
@('wave-folder', 'run-trace'),
|
||||
@($VN_DUTRU_PRO, $VN_NGANSACH_PRO),
|
||||
@('two-tier', 'all-inherit')
|
||||
)
|
||||
|
||||
for ($s = 0; $s -lt $aliasSets.Count; $s++) {
|
||||
$variants = $aliasSets[$s]
|
||||
$perVariantFiles = @{}
|
||||
foreach ($v in $variants) { $perVariantFiles[$v] = New-Object System.Collections.Generic.List[string] }
|
||||
|
||||
foreach ($f in $GovMd) {
|
||||
$content = Get-Content -Path $f.FullName -Raw -Encoding UTF8
|
||||
if ($null -eq $content) { continue }
|
||||
foreach ($v in $variants) {
|
||||
if ($content -match [regex]::Escape($v)) {
|
||||
$perVariantFiles[$v].Add((Rel $f.FullName)) | Out-Null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$liveVariants = @($variants | Where-Object { $perVariantFiles[$_].Count -gt 0 })
|
||||
if ($liveVariants.Count -ge 2) {
|
||||
$detail = ($liveVariants | ForEach-Object { "{0}={1}f" -f $_, $perVariantFiles[$_].Count }) -join ' vs '
|
||||
$sample = ($liveVariants | ForEach-Object {
|
||||
$first = $perVariantFiles[$_] | Select-Object -First 2
|
||||
"'$_' in [$($first -join ', ')]"
|
||||
}) -join ' | '
|
||||
Write-Flag 'MED' 'multiple files' `
|
||||
("vocab-fork: $detail live side-by-side -- $sample") `
|
||||
'merge to ONE canonical term, or record an alias-map in docs/governance'
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Summary + C4 self-exclusion audit (RUNTIME proof)
|
||||
# ---------------------------------------------------------------------------
|
||||
Write-Section 'Summary'
|
||||
|
||||
# Confirm 0 self-match: the detector script must never appear in the scanned set.
|
||||
$selfPath = (Join-Path $RepoRoot 'scripts\governance-detectors.ps1') -replace '/', '\'
|
||||
$selfInScan = @($GovMd | Where-Object { ($_.FullName -replace '/', '\') -ieq $selfPath }).Count
|
||||
# (governance-detectors.ps1 is .ps1 not .md so never in $GovMd; this asserts the
|
||||
# invariant explicitly. Also assert none of the excluded dirs leaked in.)
|
||||
$leaked = @($GovMd | Where-Object { Test-Excluded $_.FullName }).Count
|
||||
|
||||
Write-Host ("self-exclusion: {0} paths excluded (exact+dir rules)" -f $ExcludedActual.Count)
|
||||
foreach ($e in $ExcludedActual) { Write-Host (" - excluded: {0}" -f (Rel $e)) -ForegroundColor DarkGray }
|
||||
Write-Host ("self-match check: governance-detectors.ps1 in scan = {0} ; leaked excluded files in scan = {1}" -f $selfInScan, $leaked)
|
||||
if ($selfInScan -eq 0 -and $leaked -eq 0) {
|
||||
Write-Host ' [OK] 0 self-match (C4 satisfied)' -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host ' [!] self-exclusion LEAK - investigate Test-Excluded rules' -ForegroundColor Red
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host ("TOTAL FLAGS: {0}" -f $script:FlagCount) -ForegroundColor Cyan
|
||||
Write-Host 'NOTE: DETECT-only lowering net. Exit 0 always (never fails build). FLAGs are advisory.' -ForegroundColor DarkGray
|
||||
|
||||
exit 0
|
||||
@ -0,0 +1,28 @@
|
||||
# DOUBLE-CHECK SYNTHESIS — Harness-11 adap (2026-06-18-h11-doublecheck · `wf_a0b68d2f-30e`)
|
||||
|
||||
> 3× reviewer (read-only, adversarial ∥). Em-main scribe @P3. **VERDICT: ✅ PASS — 0 blocker.** Re-verify commit `e70c046` + regression của refinement em-main áp sau REVIEW-1.
|
||||
|
||||
## DA1 — over-suppression regression → FAILED-no-StructuredOutput → **em-main self-gate CLOSED**
|
||||
- Reviewer lane parallel[0] không trả StructuredOutput (lỗi #53 schema-force tái diễn).
|
||||
- **Em-main self-gate (recovery-pattern):** inject prose fake-drift "99 migration" (KHÔNG table-row/version/historical) → detector **CAUGHT** "99 migration but canonical=55" → revert clean. → **no over-suppression, runtime-proven.**
|
||||
- Bonus: detector pure-ASCII (Python scan 0 non-ASCII — gotcha #30 clean) · PS parse OK · exit 0 · 26 flag.
|
||||
|
||||
## DA2 — committed-state correctness → **PASS**
|
||||
- B1 **exactly 11** pointer-conversion (grep -c = 11). root CLAUDE.md:53 **tail byte-identical** (`sed -n '53p'` ends "...phiếu cũ.)" = old) → 0 load-bearing prose loss; chỉ leading count-phrase swap + S74/S73 additive prefix.
|
||||
- ef-core Mig 54/55 rows = **tên migration THẬT trên disk** (`AddPeSuggestedAndApprovedPrice` + `AddCcmNoteToPeWorkItemBudget` .cs EXIST).
|
||||
- 0 stale-count residual (grep 53mig/306test/68gotcha/93bảng = 0). cadence §2.1.3/§L.b cú-pháp đúng, path tồn-tại + run clean. engine-doc line-ref accurate (D5=:67, hmw.js:76/103/111, budget.json:19).
|
||||
- 2 MINOR (đã FIX): agents/README "(pending)" stale + C2 FP CLAUDE.md:84/:90.
|
||||
|
||||
## DA3 — containment + regression → **PASS** (0 blocker/0 major/1 minor-info)
|
||||
- Q1 0 production code (grep src/|fe-* = 0). Q2 run-trace đủ (audit/review NO sub = read-only em-main-scribe ✓ · implement có sub-task-0/1 = general-purpose Write ✓ · ledger CLOSE-beat all prior). Q4 single-writer (0 sub MEMORY.md residual · .archive-strikes.json absent). Q5 budget.json pure-additive (measured/tiers/last_sleep_at untouched).
|
||||
- **Q3 broadcasts byte-verified:** recompute INBOX body=`b2a2fc1cf399` (==_index ==frontmatter), whole-file=`318ff9f6` (==commit-msg); OUTBOX body=`7fa1b53a61ae` (==_index ==frontmatter). KHỚP TUYỆT-ĐỐI.
|
||||
- **REGRESSION over-suppression HUNT (độc-lập confirm self-gate):** enumerate cái C2-skip che = per-item frozen (ef-core "Mig 12→10 bảng") + Session-N historical + CLAUDE.md "88 table"==canonical — KHÔNG cái nào là live-aggregate-state-count. Cả 11 prose-drift VẪN bắt. C1 normalize verified 2 chiều (genuine-dangling vẫn flag + prefix-differ vẫn flag). **NO real drift hidden.**
|
||||
- Anti-finding: C3 console mojibake "D? tr<74>" = console-codepage Bash-capture artifact, KHÔNG script bug ([Console]::OutputEncoding=UTF8 render "Dự trù PRO" đúng; Select-String so-sánh UTF-8 chính-xác).
|
||||
|
||||
## Em-main actions post-doublecheck
|
||||
1. ✅ self-gate fake-drift (close DA1) — no over-suppression, runtime.
|
||||
2. ✅ +C2 "test project" skip (line 90 FP gone, 27→26) — ASCII clean.
|
||||
3. ✅ agents/README "(pending)" → run-id thật (review `wf_d7ca1ff8-942` + doublecheck `wf_a0b68d2f-30e`).
|
||||
4. ⚠️ Tree-line FP-skip ATTEMPTED rồi REVERT (literal box-glyph = gotcha #30 trap; \u-escape edit bị tool render-normalize → bỏ, line 84 "6 test" giữ làm documented soft-net FP, advisory exit-0 harmless). **Bài học: KHÔNG đưa box-glyph vào .ps1 — kể cả qua Edit tool (normalize).**
|
||||
|
||||
## VERDICT: PASS — committed-state đúng, refinement 0-regression (triple-confirmed self-gate+DA2+DA3), containment clean. Sẵn-sàng checklist-verify + push.
|
||||
20
.claude/workflows/runs/2026-06-18-h11-doublecheck/run.md
Normal file
20
.claude/workflows/runs/2026-06-18-h11-doublecheck/run.md
Normal file
@ -0,0 +1,20 @@
|
||||
# RUN — 2026-06-18-h11-doublecheck (Harness-11 adap · DOUBLE-CHECK #1, anh giao)
|
||||
|
||||
> **Harness-10 FLAT run-trace** (TRACKED). 3× reviewer (read-only, adversarial ∥). Synthesis → `doublecheck-synthesis.md`.
|
||||
|
||||
- **Workflow:** Harness-11 adap — DOUBLE-CHECK vòng 2 (anh giao "double check lại 1 turn nữa")
|
||||
- **Mode:** hmw RUN-TRACE free-text. Re-review state ĐÃ COMMIT `e70c046` (post-refinement).
|
||||
- **Trọng tâm:** REVIEW vòng 1 (`wf_d7ca1ff8-942`) đã PASS + em-main refine C2/C1 (59→27). Vòng này soi **regression của chính refinement** + bất kỳ thứ gì 2 vòng trước sót.
|
||||
|
||||
## 3 lane
|
||||
| Lane | Role | Focus |
|
||||
|---|---|---|
|
||||
| DA1 over-suppression regression | reviewer | C2 context-skip (table-row/version/historical) + C1 [-_] normalize có làm detector MÙ drift thật không? Test: tạo fake-drift trong context KHÔNG-skip → chạy → confirm bắt → revert. Over-suppress = nguy cơ #1 của refinement |
|
||||
| DA2 committed-state correctness | reviewer | git show e70c046: engine-doc + B1 ×11 + cadence-wire ĐÚNG trên disk? B1 có vô-tình đổi nghĩa/xóa nội-dung load-bearing? cadence §2.1.3/§L.b cú-pháp đúng? |
|
||||
| DA3 containment + run-trace integrity | reviewer | commit có gì sai? run-trace 4 folder đủ synthesis? broadcasts hash khớp? 0 production code thật? sub-task MD present (impl) vs read-only-scribe (audit/review)? |
|
||||
|
||||
## Acceptance
|
||||
PASS = refinement KHÔNG over-suppress (detector vẫn bắt drift thật) + committed-state đúng + containment clean. Issue → em-main fix trước checklist-verify + push.
|
||||
|
||||
## Run-id
|
||||
`wf_a0b68d2f-30e`
|
||||
@ -20,3 +20,5 @@
|
||||
| 2026-06-18-h11-audit | Harness-11 adap — AUDIT (PRESENT/PARTIAL/GAP vs SE-present) · 🆕FLAT | 2026-06-18 19:45 +07 | 2026-06-18 19:55 +07 | 4× investigator-codebase (read-only ∥, 1 PHẦN/lane) `wf_7fdc3bd5-930` | ✅ DONE — A 🟡 (A4/A5/A6 GAP hợp-lệ) · **B1+B3 GAP** (derived COPY, no freshness-detector) · **C1/C2/C3 GAP** (0 detector-script, chỉ agent-judgement) · **D5/D6/D7 PARTIAL + D8 GAP** (3-tier+1-direction chưa codify); D4/D9/D11 mechanized-mạnh sẵn. read-only→em-main scribe synthesis | `audit-synthesis.md` ✓ (sub read-only, findings-in-output) |
|
||||
| 2026-06-18-h11-implement | Harness-11 adap — IMPLEMENT (detector-script + A-gate ∥ sub · em-main MD cluster) · 🆕FLAT | 2026-06-18 19:56 +07 | 2026-06-18 20:15 +07 | 2× general-purpose (script file-disjoint ∥) + em-main single-writer (governance MD cluster) `wf_c5e5844e-7c1` | ✅ DONE — Lane1 `governance-detectors.ps1` runtime-proven (71→27 post-refinement R2; bắt drift thật + gotcha #30 mojibake fix) · Lane2 `memory-archive-gate.ps1` A4/A5/A6/A7 proven · em-main engine-doc + B1 ×11 (drift RESOLVED post-rerun) + cadence-wire D1/D2 + agents/README. B+C+D đủ-trọn (claim). Single-writer CLEAN. → REVIEW judge FP-rate | `implement-synthesis.md` ✓ (FLAT) |
|
||||
| 2026-06-18-h11-review | Harness-11 adap — REVIEW (B2 double-check, free-text) · 🆕FLAT | 2026-06-18 20:16 +07 | 2026-06-18 20:35 +07 | 3× reviewer (adversarial ∥: completeness-gate / detector-correctness / honesty-containment) `wf_d7ca1ff8-942` | ✅ **PASS** — R1 completeness-gate ĐẠT (B+C+D đủ-trọn) · R2 detector 6/6 correctness + 2 refinement (C2 context-skip + C1 normalize → 59→27 sharper) · R3 honesty+containment 0-blocker (1 nit fixed). NO-API+0-auto-write PASS. Single-writer CLEAN | `review-synthesis.md` ✓ (FLAT) |
|
||||
| 2026-06-18-h11-doublecheck | Harness-11 adap — DOUBLE-CHECK #1 (anh giao, post-commit `e70c046`) · 🆕FLAT | 2026-06-18 20:48 +07 | 2026-06-18 21:05 +07 | 3× reviewer (over-suppress-regression / committed-state / containment-runtrace) `wf_a0b68d2f-30e` | ✅ **PASS** — DA2+DA3 PASS (B1×11 exact · root:53 tail byte-identical · broadcasts hash recompute KHỚP · single-writer clean · over-suppress-hunt CLEAN). DA1 failed-no-SO → em-main self-gate fake-drift CAUGHT (no over-suppress, runtime). +C2 test-project skip (27→26) + agents/README pending→run-id. tree-skip reverted (gotcha #30 box-glyph) | `doublecheck-synthesis.md` ✓ (FLAT) |
|
||||
| 2026-06-18-h11-checklist-verify | Harness-11 adap — CHECKLIST formal self-verify (anh giao) · 🆕FLAT | 2026-06-18 21:08 +07 | 2026-06-18 21:22 +07 | 3× investigator-codebase (CL1 A+B / CL2 C / CL3 D, evidence-mapping ∥) `wf_39cd4cbe-f07` | ✅ **completeness-gate ĐẠT** — B 4/4 + C 5/5 + D 11/11 đủ-trọn (function-floor MET), A 🟡 tailored (A6 runtime cần 2×-Apply legit-by-design). D5/D6/D7 explicit-label=YES + D8 one-direction codify=YES. NO-API+0-auto-write 0-hit. All 3 lane returned | `checklist-verify-synthesis.md` ✓ (FLAT) |
|
||||
|
||||
Reference in New Issue
Block a user