[CLAUDE] Docs: S151 closeout — bootstrap + trio-AUTO đầu tiên + gói 3-máy vá sống + bookend DEEP trả nợ JUMP (tally #53=53, AS-17 promote)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m38s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m38s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@ -98,6 +98,22 @@ function Replace-LineOnce([string]$text, [string]$pattern, [string]$newLine, [st
|
||||
return $rx.Replace($text, $ev, 1)
|
||||
}
|
||||
|
||||
# Style-preserving field replace (fix S151 format-fork): the S150 signal-write re-serialized
|
||||
# this file via ConvertTo-Json (BOM + CRLF + two-space after colon), so the fixed-string
|
||||
# replacer above stopped matching (0 match => exit 7 every session after every bookend).
|
||||
# This variant's pattern carries TWO capture groups (prefix)(suffix); the matched prefix and
|
||||
# suffix are kept verbatim, so whichever spacing/EOL shape the file has SURVIVES the write.
|
||||
# Same exactly-one-match fail-loud as Replace-LineOnce (shape-drift still refuses to write).
|
||||
function Replace-FieldOnce([string]$text, [string]$pattern, [string]$valueLiteral, [string]$what) {
|
||||
$rx = New-Object System.Text.RegularExpressions.Regex($pattern, [System.Text.RegularExpressions.RegexOptions]::Multiline)
|
||||
$n = $rx.Matches($text).Count
|
||||
if ($n -ne 1) {
|
||||
Fail-Loud "surgical replace '$what' expected exactly 1 match, found $n - counter-file shape drift; refusing to write." 7
|
||||
}
|
||||
$ev = [System.Text.RegularExpressions.MatchEvaluator]({ param($m) $m.Groups[1].Value + $valueLiteral + $m.Groups[2].Value }.GetNewClosure())
|
||||
return $rx.Replace($text, $ev, 1)
|
||||
}
|
||||
|
||||
function Json-Escape([string]$s) {
|
||||
# Minimal JSON string escaping. Event text is authored quote/backslash-free, but stay safe.
|
||||
$s = $s -replace '\\', '\\'
|
||||
@ -210,25 +226,33 @@ else {
|
||||
}
|
||||
$eventJson = Json-Escape $event
|
||||
|
||||
# ---- surgical edits on the raw text (preserve formatting / emoji / LF byte-exact) ----
|
||||
# ---- surgical edits on the raw text (style-preserving: tolerate BOTH the original
|
||||
# ---- surgical shape (LF / one-space) AND the ConvertTo-Json shape (CRLF / two-space) ----
|
||||
$new = $rawText
|
||||
$new = Replace-LineOnce $new '^ "counter": \d+,$' (' "counter": ' + $newCounter + ',') 'counter'
|
||||
$new = Replace-LineOnce $new '^ "last_ticked_session": "[^"]*",$' (' "last_ticked_session": "' + $Session + '",') 'last_ticked_session'
|
||||
$new = Replace-LineOnce $new '^ "last_ticked_head": "[^"]*",$' (' "last_ticked_head": "' + $headSha + '",') 'last_ticked_head'
|
||||
$new = Replace-LineOnce $new '^ "last_ticked_at": "[^"]*",$' (' "last_ticked_at": "' + $tickDate + '",') 'last_ticked_at'
|
||||
$new = Replace-FieldOnce $new '^(\s{4}"counter":\s+)\d+(,\r?)$' ("$newCounter") 'counter'
|
||||
$new = Replace-FieldOnce $new '^(\s{4}"last_ticked_session":\s+")[^"]*(",\r?)$' $Session 'last_ticked_session'
|
||||
$new = Replace-FieldOnce $new '^(\s{4}"last_ticked_head":\s+")[^"]*(",\r?)$' $headSha 'last_ticked_head'
|
||||
$new = Replace-FieldOnce $new '^(\s{4}"last_ticked_at":\s+")[^"]*(",\r?)$' $tickDate 'last_ticked_at'
|
||||
|
||||
# ---- append ONE history entry: insert before the array close (anchored at EOF, exactly once) ----
|
||||
$entry = " {`n" +
|
||||
" `"at`": `"$tickDate`",`n" +
|
||||
" `"session`": `"$Session`",`n" +
|
||||
" `"event`": `"$eventJson`"`n" +
|
||||
" }"
|
||||
$histRx = New-Object System.Text.RegularExpressions.Regex('(\n \})(\n \]\n\}\n?)$', [System.Text.RegularExpressions.RegexOptions]::Singleline)
|
||||
# ---- append ONE history entry: insert before the array close (anchored at EOF, exactly once).
|
||||
# Shape-tolerant (fix S151 format-fork): match ANY indent + CRLF-or-LF at EOF; the inserted
|
||||
# entry reuses the file's own EOL and the LAST entry's own indent, so both shapes stay intact.
|
||||
$histRx = New-Object System.Text.RegularExpressions.Regex('(\r?\n)([ \t]+)\}([ \t]*)(\r?\n[ \t]*\][ \t]*\r?\n\}[ \t]*\r?\n?)$', [System.Text.RegularExpressions.RegexOptions]::Singleline)
|
||||
$histN = $histRx.Matches($new).Count
|
||||
if ($histN -ne 1) {
|
||||
Fail-Loud "history array-close anchor expected exactly 1 match at EOF, found $histN - counter-file shape drift; refusing to write." 7
|
||||
}
|
||||
$histEv = [System.Text.RegularExpressions.MatchEvaluator]({ param($m) $m.Groups[1].Value + ",`n" + $entry + $m.Groups[2].Value }.GetNewClosure())
|
||||
$histEv = [System.Text.RegularExpressions.MatchEvaluator]({ param($m)
|
||||
$eol = $m.Groups[1].Value
|
||||
$ind = $m.Groups[2].Value # indent of the LAST entry's closing brace
|
||||
$fld = $ind + ' ' # field indent = one level deeper
|
||||
$entry = $ind + '{' + $eol +
|
||||
$fld + '"at": "' + $tickDate + '",' + $eol +
|
||||
$fld + '"session": "' + $Session + '",' + $eol +
|
||||
$fld + '"event": "' + $eventJson + '"' + $eol +
|
||||
$ind + '}'
|
||||
$m.Groups[1].Value + $m.Groups[2].Value + '}' + $m.Groups[3].Value + ',' + $eol + $entry + $m.Groups[4].Value
|
||||
}.GetNewClosure())
|
||||
$new = $histRx.Replace($new, $histEv, 1)
|
||||
|
||||
# ---- validate the result is still parseable BEFORE we touch disk ----
|
||||
|
||||
Reference in New Issue
Block a user