[CLAUDE] Docs: S149-S150 closeout — bookend lượt đầu end-to-end (hình B) + 2 arc đóng + tally #53 chốt 45
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m48s

- Arc-1 hội-tụ-bookend (rename 5 vai + 4 máy PS1 + C9-C12) + arc-2 adap-backlog 23/23 + probe Opus-5 khép (S149)
- Bookend @close S150: wave 6 vai (4 đo + 2 KIỂM) → 20 FLAG disposition từng-dòng; ring1 31/34-ĐẠT, ring2 10/10 + M-1 view-stale-role-desc
- Khoá _frozen_until_owner CẮM trước h24-signal-write (frozen-held in thật); 9 class FIRE; JUMP dải {5,4,4,3}+asym{1,4} chờ anh #21
- STATUS bump CURRENT S149-S150 + 2 khối Recently Done; HANDOFF segment mới + re-stamp đủ-slug + (17)(18)(19) lật + (14) viết lại + 6 slot #21-#26
- K2 posture-A @engine PHẦN K + K5 luật TÁCH vòng-đo-mới @session-end (O-2/O-3 OWNER-DELEGATED execute)
- sleep-doc derive-monitor-set (bỏ hardcode 4-tên); spawn-model-audit desc/comment fix; h24-signal-write param-default fix (first-live bug)
- M9 on-behalf ×3 (tooling + inv-cb F3 + reviewer F4); ring1/ring4 nhà seed; ring2 3 cite-dead vá
- Sổ garble #53 derive-from-body chốt 45 + sub-class ngược-#53/skeleton-ruột-rỗng (ghi-đĩa CẦN-KHÔNG-ĐỦ)
- Session-log S149-S150 (Sàn-5 đăng-ký 6 run=) + closeout-synthesis dạng-1

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-07-25 12:17:05 +07:00
parent 2f39a7e22c
commit 398d343403
122 changed files with 7666 additions and 250 deletions

View File

