Skip to main content

engine-review

Post-cycle engine state diagnostic. Runs the deterministic engine auditor, then frames its findings as 7-field ailment briefs with remedy paths. Phase 38 (revised S146 to consume auditor JSON instead of re-scanning sheets).

설치로 이동

소스 정보

저장소
pnils08/GodWorld
최근 소스 활동
2026년 9월 20일 20:58
감지된 SKILL.md 언어
영어
스타
1
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
engine-review
description
Post-cycle engine state diagnostic. Runs the deterministic engine auditor, then frames its findings as 7-field ailment briefs with remedy paths. Phase 38 (revised S146 to consume auditor JSON instead of re-scanning sheets).
version
1.1
updated
2026-05-30T00:00:00.000Z
tags
["engine","active"]
effort
medium
disable-model-invocation
true
# /engine-review — Engine State Diagnostic ## Purpose After a cycle runs, identify what's broken, stuck, improving, declining, or incoherent — and produce a structured brief per ailment. **Consumers are the crons, not `/sift` / `/write-edition`** — see `/run-cycle` Step 4 "Who reads what" and §What Happens After; every `/sift` reference below is historical. Write the review for the next engine session and the civic chain: what is real, what is mechanism, what is routed to engine-debug. This skill no longer scans sheets by hand. The deterministic detector lives in `scripts/engineAuditor.js` (Phase 38.1 + 38.7 + 38.8, S146). The skill is the **framer** — it reads the auditor's JSON output and turns each pattern into a seven-field ailment brief, anomaly triage, and a baseline-brief pass-through. Determinism stays in code; narrative framing stays here. This is NOT a code check. `/pre-mortem` checks the code. This checks what the code produced — is the world making sense? ## Step 1 — Run the auditor ```bash node scripts/engineAuditor.js ``` Fail loudly if exit code is non-zero. The script must produce three files in `output/` for the current cycle: - `output/engine_audit_c{XX}.json` — ailment patterns (Phase 38.1) - `output/engine_anomalies_c{XX}.json` — anomalies with triage paths (Phase 38.7) - `output/baseline_briefs_c{XX}.json` — auto-generated event briefs (Phase 38.8) If any file is missing or invalid JSON, stop. Report the failure to the user before drafting anything — a missing detector output means the framing would be guessing. ## Step 2 — Read the three JSON files Read all three. Don't re-scan sheets. The auditor has already done the deterministic work — including, after Phase 38.2/3/4 (S146 spine step 5), the mitigator check, remedy recommendation, and Tribune framing per pattern. **Audit JSON `patterns[]`** — each pattern carries: - **Detection fields** (Phase 38.1): `type` (stuck-initiative / repeating-event / math-imbalance / cascade-failure / writeback-drift / production-imbalance / improvement / incoherence / anomaly), `severity`, `cyclesInState`, `affectedEntities` (citizens / neighborhoods / initiatives / councilSeats), `evidence` (sheet, rows, fields), `description`, `detectorVersion`. - **Mitigator state** (Phase 38.2): `mitigatorState.exists`, `mitigators[]` (per-initiative effectsFiring + effectEvidence), `gap` (`no-mitigator | mitigator-stuck | mitigator-firing-but-insufficient | remedy-working`), `recommendedAction`, `ailmentCategory`. - **Remedy path** (Phase 38.3): `remedyPath.worldSide[]` (advance-initiative / propose-new-initiative / character-intervention / council-vote / mayoral-pressure, each with type/target/action/rationale/expectedEngineEffect), and `remedyPath.techSide.bugReport` (only populated when writeback chain is structurally broken). - **Tribune framing** (Phase 38.4): `tribuneFraming.storyHandles` (per desk: civic / business / culture / sports / letters), `tribuneFraming.threeLayerCoverage` (engine / simulation / user-actions one-liners pre-written), `suggestedFrontPage` boolean, `capabilityHooks` (literal phrases Phase 39.1 grades against). - **Measurement** (Phase 38.5): `measurement.available`. When true: `priorCycle`, `expectedField`, `expected`, `observed`, `delta`, `verdict` (`remedy-firing-as-expected | remedy-firing-insufficient | remedy-not-firing | remedy-overshot`), `priorRemedyType`. When false: `reason` (`no-prior-audit | no-prior-match | prior-had-no-expectation`). Top-level `measurementHistory[]` aggregates these across patterns for cross-cycle learning. **Anomalies JSON** `anomalies[]` — `triagePath` (`cover-as-story | route-to-engine-debug | suppress-until-verified`), `confidence`, `historicalContext`. On first run with no prior audit, `anomalies[]` may be empty — expected, not a failure. **Baseline-briefs JSON** `briefs[]` — `id`, `eventClass`, `subjectIds`, `neighborhood`, `cycle`, `facts`, `threeLayerHandle`, `tier` (default `C`), `promotionHints`. ## Step 3 — Frame each ailment as a 7-field brief For every pattern (excluding `type: 'improvement'` and `type: 'anomaly'` — those go to their own sections), produce a seven-field markdown block. **Most fields now have structured source data** from the auditor's enrichers — your job is to translate the structured fields into Tribune voice, not to discover or invent. | Brief field | Structured source — read this first | |---|---| | **In-world symptom** | Open from `tribuneFraming.threeLayerCoverage.simulation`; expand into a one-line headline that names the people / neighborhood feeling it. | | **Tech diagnosis** | `evidence.fields` (the cells that triggered the match) + `mitigatorState.mitigators[*].effectEvidence` (which engine field is or isn't moving). Translate sheet-column names into prose. | | **Existing mitigators** | `mitigatorState.exists` + `mitigators[]`. Each mitigator has `name`, `implementationPhase`, `cyclesInPhase`, `effectsFiring`. | | **Why working/not** | Read `mitigatorState.gap`. The four gap values map directly: `no-mitigator` = "nothing in motion to address this"; `mitigator-stuck` = "the right initiative exists but hasn't moved"; `mitigator-firing-but-insufficient` = "the program is running but the math hasn't caught up"; `remedy-working` = "the gap is closing — this is becoming an improvement story." Use the `effectEvidence.verdict` for specifics. | | **Recommended remedy path** | `remedyPath.worldSide[]` is ordered most-likely-to-work first. List the top action; mention secondary options if `worldSide.length > 1`. Only mention `techSide.bugReport` if `techSide.triggered: true` (structural break, not institutional drag). | | **Tribune framing brief** | `tribuneFraming.storyHandles` per applicable desk. Use the `angle` + `hookLine` from each non-null desk; cite `citizens` POP-IDs as the reporter's starting cast. The three layers are pre-written in `tribuneFraming.threeLayerCoverage` — quote them or paraphrase. | | **Measurement plan** | `mitigatorState.mitigators[*].effectEvidence.expectedField` + `magnitudeThreshold` + `expectedSign` give the watch list. Add one cycle-over-cycle delta target per mitigator. | If `tribuneFraming.suggestedFrontPage: true`, mark the brief with **FRONT PAGE CANDIDATE** at the top — sift uses this to seed front-page scoring. If `tribuneFraming.capabilityHooks` is non-empty, list the hooks at the bottom of the brief — they are the literal phrases Phase 39.1's `assertHighestSeverityAilmentCoveredOnFrontPage` grades against. Sift can pass them through to the relevant reporter as required coverage tokens. ### Watch for first-run startup artifacts The first audit run after S146 derived `cyclesInState` from each initiative's `LastUpdated` date string. That can produce surprisingly large numbers (Temescal at `cyclesInState=88` from "3/25/2026"). The number self-corrects once a second audit JSON exists to diff against. **Don't frame these inflated counts as "stuck for 88 cycles" in narrative copy.** Read `cyclesInState` qualitatively on first run ("stuck, with the design phase predating the current build of the auditor"); use the precise number from the second cycle onward. ### When the structured fields are empty Phase 38.2 `gap: 'remedy-working'` doesn't surface until a second audit cycle exists with measurable deltas (per engine terminal's §17 acceptance note — "inherent to the cross-cycle design"). On the first run after any pattern, `effectEvidence.verdict` will commonly read `no-history`. That's expected — write the brief as "early signal, will measure next cycle" rather than treating it as a failure of the mitigator check. ## Step 4 — Anomaly triage section For each entry in `anomalies[]`, write one paragraph: - The anomaly (what changed, by how much) - The triage call: cover as story / route to engine debug / suppress until verified - One-line reasoning, citing `confidence` and `historicalContext` If `anomalies[]` is empty, write a one-line "No anomalies flagged this cycle." Don't fabricate. Note: routing an anomaly to engine-debug means writing a separate brief at `output/engine_anomalies_c{XX}_followup.md` flagged for the engine terminal to investigate. The anomaly is suppressed from the edition until cleared. ## Step 5 — Baseline brief pass-through Don't re-write the baseline briefs. The auditor already structured them for sift. In the engine-review markdown, include: - Total brief count, broken down by `byEventClass` from the JSON's `summary` - Count with `promotionHints` (these are sift's promotion candidates) - One-line note on which neighborhoods or active ailments the briefs cluster around - Reference: `output/baseline_briefs_c{XX}.json` `/sift` reads the JSON directly when deciding promote / publish-as-baseline / suppress per Phase 39.9 tiered review. ### Known limitation — EventType taxonomy As of S146, most events in `WorldEvents_V3_Ledger` resolve to `eventType: misc-event`, so `subjectIds` on most baseline briefs is `[]`. This blocks citizen-attributed promotion (e.g., a death brief that should hint at Beverly Hayes by POP-ID can't, because the event isn't typed as `citizen-death`). Sift can still promote on neighborhood + ailment overlap from `promotionHints`, but the citizen-specific path is degraded until the engine adds a richer EventType breakdown. Tracked in ROLLOUT_PLAN as a follow-up item. ## Step 6 — Improvements section For every `type: 'improvement'` in `patterns[]`, write one short paragraph: what's working and why. Don't bury good news. Phase 38.4 (S146 spine step 5) now also threads improvement-side handles into `tribuneFraming.storyHandles` when a positive trend has a named cause — surface those as story candidates for sift, same format as ailment briefs but tagged **IMPROVEMENT** at the top. ## Step 7 — Measurement check The audit JSON carries measurement state directly: every pattern has a `measurement` field; the JSON has a top-level `measurementHistory[]` rollup. Don't read prior `engine_review_*.md` files — the structured fields already record what fired and what didn't. **The normal case is mixed (G-ER7).** Past the first cycle, the auditor always carries `measurementHistory[]`, but each cycle still surfaces *new* patterns with no prior to match against. C95, for example: 3 of 7 ailments had `measurement.available: true`; 4 were new patterns this cycle with `available: false` / `reason: 'no-prior-match'`. So **render the table by default** — the genuine first-run / no-table case is the rare exception, not the lead. Render in three parts: 1. **Per-pattern table.** Render a row for **every** pattern, not only the `available: true` ones. For `available: true`: pattern type, affected entity, prior remedy type, expected, observed, verdict. For `available: false`, gate the verdict cell on `measurement.reason`: `no-prior-match` → `—`; `prior-had-no-expectation` → `no prior expectation`. Don't omit `available: false` rows silently — a new pattern with no prior is signal, not absence. **Skip the table entirely only in the genuine first-run case**: every pattern is `available: false` AND `reason: 'no-prior-audit'` — then write the single line `First review — no prior to compare. Measurement loop will activate on next cycle.` 2. **Remedy-type track record.** Group `measurementHistory[]` by `priorRemedyType`, count verdicts (`remedy-firing-as-expected`, `remedy-firing-insufficient`, `remedy-not-firing`, `remedy-overshot`). One row per type. This is the city's multi-cycle learning signal — what kind of intervention has actually moved the world. 3. **Win callout.** If any pattern this cycle reads `verdict: 'remedy-firing-as-expected'` AND its prior-cycle entry in `measurementHistory[]` was `remedy-not-firing`, name it in voice: the gap closed — that's a story candidate, not just a data point. One line under the table. ## Output File Write to `output/engine_review_c{XX}.md`: ``` # Engine Review — Cycle {XX} **Cycle:** {XX} | **In-world:** Y{n}C{m} **Auditor version:** {from JSON detectorVersions.engineAuditor} **Source files:** - `output/engine_audit_c{XX}.json` — {N} patterns - `output/engine_anomalies_c{XX}.json` — {N} anomalies - `output/baseline_briefs_c{XX}.json` — {N} briefs ## Ailments ### 1. [In-world symptom headline] - **Tech diagnosis:** [grounded in evidence.fields] - **Existing mitigators:** [from affectedEntities.initiatives] - **Why working/not:** [gap analysis] - **Remedy path:** [world-side preferred, tech-side fallback] - **Tribune framing:** [three-layer story handles] - **Measure next cycle:** [specific fields/milestones] ### 2. [next ailment] ... ## Anomalies ### [triage-by-triage, or "No anomalies flagged this cycle"] ## Improvements ### [what's working and why] ## Baseline Briefs (sift input) - Total: {N} briefs ({byEventClass breakdown}) - With promotion hints: {N} - Cluster note: {neighborhood / ailment overlaps} - Source: `output/baseline_briefs_c{XX}.json` ## Measurement Check (from previous review) | Pattern | Affected | Prior remedy | Expected | Observed | Verdict | |---|---|---|---|---|---| | [type] | [neighborhood / initiative] | [priorRemedyType] | [expected] | [observed] | [verdict] | (First-run case: `First review — no prior to compare. Measurement loop will activate on next cycle.`) [Win callout, if any pattern flipped from `remedy-not-firing` last cycle to `remedy-firing-as-expected` this cycle.] ### Remedy-type track record | Remedy type | Firing-as-expected | Firing-insufficient | Not-firing | Overshot | |---|---|---|---|---| | [priorRemedyType] | [N] | [N] | [N] | [N] | ## Summary - Ailments: {count} ({severity breakdown}) - Anomalies: {count} ({triage breakdown}) - Improvements: {count} - Baseline briefs: {count} ({with-promotion-hints count}) - Measurements: {firing-as-expected count} / {total measured} firing as expected; {not-firing count} not firing ``` ## Where This Sits Step 4 in the run-cycle chain. After pre-flight, pre-mortem, and cycle execution. Before build-world-summary. World summary reads this file and incorporates the framing; sift reads the same file plus the baseline-briefs JSON for editorial planning. ## Why this rewrite (S146 — two passes) **First pass (after Phase 38.1 + 38.7 + 38.8):** scanned 11 sheets by hand → consume audit + anomalies + baseline-briefs JSON. Detection moved out of the skill into `scripts/engineAuditor.js`. Skill became the framer. **Second pass (after Phase 38.2 + 38.3 + 38.4, this rewrite):** even the framing logic mostly moves into structured fields. The auditor now writes `mitigatorState`, `remedyPath`, and `tribuneFraming` per pattern — which is what the skill was previously synthesizing by hand. The skill's remaining job: translate structured engine fields into Tribune voice, surface front-page candidates, and gate anomalies. Most assertions about "what to write" come from `tribuneFraming.threeLayerCoverage` directly. Determinism in code, judgment in the skill — and the judgment surface keeps shrinking as the auditor learns. Sources: `docs/engine/archive/PHASE_38_PLAN.md` §6 (first rewrite) and §16.5 (this rewrite).
GitHub에서 보기