Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 16 additions & 4 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,26 @@ A size given as `M or L` is conditional on a decision named in that slice's file
|---|---|---|
| **M0 Stands** | Repo, gate, packaging path proven | 000, 001 approved |
| **M1 Talks** | Streaming chat with any provider, persisted, crash-safe | 010–013 approved |
| **M2 Acts** | Tools with permission gate, one side-effect membrane, local receipts, context compaction | 020–024 approved |
| **M2 Acts** | Tools with permission gate, one side-effect membrane, local receipts, context compaction; the FIPS build leg that proves 024's properties | 003, 020–024 approved |
| **M3 Remembers** | Persona, always-on memory, FTS + semantic recall, project context, and data you can take with you | 030–034 approved |
| **M4 Learns** | Skills system with agent self-management + approval | 040–041 approved |
| **M5a Automates** | Cron tasks and MCP, client and server, with authorization | 050, 059–062 approved |
| **M5b Reaches** | Gateways over PubSub, subagents | 070–072, 080 approved (081 optional, outside the milestone) |
| **M6 Ships** | Observability, native desktop shell, signed releases | 090–101 approved |
| **M7 Sandboxed** | Executable skills in an in-VM sandbox | 110 approved |
| **M9 Donatable** | OSS hygiene audited, supply chain signed, AAIF Sandbox package complete, shared libraries extracted | 120–123 approved (122 filing is an owner action) |
| **M9 Donatable** | OSS hygiene audited, supply chain signed, AAIF Sandbox package complete, shared libraries extracted | 002, 120–123 approved (122 filing is an owner action) |

Slices 025 and 026 carry no milestone: they serve regulated deployments after M2 and are assigned when the
standards register names the rows that ask for them.

## Slices

| ID | Slice | Phase | Size | Depends on | Status |
|---|---|---|---|---|---|
| 000 | Toolchain, repo bootstrap, quality gate | 0 Foundation | L | none | approved |
| 001 | Packaging spike: Burrito + ex_tauri smoke build | 0 Foundation | M | 000 | approved |
| 002 | Supply chain, early: SBOM, build provenance, the TLS floor | 0 Foundation | S | 000 | planned |
| 003 | FIPS build leg in CI, from source | 0 Foundation | M | 000 | planned |
| 010 | Core domain + persistence (Ecto/SQLite, schemas, Repo owner) | 1 Core loop | M | 000 | planned |
| 011 | LLM provider layer (req_llm behind `Trinity.LLM` behaviour) | 1 Core loop | M | 010 | planned |
| 012 | Session process + agent loop (gen_statem, DynamicSupervisor, rehydration) | 1 Core loop | L | 010, 011 | planned |
Expand All @@ -37,6 +42,8 @@ A size given as `M or L` is conditional on a decision named in that slice's file
| 022 | Core tools: filesystem, web fetch/search, shell (MuonTrap) | 2 Tools | L | 021 | planned |
| 023 | Context compaction + session lineage | 2 Tools | M | 012 | planned |
| 024 | Effect catalog, authority selection (`TRINITY_AUTHORITY`), local receipts | 2 Tools | L | 021, 022 | planned |
| 025 | Encryption at rest, and the key-custody seam | 2 Tools | M | 010, 024 | planned |
| 026 | Store-and-forward receipts for disconnected operation | 2 Tools | L | 024 | planned |
| 030 | Persona (SOUL) + always-on memory tier | 3 Memory | M | 012 | planned |
| 031 | Session search (SQLite FTS5) | 3 Memory | S | 010 | planned |
| 032 | Embeddings + semantic memory + hybrid retrieval | 3 Memory | L | 031 | planned |
Expand Down Expand Up @@ -81,8 +88,12 @@ for planning, not deadlines; the point here is the cut line, not a duration.

```
000 ─┬─ 001 ─────────────────────────────────────────── 100 ── 101
├─ 002 (supply chain, early)
├─ 003 (FIPS build leg; runs 024's FIPS tests)
└─ 010 ─┬─ 011 ─┬─ 090
│ └─ 012 ─┬─ 013 ── 021 ── 022 ── 024 ── 061 ── 062
│ └─ 012 ─┬─ 013 ── 021 ── 022 ── 024 ─┬─ 061 ── 062
│ │ ├─ 025 (also needs 010)
│ │ └─ 026
│ ├─ 020 ─┬─ 040 ── 041 ── 110
│ │ ├─ 059 ── 060 ── 061
│ │ └─ 080 ── (081 optional, also needs 061)
Expand Down Expand Up @@ -110,4 +121,5 @@ After 012, multiple branches are independent. If running more than one coding ag
| 2026-09-05 | Authority made an adapter behind a behaviour rather than a mode (ADR-0008, ADR-0010). ADR-0009 opened for the Jido question, decided at the 012 checkpoint. Slice 024 added: effect catalog, `TRINITY_AUTHORITY`, local receipts. Alignment appendices on 012, 020, 021, 022, 023, 030, 032, 040, 041. |
| 2026-09-05 | Review pass before commit 1. Counts in the three entries above were typed, not derived, and none matches the tree; a decreasing count is impossible under insert-never-renumber. Derived this date: `find slices -name SLICE.md | wc -l` → **38**. Milestones are derived from the Milestones table, not from memory. From here, any count in this log names the command that produced it. Entries above are not rewritten. |
| 2026-09-06 | Plan corrections, round 2. **Supersedes the slice count in the entry above:** that entry derived **38** on 2026-09-05, before slices 082, 083 and 084 were withdrawn and slice 034 was added. Re-derived this date, not adjusted by arithmetic: `find slices -name SLICE.md | wc -l` → **36**. The entry above is not rewritten. `scripts/plan_check.sh` now enforces this count, the acceptance-criteria numbering, the Definition-of-Done ranges, ROADMAP/SLICE.md agreement, and the absence of references to paths not in `git ls-files`. |
| 2026-09-20 | The MCP phase replanned under owner decisions of 2026-09-08, recorded in ADR-0007 decisions 5 to 8: beam_mcp 0.8.0 is the server core; 059 measures the capability gap and probes the `:server` seam (S/M); 060 is Trinity's thin driver (L, the M/L condition decided); the OAuth client role moves from 060 to 062; 061 carries a named blocker on the MRTR wrapper; the four `M5 Always-on` headers on 059 to 062 read M5a Automates, as this file has since 2026-09-08. R14 re-scoped, R15 closed. Re-derived this date: `find slices -name SLICE.md \| wc -l` → **36**. |
| 2026-09-20 | The MCP phase replanned under owner decisions of 2026-09-08, recorded in ADR-0007 decisions 5 to 8: beam_mcp 0.8.0 is the server core; 059 measures the capability gap and probes the `:server` seam (S/M); 060 is Trinity's thin driver (L, the M/L condition decided); the OAuth client role moves from 060 to 062; 061 carries a named blocker on the MRTR wrapper; the four `M5 Always-on` headers on 059 to 062 read M5a Automates, as this file has since 2026-09-08. R14 re-scoped, R15 closed. Re-derived this date: `find slices -name SLICE.md | wc -l` → **36**. |
| 2026-09-20 | Four slices added under the accepted 2026-09-20 plan: 002 (supply chain, early: SBOM, provenance, TLS floor; counted in M9), 003 (FIPS build leg from source; counted in M2 because it runs 024's FIPS properties), 025 (encryption at rest and the key-custody seam) and 026 (store-and-forward receipts; blocked on the external plane's answer). Re-derived this date: `find slices -name SLICE.md | wc -l` → **40**. |
72 changes: 72 additions & 0 deletions slices/002-supply-chain-early/SLICE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Slice 002: Supply chain, early: SBOM, build provenance, the TLS floor

| Field | Value |
|---|---|
| Phase | 0 Foundation |
| Milestone | M9 Donatable |
| Size | S |
| Depends on | 000 |
| Status | see ROADMAP.md |

Added 2026-09-20. Slice 121 keeps Scorecard, Sigstore signing of release artifacts, SLSA and the registry entry,
and depends on the release pipeline; the three items here need none of that and are cheap enough to carry from
now on.

## Goal
A CycloneDX software bill of materials generated by the gate and attached to every release; build provenance
attested on release artifacts through GitHub's attestation action; one README line stating the TLS floor and
that any MAC in an envelope Trinity mints is Trinity's and an approved one in FIPS mode.

## Why
Vision goal 10. A reviewer of a public tree expects to find what is in the binary and where the binary came
from without asking; a regulated deployment requires both on request. Deferring them to slice 121 means every
release before it ships without them.

## Scope
**In:**
- `sbom` (hex.pm, `mix sbom.cyclonedx`, CycloneDX) as a dev and test dependency; a gate step that generates
`sbom.cdx.json` and fails on a generation error; the file attached to every release by the package workflow.
- `actions/attest-build-provenance`, pinned to a commit SHA with its release in a comment like the other actions,
attesting each artifact the package workflow uploads. The attestation is verified in the same workflow with
`gh attestation verify` and the output kept in the run summary.
- One README line under Running from source: the TLS floor is 1.2, and any MAC over an envelope Trinity mints is
Trinity's own and is an approved algorithm in FIPS mode.
- `VERSIONS.md` row for `sbom`.
**Out:**
- Signing the SBOM or the artifacts with a Trinity-held key; Scorecard; SLSA levels; the registry entry. All
slice 121.
- A cryptography bill of materials. It follows once the minimum elements for one are published.

## Design notes
The SBOM is generated from `mix.lock`, so it is exact for Hex dependencies and blind to the Rust crates of the
desktop shell; the file says so in a top-level property and slice 121 adds the crate half. Provenance is
GitHub's, over the artifact's digest, and proves where the bytes were built, not what they do.

## Deliverables
- `mix.exs` dependency and gate step; `.github/workflows/package.yml` upload and attest steps; `README.md` line;
`lib/trinity/versions.ex` row and regenerated `VERSIONS.md`.

## Acceptance criteria
1. [auto] `mix gate` generates `sbom.cdx.json` and the file validates as CycloneDX (the validator's command and
exit code pasted).
2. [auto] A package run attaches the SBOM to its artifacts and attests each artifact; `gh attestation verify`
exits 0 for each, output in the run summary (run id cited).
3. [auto] The README carries the TLS floor line, and a test pins it so the line cannot vanish silently.
4. [auto] Gate green; coverage line reported.

## Proof required
- For each criterion: the command and its output, or a test name and its result. A sentence is not proof.

## Manual verification queue
None. Every acceptance criterion in this slice is `[auto]` and is proven by a command or a test.
If that changes during the slice, the criterion is retagged and this section is filled at G1.

## Definition of Done
- [ ] `mix gate` green · [ ] AC1–4 proven · [ ] docs/ADR/VERSIONS updated if affected · [ ] ROADMAP status → done · [ ] final commit + tag

## Commit & tag
`feat(s002): complete slice 002 (supply chain, early)` · tag `slice/002`

## Risks / open questions
- The SBOM's blindness to the desktop shell's crates is stated in the file itself; a reader who misses the
property misreads the bill. Slice 121 closes it.
79 changes: 79 additions & 0 deletions slices/003-fips-build-leg/SLICE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Slice 003: A FIPS build leg in CI, from source, so FIPS claims are proven rather than asserted

| Field | Value |
|---|---|
| Phase | 0 Foundation |
| Milestone | M2 Acts |
| Size | M |
| Depends on | 000 |
| Status | see ROADMAP.md |

Added 2026-09-20. Counted toward M2 Acts because its reason to exist is slice 024's FIPS property tests, which
cannot run anywhere else: the developer machine's OTP reports `crypto:info_fips()` as `not_supported`, and the
hosted BEAM images the gate uses are not FIPS builds.

## Goal
A second entry in the gate workflow's matrix that runs the whole suite on an OTP 28.5.0.5 built from source with
`--enable-fips` against the validated OpenSSL of a UBI9 container, with FIPS mode entered before the crypto
application loads, and a smoke that proves the mode is on. The default leg stays exactly as it is.

## Why
Slice 024's amendment says FIPS mode selects P-384 and never denies for want of a signer. Until a build runs
in FIPS mode, that is a sentence. This leg is the measurement. It also answers, once, what else in the tree
reaches an algorithm FIPS mode removes.

## Scope
**In:**
- A container image built by its own workflow, rebuilt when `.tool-versions` changes: UBI9, the distribution's
OpenSSL and its FIPS provider, OTP 28.5.0.5 from source with `--enable-fips`, Elixir 1.20.4. Published to the
repository's container registry so the gate leg pulls rather than builds.
- The gate leg: `fips_mode: true` for `:crypto` in the release's `sys.config` equivalent for tests, set before
crypto loads; the smoke `crypto:info_fips() =:= enabled` and the `fips_provider_buildinfo` key present in
`crypto:info/0`; then `mix test` and the rest of the gate as the default leg runs it.
- A committed record of `crypto:supports/1` on the FIPS leg diffed against the default leg, so the removed
algorithms are a list in the tree and not a memory.
- Runner minutes measured over the first ten runs and written into NOTES.md.
**Out:**
- Making FIPS mode the default anywhere; changing the OTP pin; ML-DSA (the UBI9 OpenSSL is a 3.0 line and does
not carry it; that measurement waits for a build against OpenSSL 3.5 or later and is `:unknown` until then).
- A FIPS-mode desktop bundle. Whether Burrito can wrap a `--enable-fips` ERTS is slice 100's question.

## Design notes
Entering or leaving FIPS mode on a running node is unsupported by OTP, so the leg sets the mode in configuration
and never toggles it in a test. A test that needs a removed algorithm on this leg is a finding, not a skip: it is
listed in the committed diff with the slice that owns it.

## Deliverables
- `.github/workflows/fips-image.yml` and the Containerfile; the second matrix entry in `.github/workflows/gate.yml`;
`docs/fips-leg.md` with the `crypto:supports/1` diff and how to reproduce the image; NOTES.md with the minutes.

## Acceptance criteria
1. [auto] On the FIPS leg, `crypto:info_fips()` returns `enabled` and `crypto:info/0` carries
`fips_provider_buildinfo` (log excerpt with the run id).
2. [auto] On the FIPS leg, `crypto:sign/4` with `eddsa` returns `notsup` and with `ecdsa` on `secp384r1` and
`sha384` returns a signature that verifies (test).
3. [auto] The committed `crypto:supports/1` diff between the two legs matches what the leg prints (test).
4. [auto] The whole gate runs on the leg; every red is either fixed or listed by test name with its owning slice
in `docs/fips-leg.md`; there is no skip tag.
5. [auto] Gate green on both legs; coverage line reported.

## Proof required
- For each criterion: the command and its output, or a test name and its result, with the run id. A sentence is
not proof.

## Manual verification queue
None. Every acceptance criterion in this slice is `[auto]` and is proven by a command or a test.
If that changes during the slice, the criterion is retagged and this section is filled at G1.

## Definition of Done
- [ ] `mix gate` green · [ ] AC1–5 proven · [ ] docs/ADR/VERSIONS updated if affected · [ ] ROADMAP status → done · [ ] final commit + tag

## Commit & tag
`feat(s003): complete slice 003 (FIPS build leg)` · tag `slice/003`

## Risks / open questions
- Building OTP from source is slow; the image workflow exists so the gate leg does not pay for it on every push.
If the image cannot be cached in the registry for a reason found at G1, the leg runs on a schedule and on
demand rather than on every push, and the slice says so.
- The validated provider a container ships is the distribution's claim; the slice cites the certificate number
the distribution publishes and does not restate it as Trinity's.
Loading
Loading