@ -0,0 +1,158 @@
# session-scaffold.ps1 -- scaffold 1 logic-session folder + _context skeleton (M1, S149).
# TAILOR tu hub AI_INFRA/scripts/session_scaffold.py (169 dong) -> SE PowerShell, 2-mode split @S146.
#
# MODE (exactly one):
# -New : allocate a NEW logic-session = max+1 (session-start ONLY). Optional -N pins an
# explicit id; if that id already exists (folder OR _context) -> COLLISION
# (exit 4, writes NOTHING).
# -Ensure : idempotent heal of the CURRENT session (pause/tiep). _context missing -> create;
# _context present -> exit 0 NO-OP (mtime preserved). Optional -N pins the id;
# default = max existing session.
#
# INVARIANTS:
# - ts-moc = `git log -1 --format=%cI` of RepoRoot HEAD (git-committer). NO wall-clock: git
# unavailable -> exit 3 (refuse Get-Date). Deliberate DEVIATION from hub tagged-FALLBACK --
# spec M1 line 33 "khong wall-clock"; ts feeds C10 LATENESS measurement, must be deterministic.
# - NEVER overwrite an existing _context (ANY mode) -- hard guard in Write-Context (exit 5).
# - Pure-ASCII source (gotcha #30/#37 = PS 5.1 diacritics parser-fail). Vietnamese lives ONLY
# in the external template .md, never in this .ps1.
#
# -RepoRoot = fault-inject seam: point at a scratch tree to prove teeth, not just happy-path.
# Exit codes: 0 ok/no-op | 2 usage | 3 git-unavailable | 4 collision | 5 defensive-overwrite-block.
param(
[switch]$New,
[switch]$Ensure,
[int]$N,
[string]$RepoRoot = "$PSScriptRoot\.."
)
$ErrorActionPreference = 'Stop'
# --- helpers ---
function Fail {
param([string]$Msg, [int]$Code)
Write-Output "session-scaffold: ERROR: $Msg"
exit $Code
}
function Invoke-Git {
# Run git with stderr discarded; return @{ Out; Code }. EAP=Continue so a non-repo tree
# (git exit 128) does NOT throw under the script-wide Stop preference.
param([string[]]$GitArgs)
$old = $ErrorActionPreference
$ErrorActionPreference = 'Continue'
try {
$out = & git @GitArgs 2>$null
return @{ Out = (($out | Out-String)).Trim(); Code = $LASTEXITCODE }
} finally {
$ErrorActionPreference = $old
}
}
function Rel {
param([string]$Path, [string]$Root)
if ($Path.StartsWith($Root, [StringComparison]::OrdinalIgnoreCase)) {
return $Path.Substring($Root.Length).TrimStart('\', '/')
}
return $Path
}
function Write-Context {
# Render template -> _context, UTF-8 no-BOM + LF. HARD guard: never overwrite an existing
# _context (any mode) -- this is the durable owner-evidence file.
param([string]$TemplatePath, [string]$OutPath, [int]$SessionN, [string]$Ts, [string]$Head)
if (Test-Path -LiteralPath $OutPath) {
Fail "REFUSE-OVERWRITE: $OutPath exists (never overwrite _context)" 5
}
$tpl = [System.IO.File]::ReadAllText($TemplatePath, [System.Text.Encoding]::UTF8)
$rendered = $tpl.Replace('{{N}}', "$SessionN").Replace('{{TS}}', $Ts).Replace('{{HEAD}}', $Head)
$rendered = $rendered -replace "`r`n", "`n"
$outDir = Split-Path -Parent $OutPath
if (-not (Test-Path -LiteralPath $outDir)) {
New-Item -ItemType Directory -Path $outDir -Force | Out-Null
}
$enc = New-Object System.Text.UTF8Encoding($false) # $false = emit NO byte-order-mark
[System.IO.File]::WriteAllText($OutPath, $rendered, $enc)
}
# --- validate mode (exactly one) ---
if ($New -and $Ensure) { Fail "specify exactly one of -New / -Ensure (both given)" 2 }
if (-not $New -and -not $Ensure) { Fail "specify exactly one of -New / -Ensure (none given)" 2 }
$explicitN = $PSBoundParameters.ContainsKey('N')
if ($explicitN -and $N -lt 0) { Fail "-N must be a non-negative integer (got $N)" 2 }
# --- resolve root + template ---
if (-not (Test-Path -LiteralPath $RepoRoot)) { Fail "RepoRoot not found: $RepoRoot" 2 }
$root = (Resolve-Path -LiteralPath $RepoRoot).Path
$templatePath = Join-Path $root '.claude\templates\session-context-template.md'
if (-not (Test-Path -LiteralPath $templatePath)) { Fail "template not found: $templatePath" 2 }
$sessionsRoot = Join-Path $root '.claude\sessions'
# --- compute max existing session-<N> ---
$maxN = 0
if (Test-Path -LiteralPath $sessionsRoot) {
Get-ChildItem -LiteralPath $sessionsRoot -Directory -ErrorAction SilentlyContinue | ForEach-Object {
if ($_.Name -match '^session-(\d+)$') {
$k = [int]$Matches[1]
if ($k -gt $maxN) { $maxN = $k }
}
}
}
# --- resolve target N per mode ---
if ($New) {
if ($explicitN) { $targetN = $N } else { $targetN = $maxN + 1 }
} else {
if ($explicitN) {
$targetN = $N
} else {
if ($maxN -lt 1) { Fail "-Ensure: no existing session to heal (run -New first)" 2 }
$targetN = $maxN
}
}
$sessionDir = Join-Path $sessionsRoot "session-$targetN"
$contextPath = Join-Path $sessionDir "_context-s-$targetN.md"
$folderExists = Test-Path -LiteralPath $sessionDir
$contextExists = Test-Path -LiteralPath $contextPath
# --- ts-moc from git HEAD (NO wall-clock; refuse if git down) ---
$r1 = Invoke-Git @('-C', $root, 'log', '-1', '--format=%cI')
$r2 = Invoke-Git @('-C', $root, 'log', '-1', '--format=%h')
if ($r1.Code -ne 0 -or $r2.Code -ne 0) {
Fail "git HEAD unavailable at $root -- refusing wall-clock fallback (spec M1: no wall-clock)" 3
}
$ts = $r1.Out
$head = $r2.Out
if ([string]::IsNullOrWhiteSpace($ts)) {
Fail "git returned empty committer-ts -- refusing wall-clock fallback" 3
}
# --- mode: New (allocate; collision => write NOTHING) ---
if ($New) {
if ($folderExists -or $contextExists) {
$why = if ($contextExists) { "_context exists" } else { "session folder exists" }
Write-Output "session-scaffold: COLLISION session-$targetN ($why) -- writing NOTHING (exit 4)."
exit 4
}
Write-Context -TemplatePath $templatePath -OutPath $contextPath -SessionN $targetN -Ts $ts -Head $head
Write-Output "session-scaffold: [New] created session-$targetN (max was $maxN)"
Write-Output " folder = $(Rel $sessionDir $root)"
Write-Output " context = $(Rel $contextPath $root)"
Write-Output " ts-moc = $ts (HEAD $head)"
exit 0
}
# --- mode: Ensure (idempotent heal) ---
if ($contextExists) {
Write-Output "session-scaffold: [Ensure] session-$targetN _context present -- NO-OP (exit 0, mtime preserved)."
exit 0
}
Write-Context -TemplatePath $templatePath -OutPath $contextPath -SessionN $targetN -Ts $ts -Head $head
$note = if ($folderExists) { "healed (folder existed, _context missing)" } else { "created (folder was missing)" }
Write-Output "session-scaffold: [Ensure] session-$targetN $note"
Write-Output " context = $(Rel $contextPath $root)"
Write-Output " ts-moc = $ts (HEAD $head)"
exit 0