← back to Norma
TK-11383: enforce the designerschat enrollment hold at the PUBLISHER too
72f0976838a43652d9ac83b00bbbdc410eb6a54f · 2026-09-13 11:36:39 -0700 · Steve Abrams
Kimi second-model review of 123570c: a builder-only hold guard is defeated by a
hand-edit of accounts.json, a committed `--include-held` output, an old
checkout, or Meta expanding the pages_show_list allowlist. The irreversible
action — a public post — lives in daily-cadence.js, so the guard belongs there
too, using the mechanism that file already honours.
- account-themes.json: convert the designerschat override from a keyword to a
`skip`. daily-cadence.js already excludes any handle with a skip
(eligible = HANDLES.filter(h => !themeFor(h).skip)), so even if designerschat
re-enters accounts.json by ANY path, the cadence will not post to it.
A skip can only PREVENT a post, never cause one.
- build-registry.js: a MISSING enrollment-hold.json now warns loudly instead of
silently failing open (a corrupt file already fails closed). The hard backstop
for the account that matters is now the publisher-side skip above, which does
not depend on this file existing.
Verified two independent layers: (1) default rebuild still reproduces the
committed accounts.json with byte-identical records and no designerschat
(set-diff, not a count check — Kimi's nit); (2) injecting designerschat into a
registry via --include-held and running the publisher's exact eligibility logic
excludes it (skip honoured). Nothing posted, no registry rewritten.
Undo: git revert HEAD.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M agents/instagram-agent/account-themes.jsonM agents/instagram-agent/build-registry.js
Diff
commit 72f0976838a43652d9ac83b00bbbdc410eb6a54f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Sep 13 11:36:39 2026 -0700
TK-11383: enforce the designerschat enrollment hold at the PUBLISHER too
Kimi second-model review of 123570c: a builder-only hold guard is defeated by a
hand-edit of accounts.json, a committed `--include-held` output, an old
checkout, or Meta expanding the pages_show_list allowlist. The irreversible
action — a public post — lives in daily-cadence.js, so the guard belongs there
too, using the mechanism that file already honours.
- account-themes.json: convert the designerschat override from a keyword to a
`skip`. daily-cadence.js already excludes any handle with a skip
(eligible = HANDLES.filter(h => !themeFor(h).skip)), so even if designerschat
re-enters accounts.json by ANY path, the cadence will not post to it.
A skip can only PREVENT a post, never cause one.
- build-registry.js: a MISSING enrollment-hold.json now warns loudly instead of
silently failing open (a corrupt file already fails closed). The hard backstop
for the account that matters is now the publisher-side skip above, which does
not depend on this file existing.
Verified two independent layers: (1) default rebuild still reproduces the
committed accounts.json with byte-identical records and no designerschat
(set-diff, not a count check — Kimi's nit); (2) injecting designerschat into a
registry via --include-held and running the publisher's exact eligibility logic
excludes it (skip honoured). Nothing posted, no registry rewritten.
Undo: git revert HEAD.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
agents/instagram-agent/account-themes.json | 2 +-
agents/instagram-agent/build-registry.js | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/agents/instagram-agent/account-themes.json b/agents/instagram-agent/account-themes.json
index c8f89a8..5113d9f 100644
--- a/agents/instagram-agent/account-themes.json
+++ b/agents/instagram-agent/account-themes.json
@@ -189,7 +189,7 @@
},
"_email_sweep_note": "Below: owned/active accounts found in the 2026-08-12 email sweep, staged for the moment each IG is connected to its Page (build-registry then enrolls it). Inert until the handle is linked. protestdaily is skip — it's a news/media account, not a wallcovering product feed; give it bespoke content, never the DW-product cadence.",
"designerschat": {
- "keyword": "interior design"
+ "skip": "enrollment reverted by Steve (e0dcc47) — linked but deliberately NOT in the public cadence; publisher-side backstop to enrollment-hold.json (TK-11383). If it ever re-enters accounts.json (hand-edit / --include-held / Meta allowlist expansion), daily-cadence still excludes it here."
},
"beverlyandhillsdesigns": {
"keyword": "glamour interior design"
diff --git a/agents/instagram-agent/build-registry.js b/agents/instagram-agent/build-registry.js
index 70532fe..a42331e 100644
--- a/agents/instagram-agent/build-registry.js
+++ b/agents/instagram-agent/build-registry.js
@@ -199,6 +199,14 @@ async function main() {
process.exit(1);
}
holdReadError = 'enrollment-hold.json not present';
+ // Missing (vs corrupt) is fail-OPEN by necessity — an old checkout predating
+ // the file must still build — but it is NOT silent: warn loudly, because
+ // `rm enrollment-hold.json` would otherwise disable this guard quietly. The
+ // hard backstop for the one account that matters (designerschat) is a `skip`
+ // in account-themes.json, which daily-cadence.js (the actual publisher)
+ // honours regardless of this file (Kimi review, TK-11383).
+ console.error('WARNING: enrollment-hold.json is absent — the builder-side hold guard is OFF.');
+ console.error(' The publisher-side skip in account-themes.json still applies; restore this file to re-arm the builder guard.');
}
const held = [];
for (const h of Object.keys(holdMap)) {
← 123570c TK-11383: make build-registry.js stop silently changing who
·
back to Norma
·
TK-11383: enforce the enrollment hold at the PUBLISHER too, 3bdc7a5 →