feat(genie): migrate genie engineering docs into _internal/ + operator security pages#66
Conversation
…rator security pages
Sets up the docs structure that automagik-dev/genie will submodule + symlink
at docs/ (via .docs-vendor/) so engineers see this as native genie docs while
operators on automagik.dev see only the curated public pages.
Migrated from automagik-dev/genie/docs/* (md → mdx, no content rewrite):
genie/_internal/ (excluded from Mintlify nav via .mintignore **/_internal/):
- architecture.mdx, state-machine.mdx, sdk-executor-guide.mdx
- co-orchestration-guide.mdx, spawn-auto-resume.mdx, spawn-team-resolution.mdx
- cli-reference.mdx, agent-frontmatter.mdx, agent-profiles.mdx
- retention.mdx, design-system.mdx, event-emitters-inventory.mdx
- observability-{consumers,contract,rollout}.mdx, observability-acid-tests.sql
- templates/observability-v0-flip.mdx
- detectors/{runbook,schema-audit}.mdx
genie/security/key-rotation.mdx (operator-facing, frontmatter added):
- existing key-rotation runbook from genie-supply-chain-signing wish
genie/incident-response/canisterworm.mdx (operator-facing, frontmatter added):
- existing 38KB Portuguese-language CanisterWorm public runbook
- canonical-copy reference updated to point at automagik-dev/docs
.mintignore extended with **/_internal/ — engineers see _internal/ via the
submodule from inside genie; operators on automagik.dev never see it.
Coordinated with: PR in automagik-dev/genie that adds .docs-vendor submodule
+ symlink docs → .docs-vendor/genie + deletes the old genie/docs/ tree.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (22)
📝 WalkthroughWalkthroughThis PR adds comprehensive internal and public documentation covering Genie's architecture, observability system, CLI commands, configuration guides, security procedures, and operational runbooks, while configuring Mintlify to exclude internal documentation directories from the public build. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request migrates and expands internal engineering documentation, moving numerous files to the .mdx format and updating .mintignore to exclude these internal docs from public builds. The documentation covers critical areas such as agent frontmatter, architecture, observability, and security protocols. Feedback identifies several issues within the new documentation, including a duplicated path segment in an incident response command and an undefined variable in an observability consumer code example. Additionally, multiple instances of broken links referencing old .md extensions instead of the new .mdx format were found across several files.
|
|
||
| # Caminhos alternativos | ||
| ls ~/.cache/.bun/install/cache/@automagik/genie@4.260421.*@@@1/dist/env-compat.cjs 2>/dev/null | ||
| ls ~/.cache/.bun/install/cache/.bun/install/cache/pgserve@1.1.1*@@@1/scripts/check-env.js 2>/dev/null |
| export async function startRunbookR1(opts: R1ConsumerOptions = {}): Promise<R1ConsumerHandle> { | ||
| const detector = new R1Detector(opts.detector); | ||
| const token = opts.token ?? mintR1Token({ subscriberId: opts.subscriberId }).token; | ||
|
|
||
| const handle = await runEventsStreamFollow( | ||
| { follow: true, kind: 'mailbox', token, maxEvents: opts.maxEvents, idleExitMs: opts.idleExitMs }, | ||
| (row: V2EventRow) => { | ||
| if (row.subject !== 'mailbox.delivery') return; | ||
| const data = (row.data ?? {}) as Record<string, unknown>; | ||
| const from = typeof data.from === 'string' ? data.from : null; | ||
| const to = typeof data.to === 'string' ? data.to : null; | ||
| if (!from || !to) return; | ||
|
|
||
| const finding = detector.observe({ | ||
| createdAt: new Date(row.created_at).getTime(), | ||
| from, to, trace_id: row.trace_id, | ||
| }); | ||
| if (!finding) return; | ||
|
|
||
| if (opts.onFinding) { opts.onFinding(finding); return; } | ||
| try { | ||
| emitEvent('runbook.triggered', { | ||
| rule: finding.rule, | ||
| evidence_count: finding.evidence_count, | ||
| window_minutes: 10, | ||
| correlation_id: finding.correlation_id, | ||
| recommended_sql: finding.recommended_sql, | ||
| evidence_summary: `scheduler→team-lead mailbox burst: ${finding.evidence_count} deliveries in 10m window`, | ||
| }, { severity: 'warn', source_subsystem: 'consumer-runbook-r1' }); | ||
| } catch { | ||
| // Emitting must never tear down the consumer — bookkeeping only. | ||
| } | ||
| }, | ||
| ); | ||
|
|
||
| return { stop: () => handle.stop(), getWindowDepth: () => detector.getWindowDepth(), getFindingCount: () => findingCount }; | ||
| } |
There was a problem hiding this comment.
The example code references findingCount in the return statement, but it is never defined or incremented in the function body. It should be initialized and updated when a finding is detected to make the example functional.
export async function startRunbookR1(opts: R1ConsumerOptions = {}): Promise<R1ConsumerHandle> {
const detector = new R1Detector(opts.detector);
const token = opts.token ?? mintR1Token({ subscriberId: opts.subscriberId }).token;
let findingCount = 0;
const handle = await runEventsStreamFollow(
{ follow: true, kind: 'mailbox', token, maxEvents: opts.maxEvents, idleExitMs: opts.idleExitMs },
(row: V2EventRow) => {
if (row.subject !== 'mailbox.delivery') return;
const data = (row.data ?? {}) as Record<string, unknown>;
const from = typeof data.from === 'string' ? data.from : null;
const to = typeof data.to === 'string' ? data.to : null;
if (!from || !to) return;
const finding = detector.observe({
createdAt: new Date(row.created_at).getTime(),
from, to, trace_id: row.trace_id,
});
if (!finding) return;
findingCount++;
if (opts.onFinding) { opts.onFinding(finding); return; }
try {
emitEvent('runbook.triggered', {
rule: finding.rule,
evidence_count: finding.evidence_count,
window_minutes: 10,
correlation_id: finding.correlation_id,
recommended_sql: finding.recommended_sql,
evidence_summary: `scheduler→team-lead mailbox burst: ${finding.evidence_count} deliveries in 10m window`,
}, { severity: 'warn', source_subsystem: 'consumer-runbook-r1' });
} catch {
// Emitting must never tear down the consumer — bookkeeping only.
}
},
);
return { stop: () => handle.stop(), getWindowDepth: () => detector.getWindowDepth(), getFindingCount: () => findingCount };
}
|
|
||
| This wish (`genie-serve-obs-v2`) ships **Phases 0-3 inclusive, with | ||
| `GENIE_WIDE_EMIT=0` as the default**. Phase 4 (flip-default) is a **separate | ||
| PR** gated by `docs/templates/observability-v0-flip.md`. Do not merge the |
| `notify.delivery.lag`, `stream.gap.detected`, `correlation.orphan.rate`). | ||
|
|
||
| Flip the default of `GENIE_WIDE_EMIT` to on. This is a **separate PR** with | ||
| `docs/templates/observability-v0-flip.md` as its checklist. **Not part of |
| | 2026-04-19 | Phase 2 shipped | Groups 3-4 — vocabulary wiring + consumer CLI | | ||
| | 2026-04-19 | Phase 3 shipped | Groups 5-7 — RBAC, watchdog, runbook-R1 | | ||
| | 2026-04-20 | Phase 3 gated | Group 8 — pen-test + perf gate + this full-version doc | | ||
| | TBD | Phase 4 flip | Separate PR per `docs/templates/observability-v0-flip.md` | |
|
|
||
| Auto-resume automatically restores agent sessions when their tmux pane dies unexpectedly (crash, OOM, terminal close). Instead of losing the entire conversation context, Genie detects the dead pane and respawns the agent using its preserved Claude session ID. | ||
|
|
||
| > **Canonical-UUID invariant.** Auto-resume is the mechanism that keeps the "one name = one true Claude session UUID" guarantee alive across the canonical agent's lifetime. The invariant itself — plus the single-verb state-gated spawn model, the parallel `<name>-<s4>` convention, and the five-tier team-resolution precedence — lives in [**SPAWN-TEAM-RESOLUTION.md**](SPAWN-TEAM-RESOLUTION.md). Authority trail: wishes `tui-spawn-dx`, `perfect-spawn-hierarchy`, and `fix-ghost-approval-p0` (all archived in `.genie/wishes/_archive/`). **Parallels** (`<name>-<s4>`) are **off** the bare-name auto-resume path described here; they resume only via their full id. |
There was a problem hiding this comment.
The link references SPAWN-TEAM-RESOLUTION.md, but the file has been renamed to .mdx as part of this migration.
> **Canonical-UUID invariant.** Auto-resume is the mechanism that keeps the "one name = one true Claude session UUID" guarantee alive across the canonical agent's lifetime. The invariant itself — plus the single-verb state-gated spawn model, the parallel `<name>-<s4>` convention, and the five-tier team-resolution precedence — lives in [**SPAWN-TEAM-RESOLUTION.mdx**](SPAWN-TEAM-RESOLUTION.mdx). Authority trail: wishes `tui-spawn-dx`, `perfect-spawn-hierarchy`, and `fix-ghost-approval-p0` (all archived in `.genie/wishes/_archive/`). **Parallels** (`<name>-<s4>`) are **off** the bare-name auto-resume path described here; they resume only via their full id.
| genie daemon status # Show daemon state | ||
| ``` | ||
|
|
||
| See [ARCHITECTURE.md](ARCHITECTURE.md) for full service topology details. |
| └─────────────────────────────────────────────────────────────────┘ | ||
| ``` | ||
|
|
||
| For detailed architecture documentation, see [ARCHITECTURE.md](ARCHITECTURE.md). |
| 3. Try `genie work <id>` to spawn your first worker | ||
| 4. Practice the workflow with simple tasks | ||
| 5. Scale up to multi-worker orchestration | ||
| 6. Read [ARCHITECTURE.md](ARCHITECTURE.md) for internals |
| │ • Heartbeat (60s) │ │ • executor state changes │ | ||
| │ • Orphan recon (5m) │ │ • new messages │ | ||
| │ • Lease recovery │ │ │ | ||
| └─────────────────────┘ │ Routes to: │ |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e93e3d9f00
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| # Caminhos alternativos | ||
| ls ~/.cache/.bun/install/cache/@automagik/genie@4.260421.*@@@1/dist/env-compat.cjs 2>/dev/null | ||
| ls ~/.cache/.bun/install/cache/.bun/install/cache/pgserve@1.1.1*@@@1/scripts/check-env.js 2>/dev/null |
There was a problem hiding this comment.
Fix alternate Bun cache IoC command path
The alternate-cache command in the infection check uses a duplicated path segment (~/.cache/.bun/install/cache/.bun/install/cache/...), so it will never find pgserve IoCs on hosts that only use Bun’s newer cache location. In that environment, operators can get a false-negative during Step 2.4 and incorrectly treat an infected machine as clean.
Useful? React with 👍 / 👎.
|
|
||
| **Context 1 — Burned public key / burned signing identity** | ||
|
|
||
| A Namastex security officer confirmed the cosign keyless identity is compromised (see [`docs/security/key-rotation.md`](../security/key-rotation.md)). `verify-install` returns exit `3` (signer-identity-mismatch). The host needs remediation now; rotation will take hours. |
There was a problem hiding this comment.
Point key-rotation reference to an existing page
This incident-response link targets ../security/key-rotation.md, but the migrated document in this repo is key-rotation.mdx. As written, the public docs route resolves to a missing page, so responders following this escalation path during signer-identity incidents hit a dead link.
Useful? React with 👍 / 👎.
…#67) Adds a new top-level Mintlify navigation group "Security & Trust" between Configuration and Architecture in the Genie product, filling the operator-facing gap left by the aegis-distribution-sovereignty umbrella plan. New pages: - genie/security/index.mdx — overview: trust contract, 4-channel cosign pinning, link cards to deeper pages and the CanisterWorm runbook - genie/security/distribution-sovereignty.mdx — threat model, the curl install path, verification stack, npm soft-deprecate, status table - genie/security/verifying-installs.mdx — `genie sec verify-install` walkthrough, per-stage explanation, manual 4-channel cross-check recipe, offline mode, --unsafe-unverified contract The new group also surfaces existing operator-facing pages already migrated in #66 (key-rotation + canisterworm incident response) so they have a home in the nav. genie/installation.mdx "What's next" section gets a fifth card linking to Security & Trust so operators encounter the trust documentation right after install. PR-A1 in the security-roadmap mini-PR sequence (after PR-A0 docs submodule merged via genie #1426). Co-authored-by: Automagik Genie Docs Bot <genie@namastex.ai> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
….docs-vendor/genie/ (#1426) Replaces genie's internal docs/ tree with a git submodule of automagik-dev/docs (the Mintlify public-docs repo). The symlink docs → .docs-vendor/genie makes the multi-repo nature mostly invisible: engineers cd into docs/ and see genie content directly (installation.mdx, cli/, security/, _internal/, …) without omni/rlmx siblings. Coordinated with automagik-dev/docs#66 (already merged): genie's previous docs/* content is now MDX inside the docs repo, with engineering-internal pages under genie/_internal/ excluded from the public Mintlify build via **/_internal/ in .mintignore. Changes in this PR: - .gitmodules + .docs-vendor/ submodule pointing at automagik-dev/docs:main - docs symlink → .docs-vendor/genie - Removed all 22 files from the old genie/docs/ tree (now lives in docs repo) - scripts/test-runbook.sh: canisterworm.md → canisterworm.mdx - .github/workflows/runbook-test.yml: trigger on .docs-vendor/.gitmodules changes; checkout uses submodules: recursive - .github/workflows/docs-lint.yml: same trigger + checkout updates; docs/**/*.md → docs/**/*.mdx for path filters - .github/workflows/signing-identity-pin.yml: comment refs updated - CLAUDE.md: new "Docs" section explaining the submodule + symlink workflow Workflow for editing docs going forward: 1. Edit docs/<page>.mdx (symlink follows into .docs-vendor/genie/) 2. cd .docs-vendor && git checkout -b feat/<topic> && commit + push + PR 3. After docs PR merges: cd .. && git submodule update --remote .docs-vendor && git add .docs-vendor && commit "chore: bump .docs-vendor to docs main" Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
….docs-vendor/genie/ (#1426) Replaces genie's internal docs/ tree with a git submodule of automagik-dev/docs (the Mintlify public-docs repo). The symlink docs → .docs-vendor/genie makes the multi-repo nature mostly invisible: engineers cd into docs/ and see genie content directly (installation.mdx, cli/, security/, _internal/, …) without omni/rlmx siblings. Coordinated with automagik-dev/docs#66 (already merged): genie's previous docs/* content is now MDX inside the docs repo, with engineering-internal pages under genie/_internal/ excluded from the public Mintlify build via **/_internal/ in .mintignore. Changes in this PR: - .gitmodules + .docs-vendor/ submodule pointing at automagik-dev/docs:main - docs symlink → .docs-vendor/genie - Removed all 22 files from the old genie/docs/ tree (now lives in docs repo) - scripts/test-runbook.sh: canisterworm.md → canisterworm.mdx - .github/workflows/runbook-test.yml: trigger on .docs-vendor/.gitmodules changes; checkout uses submodules: recursive - .github/workflows/docs-lint.yml: same trigger + checkout updates; docs/**/*.md → docs/**/*.mdx for path filters - .github/workflows/signing-identity-pin.yml: comment refs updated - CLAUDE.md: new "Docs" section explaining the submodule + symlink workflow Workflow for editing docs going forward: 1. Edit docs/<page>.mdx (symlink follows into .docs-vendor/genie/) 2. cd .docs-vendor && git checkout -b feat/<topic> && commit + push + PR 3. After docs PR merges: cd .. && git submodule update --remote .docs-vendor && git add .docs-vendor && commit "chore: bump .docs-vendor to docs main" Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Sets up the docs structure that
automagik-dev/geniewill submodule + symlink atdocs/(via.docs-vendor/) so genie engineers see this as native genie docs while operators onautomagik.devsee only the curated public pages.This PR is one half of a coordinated pair:
automagik-dev/docs): import genie's existing docs as MDXautomagik-dev/genie, opened next): add.docs-vendor/submodule, symlinkdocs → .docs-vendor/genie, delete the now-redundantgenie/docs/treeMigrations
Source:
automagik-dev/genie/docs/*at commita44268b0(post-PR-#1425).genie/_internal/(NEW, excluded from Mintlify nav)Pure
.md → .mdxrename, no prose rewrites:architecture.mdx,state-machine.mdx,sdk-executor-guide.mdxco-orchestration-guide.mdx,spawn-auto-resume.mdx,spawn-team-resolution.mdxcli-reference.mdx,agent-frontmatter.mdx,agent-profiles.mdxretention.mdx,design-system.mdx,event-emitters-inventory.mdxobservability-{consumers,contract,rollout}.mdx,observability-acid-tests.sqltemplates/observability-v0-flip.mdxdetectors/{runbook,schema-audit}.mdxgenie/security/key-rotation.mdx(operator-facing)Existing key-rotation runbook from the
genie-supply-chain-signingwish. Front-matter added (Mintlify title + sidebar + icon + description). HTML comments converted to a Mintlify<Note>component for the keyless-only header.genie/incident-response/canisterworm.mdx(operator-facing)Existing 38 KB Portuguese-language CanisterWorm public runbook. Front-matter added. Banner header converted to Mintlify
<Info>component. Canonical-copy reference updated fromautomagik-dev/genie/docs/incident-response/canisterworm.md→automagik-dev/docs/genie/incident-response/canisterworm.mdx(the doc itself documents that this IS the canonical copy now)..mintignore
Adds
**/_internal/so engineering content surfaces in the genie repo (via submodule + symlink) but never reaches the public Mintlify build at automagik.dev.Test plan
genie/security/key-rotationandgenie/incident-response/canisterwormcorrectlygenie/_internal/*pages do NOT appear in the rendered navautomagik-dev/genieis opened with submodule pointer at this branch's HEAD; bumps to main HEAD after this PR merges🤖 Generated with Claude Code
Summary by CodeRabbit