Skip to content

feat(scripts): fill placeholders without destroying the filling machinery - #590

Open
hyperpolymath wants to merge 2 commits into
mainfrom
fix/placeholder-substituter
Open

feat(scripts): fill placeholders without destroying the filling machinery#590
hyperpolymath wants to merge 2 commits into
mainfrom
fix/placeholder-substituter

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

The estate-wide "fill derivable placeholders" sweep replaced {{TOKEN}} by plain text substitution across every file. It drew 141 review findings across 90 repositories, and one is severe:

sed "s/{{PROJECT_NAME}}/$name/g"  →  sed "s/Conative Gating/$name/g"
sed -e "s/{{DATE}}/$DATE/g"       →  sed -e "s/2026-08-05/$DATE/g"

Those are the scripts whose job is to perform template substitution. Filling the left-hand side of their own sed expressions means template application silently stops working — and stays invisible until someone mints a repository and gets a half-substituted tree. 289 pull requests carry that change and are being closed in favour of this.

The rule plain replacement cannot express: a placeholder is sometimes a value to fill and sometimes the subject being discussed. Three contexts make it the subject, all excluded here:

  1. Left-hand side of a substitutions/{{X}}/…/, s|{{X}}|…| (alternate delimiters handled). The token is a search pattern.
  2. Files whose topic IS the tokenREQUIRES_INITIALISATION.md, QUICKSTART*. Filling those produced "Replace laminar, laminar, {{DEPS}} with actuals".
  3. Another tool's delimitersjust uses {{ARGS}} natively; reporting it as unfilled leaves a repo permanently "not initialised".

Template sources are skipped outright — their tokens are the deliverable.

ok  sed LHS placeholders survive (the 90-repo corruption)
ok  sed LHS {{DATE}} survives
ok  alternate sed delimiter | also protected
ok  ordinary prose IS substituted
ok  QUICKSTART left alone (its subject is the token)
ok  REQUIRES_INITIALISATION left alone
ok  template source keeps its tokens
ok  just's own {{ARGS}} never touched
9 passed, 0 failed

🤖 Generated with Claude Code

…nery

The estate-wide "fill derivable placeholders" sweep replaced `{{TOKEN}}` by
plain text substitution across every file. It drew 141 review findings across
90 repositories, and one of them is severe:

    sed "s/{{PROJECT_NAME}}/$name/g"  ->  sed "s/Conative Gating/$name/g"
    sed -e "s/{{DATE}}/$DATE/g"       ->  sed -e "s/2026-08-05/$DATE/g"

Those are the scripts whose JOB is to perform template substitution. Filling
the left-hand side of their own `sed` expressions means template application
silently stops working, and stays invisible until someone mints a repository
from the template and gets a half-substituted tree. 289 pull requests carry
that change.

The rule plain replacement cannot express: a placeholder is sometimes a VALUE
TO FILL and sometimes the SUBJECT BEING DISCUSSED. Three contexts make it the
subject, and all three are excluded here:

  1. The left-hand side of a substitution — `s/{{X}}/.../`, `s|{{X}}|...|`.
     The token is a search pattern. Alternate delimiters are handled.
  2. Files whose topic IS the token — REQUIRES_INITIALISATION.md lists what is
     still to fill; QUICKSTART says "Replace {{DEPS}} with actuals". Filling
     those produced "Replace laminar, laminar, {{DEPS}} with actuals".
  3. Another tool's own delimiters — `just` uses {{ARGS}} natively in recipe
     bodies. It is not a template placeholder, and reporting it as unfilled
     leaves a repository permanently "not initialised".

Template sources (*.template, templates/) are skipped outright: their tokens
are the deliverable.

scripts/tests/fill-placeholders-test.sh asserts all of it, and its first three
cases reproduce the exact 90-repository corruption this replaces. 9/9 pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
This was referenced Aug 6, 2026
This was referenced Aug 6, 2026
Three repositories show the same fault the substituter must prevent, and it is
distinct from the sed-LHS corruption this script already handles:
{{PROJECT_NAME}} was filled with a human display name in slots that require a
machine-safe identifier, producing verbatim

    (name 'BoJ Server Mk2)
    url "https://github.com/x/BoJ Server Mk2"
    @software{BoJ Server Mk2_2026,

all syntactically invalid — and one repository carried
`Octad-Recover (working title — see naming section below)` into the same slots.

A value can be correct AND wrong depending on where it lands. Identifier and
URL contexts are now recognised — Guix/Scheme `(name ...)`, BibTeX entry keys,
URLs, container tag positions, manifest identifier fields — and a value that is
not slug-safe is NOT written there. If the map supplies PROJECT_SLUG or
REPO_SLUG, those slots get it; otherwise the token is left in place and the
refusal is reported, and the run exits non-zero.

⚠ Leaving the token visible is deliberate. An unfilled {{PROJECT_NAME}} is
obviously unfinished; `(name 'BoJ Server Mk2)` looks plausible and fails later,
somewhere else.

Also confirmed by test that `just`'s own {{project}} interpolation survives —
another repository had it clobbered to a literal `project_ovine`. This script
is mapping-driven and case-sensitive, so unmapped tokens are untouched, but the
case now has a test so it stays that way.

14/14 pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
@sonarqubecloud

sonarqubecloud Bot commented Aug 6, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@@ -0,0 +1,193 @@
#!/usr/bin/env python3
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