Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d8ec72e
Harden eternal stack gates and policy contracts
claude Jun 16, 2026
4c6f90d
fix compact reset boundaries
claude Jun 19, 2026
5771908
fix coderabbit review findings
claude Jun 19, 2026
f37dfde
fix coderabbit follow-up findings
claude Jun 19, 2026
d575c65
address coderabbit follow-ups
claude Jun 19, 2026
96969cf
resolve coderabbit readability notes
claude Jun 19, 2026
a815b64
address coderabbit audit notes
claude Jun 19, 2026
4224b74
update workflow and triage review notes
claude Jun 19, 2026
2ec364d
document cursor rule install coverage
claude Jun 19, 2026
b7468ab
align tcg rule export scopes
claude Jun 19, 2026
1e1a80f
document privacy overlay format
claude Jun 19, 2026
e8f1bf8
cover workflow review follow-ups
claude Jun 19, 2026
3ee5fca
harden privacy and ci review notes
claude Jun 20, 2026
aef2d52
resolve coderabbit guard follow-ups
claude Jun 20, 2026
846a866
address workflow metadata review notes
claude Jun 20, 2026
36942c6
fail closed on rule copy errors
claude Jun 20, 2026
7212672
harden privacy scanner review notes
claude Jun 20, 2026
34e4645
address final coderabbit review notes
claude Jun 20, 2026
3316574
resolve coderabbit changelog follow-ups
claude Jun 20, 2026
2947e75
address coderabbit documentation and sync notes
claude Jun 20, 2026
e29dd3a
harden privacy scanner review notes
claude Jun 20, 2026
dff9c76
clarify ci cd enforcement coverage
claude Jun 20, 2026
f274cfa
normalize tcg contract coverage path
claude Jun 20, 2026
057a36a
fix hook test shellcheck cleanup
claude Jun 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/health.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: health

on:
pull_request:
push:
branches:
- main
- "release/**"

Comment on lines +3 to +9

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Add workflow-level concurrency control.

Without concurrency, rapid pushes can run overlapping full health jobs for the same ref, wasting CI time and increasing queue contention.

🔧 Suggested diff
 on:
   pull_request:
   push:
     branches:
       - main
       - "release/**"

+concurrency:
+  group: health-${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
 permissions:
   contents: read
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
pull_request:
push:
branches:
- main
- "release/**"
on:
pull_request:
push:
branches:
- main
- "release/**"
concurrency:
group: health-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 3-8: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting

(concurrency-limits)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/health.yml around lines 3 - 9, The GitHub Actions workflow
health.yml lacks concurrency control, allowing multiple overlapping job runs for
the same branch or pull request, which wastes CI resources and increases queue
contention. Add a top-level concurrency section to the workflow (at the same
indentation level as the existing on trigger configuration) that cancels
in-progress jobs when a new run is triggered for the same ref. Use a concurrency
group that combines the workflow name or identifier with the git ref
(github.ref) to ensure only one job runs per branch/PR at a time, and set
cancel-in-progress to true to automatically cancel previously queued jobs when a
newer one starts.

Source: Linters/SAST tools

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
repo-health:
name: Repository Health Checks
runs-on: ubuntu-24.04
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
with:
persist-credentials: false

- name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: "22"
Comment on lines +23 to +31

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat .github/workflows/health.yml

Repository: eternalwaitt/eternal-stack

Length of output: 1004


🌐 Web query:

GitHub Actions best practices pinning commit SHA security v4 mutable tags

💡 Result:

Pinning GitHub Actions to a full-length commit SHA is the only way to ensure the immutability of an action and protect against supply chain attacks involving mutable references [1][2][3]. Why Pinning by SHA is Required: Git tags (like v4) and branch names (like main or master) are mutable pointers [4][5][6]. They can be force-pushed or updated at any time by repository maintainers or attackers who compromise a maintainer's account [7][8][9]. When you reference an action by a tag, your workflow will automatically execute whatever code the tag currently points to, making you vulnerable to malicious code injection if that tag is retargeted [10][5][11]. Best Practices for Security: - Use Full 40-Character Commit SHAs: Always use the complete 40-character SHA [12][11]. Never use shortened SHAs or mutable tags [12][3]. - Maintain Readability with Comments: Because SHAs are not human-readable, append the original tag or version as a comment in your YAML file [6][11]. This allows automated tools like Dependabot or Renovate to identify which version the SHA corresponds to and suggest updates [13][2][6]. Example: - uses: actions/checkout@11bd719 # v4.2.2 - Automate Updates: Use dependency management tools such as Dependabot or Renovate to keep your pinned SHAs up to date [13][6]. They can be configured to automatically create pull requests when a new tag is released, ensuring you receive security patches without manually managing the SHAs [13][6]. - Enforce via Policy: GitHub allows organization and repository-level policies that can mandate the use of full-length commit SHAs, causing any workflows that use mutable references to fail [1][7][6]. - Use Audit Tools: Implement automated checks in your CI/CD pipeline, such as zizmor or custom scripts, to scan your workflow files and fail builds that contain unpinned actions [12][6][11]. Verified creator badges on GitHub Marketplace provide some assurance, but they do not eliminate the risk of account compromise or malicious tag updates; SHA pinning remains the definitive security control [1][8].

Citations:


🌐 Web query:

actions/checkout persist-credentials false security best practice

💡 Result:

Setting persist-credentials to false in actions/checkout is considered a security best practice to minimize the exposure of repository authentication tokens during a workflow execution [1][2][3]. By default, actions/checkout is set to persist-credentials: true, which causes the action to configure the local Git environment with the provided token (typically GITHUB_TOKEN or a custom SSH key) [4][1][5]. This makes the credentials available to any subsequent steps in the same job [1][2][6]. While the token is removed during post-job cleanup, setting this to false prevents the token from being written to the Git configuration on disk in the first place, thereby reducing the risk of accidental exposure via logs, artifacts, or unauthorized access by malicious actions within the workflow [1][5][7]. It is important to note the following context: 1. How it works: When persist-credentials is true, the action writes the credentials to the local git config [4][2]. In recent versions (starting with v6), this storage location was moved to a restricted directory ($RUNNER_TEMP) to reduce the risk of accidental leaks through artifact creation [4][8][7]. 2. Limitations: Setting persist-credentials to false only affects the automatic configuration of the local git environment [2][9]. It does not revoke the job's access to the GITHUB_TOKEN, which remains available to the workflow through other standard mechanisms [6][7]. If a subsequent action (such as a git-auto-commit action) requires authenticated git operations, it may fail unless you manually reconfigure the credentials or provide them via other means [3]. 3. Recommendation: You should explicitly set persist-credentials: false unless your workflow specifically requires authenticated git commands (like pushing commits back to the repository) [1]. Even then, consider whether there are more secure ways to provide those credentials only to the specific steps that require them [2][6]. Example configuration: - uses: actions/checkout@v4 with: persist-credentials: false

Citations:


🌐 Web query:

actions/setup-node package-manager-cache false security 2024 2025

💡 Result:

In actions/setup-node, the package-manager-cache input controls the automatic caching feature for npm [1][2]. By default, this input is set to true, which enables automatic caching if your package.json file includes a devEngines.packageManager or a top-level packageManager field set to npm, provided no explicit cache input is specified [1][2][3]. Setting package-manager-cache to false disables this automatic caching behavior [1][4]. GitHub officially recommends setting package-manager-cache: false in workflows that involve elevated privileges or access to sensitive information, such as those used for package publishing, when caching is not strictly required for performance [1][5][2]. This guidance is provided as a security measure to mitigate risks like cache poisoning, where an attacker might attempt to inject malicious code or intercept sensitive data (including tokens) via the cached dependency directory [5]. If a workflow is designed to run with elevated permissions—or if you simply want to avoid the potential security surface area of automated caching—explicitly disabling it is considered a best practice [1][6]. For example, to disable it in your GitHub Actions workflow: steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: '24' package-manager-cache: false # Disables automatic npm caching [7]

Citations:


Pin action revisions and harden checkout defaults.

Lines 18 and 21 use mutable tags (@v4), which are vulnerable to supply-chain attacks. Pin both actions to full 40-character commit SHAs (with version comments for readability), set persist-credentials: false on checkout to prevent unnecessary credential persistence, and disable automatic package-manager caching on setup-node to mitigate cache-poisoning risks.

🧰 Tools
🪛 zizmor (1.25.2)

[warning] 17-18: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 18-18: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 21-21: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 21-21: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): enables caching by default

