Skip to content

fix(isa-utils): function replacer in appendDecisionRow so ISA dollar amounts don't backref-expand - #2045

Closed
alexfry-axeai wants to merge 1 commit into
danielmiessler:mainfrom
alexfry-axeai:fix/isa-utils-decisions-backref
Closed

fix(isa-utils): function replacer in appendDecisionRow so ISA dollar amounts don't backref-expand#2045
alexfry-axeai wants to merge 1 commit into
danielmiessler:mainfrom
alexfry-axeai:fix/isa-utils-decisions-backref

Conversation

@alexfry-axeai

Copy link
Copy Markdown

What

appendDecisionRow (in LifeOS/install/hooks/lib/isa-utils.ts) appends the auto-rewind Decisions row using a string replacement built from the existing Decisions body:

return content.replace(decisionsRe, `${match[1]}${match[2].trimEnd()}\n${row}\n${match[3]}`);

The bug

That Decisions body routinely contains literal dollar amounts. String.prototype.replace interprets $1, $2, $&, etc. in a replacement string as regex backreferences — so an amount like $14,000 is read as capture group 1 followed by 4,000. On any resume of a completed ISA, the rewrite expands those into the captured section text, duplicating the ## Decisions heading and shredding the section (a $14,000 becomes <group-1>4,000, with fragment lines and repeated headers).

The fix

Use a function replacer, whose return value is inserted verbatim with no $ interpretation:

return content.replace(decisionsRe, () => `${match[1]}${match[2].trimEnd()}\n${row}\n${match[3]}`);

One line of behavior change, plus a short explanatory comment. appendDecisionRow is exported so it can be unit-tested.

Test

Adds isa-utils.test.ts, a regression test using synthetic $1/$2/$3/$4-prefixed amounts. It asserts every amount survives intact, exactly one ## Decisions heading remains, and the rewind row lands under Decisions. Fails on the old string replacement, passes on the fix.

bun test LifeOS/install/hooks/lib/isa-utils.test.ts   # 1 pass

…amounts don't backref-expand

appendDecisionRow appended its auto-rewind row with a STRING replacement built
from the existing Decisions body. That body carries literal dollar amounts, and
String.prototype.replace interprets $1/$2/$& in a replacement string as regex
backreferences, so an amount like $14,000 expanded to <capture-group-1>4,000 —
duplicating the ## Decisions header and shredding the section on any resume of a
completed ISA. Switch to a function replacer, whose return value is inserted
verbatim. Adds a regression test (synthetic amounts).
@danielmiessler

Copy link
Copy Markdown
Owner

Ported with credit, test included. Closing, next release. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants