* test(#4243): failing-first regressions for bold-field anchoring and frontmatter round-trip * fix(#4243): anchor stateReplaceField bold form to line start The bold branch of stateReplaceField carried no ^ and no /m flag, so a bold label quoted mid-sentence inside prose — the issue's **Status:** inside an Accumulated Context bullet — captured the rewrite and destroyed the rest of its line, silently, whenever a whole-body caller fed the function every section (beginPhaseCore's tryField, advancePlanCore's Status/Current Plan writes). The plain branch was always line-anchored; only the bold branch lagged. Anchored to ^([ \t]*\*\*Field:\*\*[ \t]*) with /im, reusing #4010's same-line confinement idiom for the leading class (deliberately not the issue's suggested ^\s* — it can consume the newlines before the label into the match) and #4186's recognition-by-anchoring discipline. Frontmatter half of the issue (unknown-key drops, invented milestone defaults) is already fixed on next by #2202/#3216/#4129; pinned here with the issue's requested regression fixtures. * test(#4243): pin survival contract, not derived percent, in frontmatter rows Bench RED run caught two assertion defects in the pin rows: the unknown progress subkey re-parses as a quoted scalar ('77' vs 77), and percent is a declared derived subkey - omitted under the #3573 no-roadmap withhold, recomputed when measured (#4129) - so pinning its value over-pins derived semantics. The rows now pin what the issue demands: unknown/custom keys survive, stored counters are kept under the withhold, milestone identity is never reset to invented defaults. * chore(#4243): changeset for the anchored bold-field fix * chore(#4243): backfill PR number in changeset
This commit is contained in:
@@ -553,7 +553,22 @@ export function stateReplaceField(content: string, fieldName: string, newValue:
|
||||
// `(.*)` captured the following line and the rebuild discarded it — the #4010
|
||||
// data-loss. ADR-3180 §7.7 makes stateExtractField the same-line-confined owner;
|
||||
// this aligns the writer to it.
|
||||
const boldPattern = new RegExp(`(\\*\\*${escaped}:\\*\\*[ \\t]*)(.*)`, 'i');
|
||||
//
|
||||
// #4243: the bold form is also ANCHORED to line start, with same-line leading
|
||||
// whitespace only. The pre-fix pattern carried no `^` and no `m` flag, so a
|
||||
// bold label quoted MID-SENTENCE inside prose — an Accumulated Context bullet
|
||||
// mentioning `**Status:**` — captured the rewrite and destroyed the rest of
|
||||
// its line, silently, whenever a whole-body caller fed this function every
|
||||
// section (beginPhaseCore's tryField, advancePlanCore's Status/Current Plan
|
||||
// writes). The plain branch below was always line-anchored; only the bold
|
||||
// branch lagged. Anchoring reuses #4010's same-line confinement idiom (the
|
||||
// leading class is `[ \t]*`, deliberately NOT the `\s*` the issue suggested —
|
||||
// `^\s*\*\*` can consume the newlines before the label into the match and
|
||||
// drop them on rebuild) and #4186's recognition-by-anchoring discipline: a
|
||||
// write target must BE the whole declared line shape, never a substring
|
||||
// guess inside prose. `$` is explicit-and-inert (`.` never crosses line
|
||||
// terminators) and documents that the match ends at end-of-line.
|
||||
const boldPattern = new RegExp(`^([ \\t]*\\*\\*${escaped}:\\*\\*[ \\t]*)(.*)$`, 'im');
|
||||
if (boldPattern.test(content)) {
|
||||
return content.replace(boldPattern, (_match, prefix: string) => joinFieldReplacement(prefix, newValue));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user