(cache-poisoning)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/health.yml around lines 17 - 23, Replace the mutable
action tags with pinned 40-character commit SHAs for both the checkout action on
line 18 and the setup-node action on line 21, adding version comments for
readability (e.g., "# v4.x.x"). For the checkout action, add a new configuration
line with persist-credentials set to false to prevent unnecessary credential
persistence. For the setup-node action, add a new configuration line to disable
automatic package-manager caching by setting cache to null to mitigate
cache-poisoning risks.

Source: Linters/SAST tools

# No package install runs in this job; keep setup-node package-manager caching disabled.
package-manager-cache: false

- name: Install CLI dependencies
run: |
sudo apt-get update
sudo apt-get install -y jq fd-find ripgrep shellcheck python3.12
sudo ln -sf "$(command -v fdfind)" /usr/local/bin/fd
sudo ln -sf "$(command -v python3.12)" /usr/local/bin/python3

- name: Validate generated rule exports
run: node scripts/sync-rule-exports.mjs --check

- name: Hook tests
run: tests/test-hooks.sh

- name: Workflow tool tests
run: tests/test-workflow-tools.sh

- name: Install and rollback tests
run: tests/test-install.sh

- name: Doctor
run: scripts/doctor.sh --jobs 4
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ coverage/
plans/
docs/plans/
docs/research/
# Local privacy overlay is intentionally ignored without hiding all .eternal/ state.
/.eternal/privacy-banned-tokens.local
/rules-manifest.local.json

# Never commit private Claude runtime data.
settings.local.json
Expand Down
40 changes: 35 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,37 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this

### Deprecated

## v0.5.2

2026-06-16

### Added

- `.github/workflows/health.yml` — CI health workflow for rule export sync, hook tests, workflow tests, install/rollback tests, and doctor.
- `scripts/doctor.sh` — health checks now cover ShellCheck, rule module export drift, privacy scan enforcement, and pending-release changelog validation.
- `rules/eternal-saas/project/tcg-contract.md` — scoped TCG/card-domain contract rule module and generated Cursor export.

### Changed

- `scripts/sync-rule-exports.mjs` and `scripts/init-project-rules.sh` — manifest-driven rule sync now validates profile membership, generated Cursor exports, privacy overlays, and install-time Cursor checksums.
- `scripts/init-project-rules.sh` — installs generated Cursor `.mdc` modules alongside Claude rules, validates Cursor exports, and tracks Cursor checksums in the install receipt.
- `rules/eternal-saas/*` — rule host metadata now reflects Claude and Cursor support without claiming unsupported Codex nested context output.
- Email triage runtime references now use the `etrnl-email` command pattern across guards, canaries, slash commands, and fixtures instead of legacy `vivaz-email` naming.
- `hooks/cc-sessionstart-restore.sh`, `scripts/lib/etrnl-state-core.mjs`, and `scripts/workflow-health.mjs` — track session reset boundaries so `/new` and `/clear` isolate stale compact handoff state.
- `scripts/bootstrap-tools.sh` and `scripts/tool-stack-check.mjs` — support validated `ETRNL_CODEGRAPH_NPM_SPEC` and `ETRNL_BEADS_NPM_SPEC` overrides for pinned global tool installs.
- Bundled skill namespaces now align around `@example-suite`, `money-vo-discipline`, and `orpc-patterns` naming across policy skills, routing lists, and vendored bundles.
- `skills/bundled/stripe-best-practices` — hardens Stripe guidance from advisory wording to explicit policy gates for API versions, payment-surface selection, test/migration expectations, and Connect settlement/dispute behavior.

### Fixed

- `scripts/install.sh` — validate source install inputs before any non-dry-run mutation.
- `hooks/cc-stop-verifier.sh`, `hooks/cc-pretooluse-guard.sh`, and `scripts/code-health-ledger-check.mjs` — close enforcement gaps for invalid Stop JSON, live hook writes, and prompt-only code-health audits.
- `scripts/update-check.mjs`, `scripts/skill-contract-check.mjs`, `scripts/tool-stack-check.mjs`, and `scripts/doctor.sh` — harden update trust, bundled skill contracts, pinned tool install specs, ShellCheck, privacy scanning, and rule export drift detection.

### Security

- `rules-manifest.json`, `scripts/privacy-banned-token-check.mjs`, and `scripts/doctor.sh` — remove tracked private project literals from the privacy gate and support standalone or doctor-integrated banned-token scans with gitignored local overlays and redacted diagnostics.

## v0.5.1

2026-06-11
Expand Down Expand Up @@ -53,14 +84,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
- `templates/AGENTS.global.md` — portable ~32-line cross-host agent baseline for Codex startup.
- `templates/AGENTS.override.codex.md` — Codex-specific startup deltas (no slash commands, no hooks, byte budget, skills path).
- `docs/rules.md` — cross-host rules reference: module catalog, host activation per tool, install and drift-check commands.
- `docs/adr/0003-cross-host-rule-stack.md` — decision record for the Exodia cross-host rule architecture.
- `docs/adr/0003-exodia-cross-host-rules.md` — decision record for the Exodia cross-host rule architecture.
- Codex byte gate in `scripts/doctor.sh` — warns when `~/.codex/AGENTS.md` exceeds 75 % of the configured `project_doc_max_bytes` limit.
- Manifest assertions in `scripts/doctor.sh` — validates `rules-manifest.json` schema version, `bannedTokens` non-empty, and `rules/eternal-saas/global/` module count.
- Rollback now restores `rules/eternal-saas` global digest and backed-up Codex startup files (`AGENTS.md`, `AGENTS.override.md`).
- `scripts/lib/skill-lists.sh` now includes `init-project-rules.sh` in `INSTALL_SCRIPTS` so it deploys to both Claude and Codex homes.
- Prompt router extended: "prune AGENTS/claude/rules", "rule bloat", "AGENTS.md/CLAUDE.md too long", "trim AGENTS/CLAUDE.md", and "startup file/context too long" prompts now route to `etrnl-ops-agent-files`. Three new skill-triggering fixture cases added.
- Six project pilots with the eternal-saas pack: core-suite, agency-tbd, tcg-collector, mimo-finance, vivaz-website, and sbcc-portal — each with project-specific `local-overrides.md`, pruned `AGENTS.md`, and removed old flat rule files.
- sbcc-portal `.gitignore` updated to track `.claude/rules/` while keeping local session state ignored.
- Six private project pilots with the eternal-saas pack, each with project-specific `local-overrides.md`, pruned `AGENTS.md`, and removed old flat rule files.
- One private pilot `.gitignore` updated to track `.claude/rules/` while keeping local session state ignored.

### Changed

Expand All @@ -73,7 +104,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this

### Fixed

- `scripts/plan-readiness-check.mjs` no longer flags hyphenated proper names such as the `agency-tbd` repo as a `TBD` placeholder; standalone `TBD` markers still fail (regression tests in `tests/test-workflow-tools.sh`).
- `scripts/plan-readiness-check.mjs` no longer flags hyphenated proper names such as the `example-agency` repo as a `TBD` placeholder; standalone `TBD` markers still fail (regression tests in `tests/test-workflow-tools.sh`).
- `scripts/update-check.mjs` now correctly marks `sync-rule-exports.mjs` as source-only (not installed) to prevent false drift failures.
- `scripts/update-check.mjs` renamed map includes `doctor.sh → doctor-etrnl.sh` to suppress stale-scripts drift false positives.

Expand All @@ -94,4 +125,3 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
### Security

- Public repository boundary: no private identity, credentials, transcripts, or local planning artifacts in tracked files.

8 changes: 5 additions & 3 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ Eternal Stack is designed as a complete skill family. Policy, review, simplifica
| `better-auth`, `tenant-isolation-patterns`, `money-vo-discipline` | Auth, tenancy, and money discipline | Community / upstream skill bundles |
| `stripe-best-practices`, `abacatepay-integration` | Payments review | Community / upstream skill bundles |
| `ci-cd` | CI helper scripts referenced by `/etrnl-dev-ci` | Community skill bundle |
| `domain-*`, `i18n-localization`, and related domain skills | Domain-specific review gates | Community / upstream skill bundles |
| `domain-cli`, `domain-cloud-native`, `domain-embedded`, `domain-fintech`, `domain-iot`, `domain-ml`, `domain-web`, `rules/eternal-saas/project/tcg-contract.md` | Domain-specific review gates and TCG project rule routing | Community / upstream skill bundles plus Eternal Stack rules |
| `prisma-expert` | Prisma schema and query review | Community / upstream skill bundle |
| `i18n-localization` | Locale and translation review | Community / upstream skill bundle |

The full inventory and routing notes live in [docs/skills.md](docs/skills.md).

Expand All @@ -40,7 +42,7 @@ Eternal Stack reimplements useful mechanisms from public agent-tooling projects
| --- | --- |
| [colbymchenry/codegraph](https://github.com/colbymchenry/codegraph) | Optional local code-graph MCP; bootstrap and health checks in `full` profile |
| [hyhmrright/brooks-lint](https://github.com/hyhmrright/brooks-lint) | Review finding shape (Symptom → Source → Consequence → Remedy); vendored Brooks modules |
| [rtk-ai/rtk](https://github.com/rtk-ai/rtk) | Codex deterministic command rewrite via `codex-rtk-pre-tool-use.sh` |
| [rtk-ai/rtk](https://github.com/rtk-ai/rtk) | Optional Codex command rewrite helper via `codex-rtk-pre-tool-use.sh`; separate from the Claude/Cursor rule pack |
| [GitHub/spec-kit](https://github.com/github/spec-kit) | Plan/readiness executability gates |
| [Chachamaru127/claude-code-harness](https://github.com/Chachamaru127/claude-code-harness) | Quality gates, browser artifact contracts, review plateau ideas |
| [infinri/Writ](https://github.com/infinri/Writ) | Mandatory-rule mechanical enforcement |
Expand All @@ -49,7 +51,7 @@ Eternal Stack reimplements useful mechanisms from public agent-tooling projects

## Claude Code

Eternal Stack targets [Claude Code](https://docs.anthropic.com/en/docs/claude-code) hook and skill surfaces. Codex parity helpers install under `~/.codex/etrnl/` when you use both hosts.
Eternal Stack targets [Claude Code](https://docs.anthropic.com/en/docs/claude-code) hook and skill surfaces. The reusable rule pack exports to Claude and Cursor; optional Codex helper state installs under `~/.codex/etrnl/` when you use both hosts.

## Contributing upstream

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ tests/test-hooks.sh

**Hooks** — enforcement at tool boundaries. Full catalog and lifecycle wiring: [docs/hooks.md](docs/hooks.md). Pretool and stop rules: [docs/guards.md](docs/guards.md). Regression: [tests/test-hooks.sh](tests/test-hooks.sh).

**Skills** — repeatable workflows as `/etrnl-*` commands, grouped by namespace (`dev`, `audit`, `ops`, `comm`). Inventory: [docs/skills.md](docs/skills.md).
**Skills** — repeatable workflows as `/etrnl-*` commands, grouped by namespace (`dev`, `audit`, `ops`, `comm`). Bundled domain skills include `domain-cli`, `domain-cloud-native`, `domain-embedded`, `domain-fintech`, `domain-iot`, `domain-ml`, and `domain-web`. Inventory: [docs/skills.md](docs/skills.md).

**Scripts** — deterministic helpers for ledgers, browser QA, workflow health, code-health inventory, deep-audit validation, and release hygiene.

Expand Down Expand Up @@ -86,7 +86,7 @@ Don't skip those steps. Strict mode with untested hooks will interrupt things yo
| [CLAUDE.md](CLAUDE.md) | Thin Claude Code wrapper that imports `AGENTS.md` |
| [docs/hooks.md](docs/hooks.md) | Hook reference: every `cc-*` entrypoint, events, default vs strict |
| [docs/guards.md](docs/guards.md) | Pretool deny catalog, stop-verifier gates, fail-open matrix |
| [docs/rules.md](docs/rules.md) | Cross-host rule pack: module catalog, host activation, `init-project-rules.sh` |
| [docs/rules.md](docs/rules.md) | Claude and Cursor rule pack: module catalog, host activation, `init-project-rules.sh` |
| [docs/install.md](docs/install.md) | Install, update, uninstall, profiles, strict mode |
| [docs/migration.md](docs/migration.md) | Rollout sequencing — safe migration order |
| [docs/configuration.md](docs/configuration.md) | Profiles, strict mode, env var tuning |
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.5.1
0.5.2
20 changes: 10 additions & 10 deletions commands/email-triage.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description: Run VIVAZ email Inbox Zero triage for one account, then open the action queue.
description: Run managed email Inbox Zero triage for one account, then open the action queue.
argument-hint: <account-id>
allowed-tools: Bash
---
Expand All @@ -8,41 +8,41 @@ Account argument from the slash command: `$ARGUMENTS`

Treat the argument as the account id. If it is empty, ask the repository owner for the account id and stop.

Do not handwrite Gmail commands. Do not send email. Do not mutate Gmail outside the VIVAZ email runtime.
Do not run `vivaz-email triage run` for this slash command. That is a dry classification path and does not clear INBOX.
Do not handwrite Gmail commands, send email, or mutate Gmail outside the managed email runtime.
Avoid `etrnl-email triage run` for this slash command; it is a dry classification path and does not clear INBOX.

Phase 1 is Inbox Zero. Triage every email in INBOX, archive known bad-quality emails, label action/waiting/manual-review items, remove them from INBOX, and provider-verify INBOX is zero:

```bash
vivaz-email triage guarded-run --account <account-id> --max-inbox 500 --apply --require-insights
etrnl-email triage guarded-run --account <account-id> --max-inbox 500 --apply --require-insights
```

Verify the queue run before opening any queue:

```bash
vivaz-email triage verify --latest --account <account-id>
etrnl-email triage verify --latest --account <account-id>
```

If verification does not show `inbox_zero_verified: true`, `inbox_count: 0`, and either `gmail_mutated: true` or `queue_ready_without_mutation: true`, do not show queue items. Continue Inbox Zero triage first or paste the runtime blocker.

If `guarded-run` exits with `TRIAGE_GUARD_ML_DISAGREED`, do not ask the repository owner whether to continue. Inspect the runtime evidence, patch deterministic triage rules/cache when appropriate, then rerun the guarded command:

```bash
vivaz-email triage guarded-run --account <account-id> --max-inbox 500 --apply --require-insights
vivaz-email triage ml-reviews --latest --account <account-id> --limit 20
vivaz-email triage report --latest --account <account-id> --include-failures --format markdown
etrnl-email triage guarded-run --account <account-id> --max-inbox 500 --apply --require-insights
etrnl-email triage ml-reviews --latest --account <account-id> --limit 20
etrnl-email triage report --run-id <run-id> --format markdown
```

Phase 2 starts only after Inbox Zero is verified. Use the queue run id emitted by the runtime, then show exactly one action/reply queue item:

```bash
vivaz-email triage queue --run-id <run-id> --mode reply --format markdown --next
etrnl-email triage queue --run-id <run-id> --mode reply --format markdown --next
```

If the queue item shows a proposed reply with a draft id, run the outgoing reply checker before asking the repository owner to approve or send it:

```bash
vivaz-email drafts check --draft-id <draft-id>
etrnl-email drafts check --draft-id <draft-id>
```

If the checker returns any issue, stop and surface the failed draft check with the exact issue list. Do not improvise manual rewrites, and do not ask the repository owner to approve or send a failed draft until the runtime provides a checked replacement draft.
Expand Down
12 changes: 6 additions & 6 deletions docs/adr/0003-exodia-cross-host-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ date: 2026-06-10

## Context

Claude Code, Codex, and Cursor each provide native agent-context surfaces (`.claude/rules/` with `paths:` frontmatter, `AGENTS.md` nesting, and `.mdc` with `globs`), but the rule content is currently authored separately for each project. This creates drift, duplication, and inconsistent enforcement surfaces across repos.
Claude Code, Codex, and Cursor each provide native agent-context surfaces (`.claude/rules/` with `paths:` frontmatter, global `AGENTS.md` startup context, and `.mdc` with `globs`), but the rule content is currently authored separately for each project. This creates drift, duplication, and inconsistent enforcement surfaces across repos.

Host features verified on 2026-06-10:
- **Claude Code** natively loads `.claude/rules/` and `~/.claude/rules/` with `paths:` frontmatter scoping; no hooks needed.
- **Codex** reads `~/.codex/AGENTS.md` and `AGENTS.override.md`; nested `AGENTS.md` files are its only depth mechanism; no glob or import syntax.
- **Codex** reads `~/.codex/AGENTS.md` and `AGENTS.override.md`; this repo installs the global startup digest and does not install project-depth rule modules for Codex.
- **Cursor** `.mdc` files with `globs`, `description`, and `alwaysApply` are native; Cursor has no user-level rules directory (settings UI only).

`scripts/install.sh` already syncs `rules/etrnl` to `~/.claude/rules/etrnl` with an atomic tmp/old swap and implements `ETRNL_INSTALL_STARTUP` gating for startup files. The bundled skill family already publishes Eternal-stack patterns publicly (`money-vo-discipline`, `abacatepay-integration`, `eternal-best-practices`).
Expand All @@ -24,11 +24,11 @@ This record is ADR 0003. ADR 0002 is taken by `etrnl-state-and-compact-handoff`.

### 2. Privacy boundary

The `eternal-saas` rule pack ships publicly. Excluded from tracked rule files: client business names, account facts, credentials, transcripts, and personal identity. Client-repo rollout lists stay in local gitignored planning paths. Enforcement: `rules-manifest.json` carries `privacy.bannedTokens`; `sync-rule-exports.mjs --check` fails when a tracked rule file contains one.
The `eternal-saas` rule pack ships publicly. Excluded from tracked rule files: client business names, account facts, credentials, transcripts, and personal identity. Client-repo rollout lists stay in local gitignored planning paths. Enforcement: `rules-manifest.json` carries generic privacy sentinel tokens plus optional untracked local token files; `sync-rule-exports.mjs --check` fails when a tracked rule file contains one.

### 3. Codex scoped depth via nested AGENTS.md
### 3. Codex uses the startup digest

Each rule module may declare `codexNested: <relative-dir>`; `sync-rule-exports.mjs` emits a nested `AGENTS.md` for declared modules; undeclared modules ride the root digest only. No import syntax exists in Codex — `@` imports are never used in Codex files.
The project rule pack installs to Claude Code and Cursor project surfaces. Codex receives the shared baseline through `~/.codex/AGENTS.md` and `AGENTS.override.md`; no nested project `AGENTS.md` files are generated by `sync-rule-exports.mjs` or `init-project-rules.sh`.

### 4. Byte budget is read, not assumed

Expand All @@ -48,7 +48,7 @@ All project-pack installs use file copies. Symlinks break for other clones, CI,

## Consequences

- One source of truth for rule content; Claude `.claude/rules/`, Cursor `.mdc`, and Codex `AGENTS.md` files are generated or installed from the same module.
- One source of truth for project rule content; Claude `.claude/rules/` and Cursor `.mdc` files are generated or installed from the same module. Codex receives the global baseline through startup files.
- `sync-rule-exports.mjs --check` in the test suite prevents host-twin drift and banned-token leaks.
- The byte-gate in `doctor.sh` keeps Codex context under the effective limit; the explicit fallback prevents silent overflow.
- Checksum-tracked installs let pilot repos self-classify drift without re-running install.
Expand Down
Loading