feat(linkedin-studio): wire contract-gate + ratify into newsletter Step 4.5 (fix #1 slice 3)
Slice 3 of fix #1 (§C2 bindende + akkumulerende): wire the deterministic §B/§C1 contract-gate into the long-form pipeline as a pre-handoff step, so mechanical violations die deterministically BEFORE the costly AI gates and never reach the operator at a judgment gate ("rettelser fester seg"). Newsletter pipeline: - New Step 4.5 (between Step 4 consistency/quality and Step 5 fact-check): (1) ratify the gate (rules.ts <-> §E-manifest 1:1; DRIFT escalates to operator, not a draft fix) and (2) gate the draft (exit 0 PASS / exit 1 BLOCK -> fix by tightening + re-run; WARN = direction, never blocks). Adopter-safe: no-op when contract-gate deps / the maskinrommet contract are absent. - Pipeline phase count 16 -> 17 across every LIVE surface (overview table + build-status + narrative + banner + schema pointer in newsletter.md; command-table rows in CLAUDE.md and README). Historical version-narrative entries left untouched. - edition-state.template.json: new "contract-gate" phase string (Step 4.5), between consistency-quality and factcheck-sweep. JSON valid; phases 16->17. CI integration (test-runner.sh, Section 14 — new): - 14a: contract-gate suite stays green (npm test exit 0) with a 33-test case-count floor (anti-erosion). - 14b: ratify invariant — rules.ts bound 1:1 to the §E-manifest. - Both KTG-internal and adopter-safe (warn/skip, never fail, when deps or the contract are absent). set +e inside the test command-substitution keeps a red suite from aborting the runner; ratify exit 1 captured via if-subshell. - SC6 anti-erosion section renumbered 14 -> 15; header comment updated. Verification: - Structure lint 81 -> 83/0/0 (contract-gate suite + ratify both green). - Documented Step 4.5 command smoke-tested on a real draft (serier/silvija-seres-motsvar/utkast/04-utkast.md): 0 BLOCK / 2 WARN -> "Gate passert", exit 0. - edition-state.template.json valid JSON; phases array = 17. foldIns capture into the pipeline phases deferred to a later slice (scope A). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ff3467de79
commit
e26d9fb659
5 changed files with 131 additions and 15 deletions
|
|
@ -19,8 +19,11 @@
|
|||
# S13. The external data-dir convention guard (M0: no command/agent/skill/hook prose
|
||||
# references a migrated user-data path in-plugin — bare or ${CLAUDE_PLUGIN_ROOT}-pinned;
|
||||
# + no ANALYTICS_ROOT in-plugin pin; + an SC2 dry-run that the tree holds no in-plugin
|
||||
# user data) in Section 13, each with a non-vacuity self-test; the assertion-count
|
||||
# anti-erosion floor (SC6) in Section 14. All are live below (Sections 8–14).
|
||||
# user data) in Section 13, each with a non-vacuity self-test; the contract-gate
|
||||
# binding guard (Slice 3: the §B/§C1 gate's own suite stays green and rules.ts
|
||||
# ratifies 1:1 against the maskinrommet §E-manifest — KTG-only, skipped for an adopter
|
||||
# shipping no deps/contract) in Section 14; the assertion-count anti-erosion floor
|
||||
# (SC6) in Section 15. All are live below (Sections 8–15).
|
||||
#
|
||||
# Usage: bash scripts/test-runner.sh
|
||||
# bash 3.2-safe: plain arrays only, no `declare -A`, no `mapfile`/`readarray`.
|
||||
|
|
@ -573,7 +576,49 @@ fi
|
|||
|
||||
echo ""
|
||||
|
||||
# --- Section 14: Assertion-Count Anti-Erosion (SC6) ---
|
||||
# --- Section 14: Contract-Gate Binding (Slice 3) ---
|
||||
echo "--- Contract-Gate Binding ---"
|
||||
|
||||
# The deterministic §B/§C1 contract-gate (scripts/contract-gate) is wired into
|
||||
# /linkedin:newsletter as Step 4.5. Two invariants belong in CI, not per-edition:
|
||||
# (14a) the gate's own test suite stays green and its case count never erodes; and
|
||||
# (14b) rules.ts stays bound 1:1 to the maskinrommet skrivekontrakt §E-manifest
|
||||
# (ratify). Both are KTG-internal: skipped (warn, never fail) for an adopter that
|
||||
# ships no contract-gate deps or no contract — so the lint stays green everywhere.
|
||||
# bash 3.2-safe; `set +e` inside the test command-substitution keeps a red npm test
|
||||
# from aborting the whole runner (set -e is active), and ratify exit 1 is captured by
|
||||
# the `if (subshell)` form (condition context is exempt from set -e).
|
||||
CG_DIR="scripts/contract-gate"
|
||||
if [ -x "$CG_DIR/node_modules/.bin/tsx" ]; then
|
||||
# 14a: the gate suite is green (npm test exit 0) and holds its case-count floor.
|
||||
CG_OUT=$( set +e; (cd "$CG_DIR" && npm test) 2>&1; echo "CG_EXIT:$?" )
|
||||
CG_EXIT=$(echo "$CG_OUT" | grep -oE 'CG_EXIT:[0-9]+' | grep -oE '[0-9]+' | head -1)
|
||||
CG_TESTS=$(echo "$CG_OUT" | grep -oE 'tests [0-9]+' | grep -oE '[0-9]+' | tail -1)
|
||||
CONTRACT_GATE_TESTS_FLOOR=33
|
||||
if [ "$CG_EXIT" = "0" ] && [ -n "$CG_TESTS" ] && [ "$CG_TESTS" -ge "$CONTRACT_GATE_TESTS_FLOOR" ]; then
|
||||
pass "contract-gate suite green: $CG_TESTS tests pass (floor $CONTRACT_GATE_TESTS_FLOOR)"
|
||||
else
|
||||
fail "contract-gate suite NOT green (exit=${CG_EXIT:-?}, tests=${CG_TESTS:-?}, floor $CONTRACT_GATE_TESTS_FLOOR) — run: (cd $CG_DIR && npm test)"
|
||||
fi
|
||||
|
||||
# 14b: ratify — rules.ts <-> §E-manifest 1:1. Skipped when the contract is absent.
|
||||
CONTRACT="${MASKINROMMET_CONTRACT:-$PLUGIN_ROOT/../../maskinrommet/docs/skrivekontrakt.md}"
|
||||
if [ -f "$CONTRACT" ]; then
|
||||
if (cd "$CG_DIR" && node --import tsx src/cli.ts --ratify) >/dev/null 2>&1; then
|
||||
pass "contract-gate ratify: rules.ts bound 1:1 to the §E-manifest (in sync)"
|
||||
else
|
||||
fail "contract-gate ratify DRIFT — rules.ts != §E-manifest; run: (cd $CG_DIR && npm run ratify)"
|
||||
fi
|
||||
else
|
||||
warn "contract-gate ratify skipped — contract absent ($CONTRACT); KTG-only invariant"
|
||||
fi
|
||||
else
|
||||
warn "contract-gate skipped — deps absent ($CG_DIR/node_modules); run: (cd $CG_DIR && npm install)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# --- Section 15: Assertion-Count Anti-Erosion (SC6) ---
|
||||
# The lint self-modifies its own checks, so a green run could mask a silently dropped
|
||||
# assertion. Pin the pre-M0 total (74 pass()+fail() invocations) as a floor; the count
|
||||
# may only grow (brief-reviewer assumption 3). Runs last so TOTAL_CHECKS sees every prior check.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue