Commit Graph

49 Commits

Author SHA1 Message Date
Claude Code
328e9ba613 Task #138: Wiki.js subscriber tier sync via GraphQL (REQ-2026-04-15-subscriber-wiki-auth)
- src/services/wikijsSync.js: GraphQL client for Wiki.js at subscribers.firefrostgaming.com
  - syncWikiUser(discordId, username, tierLevel): creates user if not exists, updates group if exists
  - demoteToAwakened(discordId): downgrades group on cancellation/chargeback/refund
  - Email convention: {discordId}@firefrost.local (unique internal addresses)
  - Tier → group mapping: 1=Awakened, 2=Elemental, 3=Knight, 4=Master, 5=Legend, 6=Sovereign
  - Silent-fail: never breaks the Stripe webhook
- src/routes/stripe.js: hooked into 4 lifecycle paths:
  - checkout.session.completed → syncWikiUser (non-blocking)
  - customer.subscription.deleted → demoteToAwakened
  - charge.dispute.created (chargeback) → demoteToAwakened
  - charge.refunded (refund ban) → demoteToAwakened
- .env.example: added WIKIJS_URL, WIKIJS_API_KEY, DISCORD_ISSUE_WEBHOOK_URL

PRE-REQ: Michael must create 6 groups in Wiki.js admin + generate API key before deploy.
2026-04-16 00:15:55 -05:00
Claude Code
49f8f79c2f Discord Action Log: audit trail for Arbiter's Discord actions (Issue #1)
- Migration 142: discord_action_log table (action_type, discord_id, username, details JSONB, success, error_message)
- src/services/discordActionLog.js: silent-fail logAction() writes to DB with console fallback
- src/discord/reactionRoles.js: log reaction_role_add / reaction_role_remove with roleId + emoji + messageId
- src/discord/events.js: log wanderer_assigned + welcome_dm on guildMemberAdd
- src/routes/stripe.js: log link_reminder_dm success/failure on post-checkout
- src/routes/admin/discord-log.js: GET /admin/discord-log (recent 100, filter by action_type + search by discord_id/username)
- src/views/admin/discord-log.ejs: color-coded action type badges, success/fail pills, details column
- layout.ejs: sidebar link under Monitoring section
- admin/index.js: wired discordLogRouter

All JS node --check clean. EJS ejs.compile() clean.
2026-04-16 00:07:08 -05:00
Claude Code
e6552864f0 Bitch Bot: full source scaffold for NeoForge 1.21.1 (REQ-2026-04-15-bitch-bot)
First-boot server provisioner. Named by Holly. Architecture per Gemini 4-round
consultation. Drops a provision.json in server root, mod runs once on
ServerStartedEvent: pastes spawn schematic, places TP command blocks pointing
at the original level.dat spawn, sets worldspawn, gamerules, YAWP region file,
self-destructs by renaming jar to .jar.disabled.

Files (services/bitch-bot/1.21.1/):
- build.gradle / settings.gradle / gradle.properties / gradle wrapper (mirrors rules-mod 1.21.1)
- META-INF/neoforge.mods.toml
- BitchBot.java        — @Mod entry, ServerStartedEvent listener, Throwable net
- Provisioner.java     — sequenced step runner, per-step try/catch, success tracking gates self-destruct
- ProvisionConfig.java — Gson POJO matching provision.json schema verbatim
- SchematicLoader.java — HTTP download + SHA-256 verify + Sponge v2 .schem parser (NbtIo + varint + BlockStateParser palette)
- CommandBlockPlacer.java — impulse command blocks with /tp @p baked into CommandBlockEntity
- SignPlacer.java      — oak signs, 4-line front text via SignBlockEntity#setText
- YawpConfigWriter.java — drops region JSON to world/serverconfig/yawp/regions/{name}.json
- SelfDestruct.java    — ProtectionDomain → CodeSource → jar rename, Windows fallback to deleteOnExit

Plus services/bitch-bot/CLAUDE.md (project doc) and sample-provision.json.

NOT COMPILED — no Java/Gradle on Nitro per repo CLAUDE.md. Compile on Dev Panel:
  cd /opt/mod-builds/firefrost-services/services/bitch-bot/1.21.1
  source use-java 21
  /opt/gradle-8.8/bin/gradle build --no-daemon

Risk areas flagged in CLAUDE.md for first compile: schematic parser (untested
against real WorldEdit output), YAWP file format (best-guess schema).
2026-04-15 12:47:08 -05:00
Claude
364d6411ec Archive all completed REQs — bridge clear for Bitch Bot task 2026-04-15 17:19:02 +00:00
Claude Code
b0b69fb172 Task #166: Trinity Console Issue Tracker (REQ-2026-04-14-issue-tracker)
- Migration 141: issues, issue_attachments, issue_comments
- src/routes/admin/issues.js: session-auth UI routes (list/new/detail/status/assign/comments/upload)
- src/routes/api.js: /api/internal/issues REST surface (Bearer token)
- src/services/issueNotifier.js: Discord webhook helper (DISCORD_ISSUE_WEBHOOK_URL)
- Views: index (list+filters), new (mobile-first form), detail (screenshots, comments, workflow)
- layout.ejs: sidebar nav link
- package.json: add multer ^1.4.5-lts.1
- CSRF token passed via query param on multipart forms (body unparsed when csurf runs)
- Screenshots stored in services/arbiter-3.0/uploads/issues/ (10MB limit, 6 files max)
2026-04-15 01:53:18 -05:00
Claude Code
263a7e3e47 Task #163: backfill script for empty task descriptions (6/15 matched) 2026-04-15 01:46:11 -05:00
Claude Code
722771e305 bridge: archive SCC + code-queue-badge-fix; update ACTIVE_CONTEXT 2026-04-15 01:33:01 -05:00
Claude (Chronicler #83 - The Compiler)
cef0d8465e Fix: skip stale DB versions for installer-detected servers without file_id
Installer-method servers had full filenames as current_version (e.g.
"DeceasedCraft_Beta_DH_Edition_5.10.16") which prevented reaching
pending_calibration. Now only uses DB current_version if file_id is
also set (validated) or detection method isn't installer.

Migration clears existing stale rows → pending_calibration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 06:33:57 -05:00
Claude (Chronicler #83 - The Compiler)
27b2744786 Truth File strategy: never seed from latest, calibrate or detect
CheckModpackUpdates:
- Reads .modpack-checker.json Truth File from server filesystem
- Falls back to manifest.json, extracts fileID, writes Truth File
- NEVER seeds current_version from latest API result
- Unknown version → status: pending_calibration (not up_to_date)
- Removed seedCurrentVersion heuristic — replaced with Truth File
- writeTruthFile() helper writes .modpack-checker.json via Wings

ModpackAPIController:
- calibrate() now writes Truth File after DB update
- Persists across server reinstalls and cron runs

wrapper.tsx:
- pending_calibration: shows "Version unknown" + "Identify Version" button
- Ignored servers: muted card with "Resume" button (not hidden)
- Extracted renderCalibrateDropdown() for reuse
- Error state shows message instead of vanishing

Migration:
- Updates existing unknown+detected rows to pending_calibration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 06:09:05 -05:00
Claude (Chronicler #83 - The Compiler)
0caddef86d Fix async error handling + build.sh copy/inject separation
wrapper.tsx:
- Added error state — shows graceful message instead of silent vanish
- useEffect catch sets error string, not null data
- refresh() catch sets error string, not empty catch
- Error UI shows gray card with message in widget slot

build.sh:
- ALWAYS copies TSX files (even on reinstall — fixes stale component bug)
- Separated copy step from injection step
- ErrorBoundary upgrade path: removes bare <ModpackVersionCard />,
  replaces with wrapped version
- Imports added independently (not as one sed block)
- Renumbered sections for clarity

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 01:31:44 -05:00
Claude (Chronicler #83 - The Compiler)
7e3ffe2577 Fix: clean version extraction + short display names
ModpackApiService: regex extracts semver from CurseForge displayName
  "All the Mods 9-0.1.0" → version: "0.1.0", display_name: full string

Widget: short name + version helpers
  "All the Mods 9 - ATM9" → "ATM9"
  Display: "ATM9 0.1.0 → 1.0.0 ↑" (update) or "✓ ATM9 — 1.0.0" (current)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 01:09:57 -05:00
Claude (Chronicler #83 - The Compiler)
28608e9fa8 Build pipeline hardening: ErrorBoundary, no PHP copies, TS pre-flight
- ErrorBoundary.tsx wraps widget — crashes show fallback, not blank void
- build.sh v1.1.0: removed ALL PHP file copies (Chronicler deploys manually)
- Added set -e / set -u for fail-fast
- Added TypeScript pre-flight check (yarn tsc --noEmit) before build
- Added dynamic Blueprint controller detection via find
- Widget injection now wrapped in <ModpackErrorBoundary>
- Pre-commit PHP lint hook at scripts/pre-commit-hook.sh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 00:17:30 -05:00
Claude (Chronicler #83 - The Compiler)
be6b14bd67 Housekeeping: archive stale manifest.json dispatch from responses
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:50:00 -05:00
Claude (Chronicler #83 - The Compiler)
dd05a41567 v1.1.0 Priority 3b: zero-click widget with recalibrate + ignore
Widget redesign:
- Zero-click: loads cached status on mount via GET /status (no API calls)
- Shows platform icon + modpack name + version comparison
- Orange background + arrow (current → latest) when update available
- Cyan + checkmark when up to date
- Refresh button triggers manual check
- Calibrate button opens dropdown with last 10 releases
- Ignore button hides non-modpack servers
- Current release highlighted in calibrate dropdown

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:44:21 -05:00
Claude (Chronicler #83 - The Compiler)
b84958c0ee v1.1.0 Priorities 2-5: date seeding, new endpoints, BCC detection
Priority 2 — Date-time seeding:
- fetchFileHistory() for CurseForge, Modrinth, FTB
- seedCurrentVersion() matches release closest to server install date
- Falls back to latest if no history or no install date

Priority 3 — New endpoints:
- GET /servers/{server}/status — zero-click cached status
- GET /servers/{server}/releases — recalibrate dropdown (10 releases)
- POST /servers/{server}/calibrate — save user's version selection
- POST /servers/{server}/ignore — toggle is_ignored flag

Priority 5 — BCC log parsing:
- detectFromBccLog() reads logs/latest.log for BetterCompatibilityChecker
- Extracts modpack name + version from BCC output line
- Skips CHANGE_ME values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:42:34 -05:00
Claude (Chronicler #83 - The Compiler)
9415c1b984 v1.1.0 Priority 1+2b: file ID comparison + manifest version extraction
- Migration: adds current_file_id, latest_file_id, is_ignored columns
- ModpackApiService: all 4 platforms now return file_id in response
- CheckModpackUpdates: file ID comparison (preferred) with string fallback
- detectCurseForge: extracts manifest['version'] as installed_version
- Cron skips is_ignored servers
- Detection priority: manifest version > egg var > DB record > seed latest

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:38:41 -05:00
Claude (Chronicler #83 - The Compiler)
32e2d726bb Fix: manualCheck now checks modpack_installations + cron cache
Detection priority in manualCheck():
1. Egg variables
2. modpack_installations table (NEW)
3. DaemonFileRepository file scan
4. Cached cron data from modpackchecker_servers (NEW)

Also returns current_version and update_available in response
so the console widget can show version comparison.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:09:23 -05:00
Claude (Chronicler #83 - The Compiler)
68ee40e89d Fix: seed current_version from latest on first detection
When a server is first detected, current_version is set to latest_version
(the pack was just installed = it's current). On future runs, if the API
returns a newer latest_version, the stored current_version stays and we
detect the update. Also preserves egg variable and existing DB values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:04:04 -05:00
Claude (Chronicler #83 - The Compiler)
31f245a1b9 Fix: trim CurseForge API key + add debug logging for 403 diagnosis
Key may have whitespace from dbGet. Added Log::debug with key length
and modpack ID to diagnose the 403.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:57:23 -05:00
Claude (Chronicler #83 - The Compiler)
36800ae7a7 Fix: remove orderBy on modpack_installations — table has no id column
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:52:22 -05:00
Claude (Chronicler #83 - The Compiler)
87d834942a Fix: remove finalized filter, use latest installation per server
Most modpack_installations rows have finalized=0 — filter was excluding
nearly everything. Now takes the most recent installation row regardless
of finalized status.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:48:37 -05:00
Claude (Chronicler #83 - The Compiler)
3b64110f01 Add modpack_installations table as primary detection source
Detection priority now:
1. modpack_installations table (panel's own install data — fastest)
2. Egg variables (MODPACK_PLATFORM/MODPACK_ID)
3. DaemonFileRepository file scan (last resort fallback)

This immediately detects all 19 CurseForge servers on the live panel
without any Wings calls or egg variable configuration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:41:19 -05:00
Claude (Chronicler #83 - The Compiler)
7ef83fd0a0 Add debug logging, alternate paths, and FTB detection to cron
- CurseForge: tries manifest.json + minecraftinstance.json
- Modrinth: modrinth.index.json (unchanged)
- FTB: version.json with parent ID detection
- All catch blocks now log exception messages for debugging
- Wings connection failures logged explicitly

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:39:50 -05:00
Claude (Chronicler #83 - The Compiler)
698273d636 Implement hybrid auto-detection for modpack cron (Magic & Manual)
- CheckModpackUpdates now scans ALL servers, not just egg-configured ones
- Step 1: egg variables (fastest)
- Step 2: DaemonFileRepository file detection (manifest.json, modrinth.index.json)
- Step 3: mark unconfigured if nothing found
- Respects is_user_overridden flag for manual configs
- New migration adds detection_method + is_user_overridden columns
- Per Gemini hybrid detection consultation (2026-04-06)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:35:24 -05:00
Claude (Chronicler #83 - The Compiler)
0bdd745527 Archive: live panel deploy confirmed — v1.0.0 is live on production
*/6 fix already in repo since 44a3043 — no change needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:27:36 -05:00
Claude (Chronicler #83 - The Compiler)
4e5ee7e49d Fix: getStatus returns all servers for root admins
accessibleServers() only returns explicitly assigned servers — admins
don't get them on the client API side. Now checks root_admin and
returns all servers for admin users.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:14:30 -05:00
Claude (Chronicler #83 - The Compiler)
0311249938 Add Node version detection + yarn build:production to build.sh
- Node <16 fails fast with helpful error
- Node 17+ gets --openssl-legacy-provider for CSS module compat
- yarn build:production runs automatically after all injections
- Graceful fallback if yarn missing or build fails (admin + console still work)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:06:43 -05:00
Claude (Chronicler #83 - The Compiler)
00b5eadc7d Archive: Gemini consultation on v1.1.0 badge build plan (Node detection)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:02:02 -05:00
Claude (Chronicler #83 - The Compiler)
990542abc9 Phase 11D complete, badges deferred to v1.1.0, listings updated
- Moved dashboard badges to "Upcoming v1.1.0" in both BBB listings
- Updated ACTIVE_CONTEXT — all code-side Phase 11 work done
- Waiting on Michael for BBB listings + live panel green light

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:56:43 -05:00
Claude (Chronicler #83 - The Compiler)
0d6752792a bridge: Request — badge build blocked, need decision (skip or patch webpack)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:51:21 -05:00
Claude (Chronicler #83 - The Compiler)
bb7728fe0d Fix: add !important to callout backgrounds to override AdminLTE
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:48:47 -05:00
Claude (Chronicler #83 - The Compiler)
9d1c5d4291 bridge: Request — debug dashboard badge injection on Dev Panel
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:47:11 -05:00
Claude (Chronicler #83 - The Compiler)
705960b61f Fix: callout boxes use dark background with accent border + heading
Dark #1a1a2e background, brand color borders and headings only,
light gray body text. Matches Pterodactyl dark theme.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:44:34 -05:00
Claude (Chronicler #83 - The Compiler)
c0dfc6e186 Fix: force white text on callout boxes for readability
Cyan/orange callout backgrounds need white text and underlined links.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:38:33 -05:00
Claude (Chronicler #83 - The Compiler)
9640505c43 Fix: remove missing settings-notices partial from admin view
Partial doesn't exist in Blueprint beta-2026-01.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:37:41 -05:00
Claude (Chronicler #83 - The Compiler)
bd9a5fcde3 Fix: admin view extends Pterodactyl layout with proper AdminLTE styling
Rewrote view.blade.php to use @extends('layouts.admin'), @section blocks,
AdminLTE box/callout/table classes, and standard Pterodactyl admin chrome.
Replaces custom inline styles with framework components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:33:06 -05:00
Claude (Chronicler #83 - The Compiler)
fa5fb364c1 Fix: normalize order IDs to uppercase across all MVC endpoints
- LicenseService.php: strtoupper(trim()) before sending to Arbiter
- mvc.js: toUpperCase().trim() on activate, validate, deactivate, webhook
- verifymvc.js: toUpperCase().trim() on /verify-mvc Discord command

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:25:35 -05:00
Claude (Chronicler #83 - The Compiler)
1255c315ee Fix: build.sh overwrites Blueprint's auto-generated admin controller
Blueprint generates its own controller at app/Http/Controllers/Admin/
Extensions/modpackchecker/. Our controller.php with LicenseService DI
now overwrites it during build so the route uses the licensed version.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:18:47 -05:00
Claude (Chronicler #83 - The Compiler)
d66ea6212d Phase 11F: BuiltByBit listing drafts — Standard + Professional + changelog
Standard ($14.99): CurseForge, Modrinth, Technic, daily checks, 48h support
Professional ($24.99): + FTB, custom intervals, Discord webhooks, 24h support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:16:03 -05:00
Claude (Chronicler #83 - The Compiler)
83333a47fa Fix: build.sh clears Laravel cache after copying PHP classes
The admin controller was failing because Laravel's DI container had stale
class resolution cache. Added php artisan optimize:clear at end of build.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:11:52 -05:00
Claude (Chronicler #83 - The Compiler)
44fb51fcfb bridge: Request — Phase 11E scope clarification (GitBook knowledge base)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:57:40 -05:00
Claude (Chronicler #83 - The Compiler)
9dd308f0bb Fix: build.sh also copies ModpackApiService.php to app/Services/
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:54:15 -05:00
Claude (Chronicler #83 - The Compiler)
44a304331f Fix: remove */6 from doc comment — PHP parses */ as end-of-comment
Changed cron example from '0 */6 * * *' to '0 0,6,12,18 * * *' to avoid
the */ closing the docblock prematurely and causing a syntax error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:52:19 -05:00
Claude (Chronicler #83 - The Compiler)
34cc2b7110 Fix: build.sh explicitly copies PHP classes to Laravel app/ tree
Blueprint's requests.app merge doesn't create new subdirectories reliably.
build.sh now copies LicenseService, ValidateLicense, CheckModpackUpdates,
and ModpackAPIController directly into app/ during blueprint -install.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:48:05 -05:00
Claude (Chronicler #83 - The Compiler)
c2d72cbabc bridge: Request — Deploy Phase 11D to Dev Panel for testing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:40:16 -05:00
Claude (Chronicler #83 - The Compiler)
8872f67727 Phase 11D: Blueprint license activation, phone-home, and tier gating
- LicenseService.php: activate/validate/deactivate + 7-day grace period
- ValidateLicense.php: mvc:validate Artisan command (daily cron)
- Updated controller.php: license activation/deactivation in update handler
- Updated view.blade.php: order ID input, status indicator (green/yellow/red),
  grace/expired banners, dynamic pro-tier field gating, update-available card

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:36:55 -05:00
Claude (Chronicler #83 - The Compiler)
7c58cea3e5 Phase 11B/C: /verify-mvc slash command + role assignment
- New discord/verifymvc.js: verifies BBB order, links discord_id, assigns customer role
- Wired into events.js handler and index.js command registration
- Reads MVC_CUSTOMER_ROLE_ID from env — Chronicler creates role + sets value

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:30:13 -05:00
Claude (Chronicler #83 - The Compiler)
fd50009f67 Phase 11A: MVC licensing — migration + API routes
- 138_mvc_licensing.sql: mvc_licenses + mvc_activations tables
- src/routes/mvc.js: activate, validate, deactivate, BBB webhook, version check
- Wired /api/mvc into Arbiter index.js
- Ready for Chronicler deployment to Command Center

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:16:16 -05:00
Claude (Chronicler #83 - The Compiler)
a305c7e686 bridge: Archive Phase 11 spec, update ACTIVE_CONTEXT
- Archived RES-2026-04-12-phase11-implementation-spec from Chronicler
- Updated status with completed code review and next steps (Phase 11A-G)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:12:40 -05:00