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
12 changes: 6 additions & 6 deletions .trinity/seals/tools_ToolsCatalog.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"gen_hash_c": "sha256:384910416b5d8272b4c4e5996275a22c4e80114239022a0175a3fb0ea37366c6",
"gen_hash_rust": "sha256:53f1d086bd48db70e287ff758507ab09c805a9856afd0ba43beee8f83f11055b",
"gen_hash_verilog": "sha256:b8e6f8c0267d8428d26348ce712dda23278355d6b78b33023442da569aef8026",
"gen_hash_zig": "sha256:571c3fbda53beff630328215d4a7128144dec103c4455d3f64c196a981cd9384",
"gen_hash_c": "sha256:a0007fe9e3313994b5afb5e3bc310241f4c9d83fd43cd6e4ad10aab48fc5f3b0",
"gen_hash_rust": "sha256:39fc1e4670ca8a6d3c28d631a926044240e6a5521cf7378096bf6f5f6dab7099",
"gen_hash_verilog": "sha256:191ac688fd734ba5ad0e9ef410dd12bcc671285692c36c591edb814289502186",
"gen_hash_zig": "sha256:4047f02d8d2d73f2f9d17a03251de5aa086ecfcc8b0813fcac99b8ff4873cacc",
"module": "ToolsCatalog",
"ring": 12,
"sealed_at": "2026-09-12T12:19:38Z",
"sealed_at": "2026-09-13T04:09:22Z",
"sealed_by": "t27c-bootstrap@0.2.0",
"spec_hash": "sha256:697ee78508508e7b71573758a7336b359795faf20d4b2aeeb7ee6dc48a52d12e",
"spec_hash": "sha256:1ec86e7561e1830b7f478ffc835f028522b5297c375296b7674990b182956235",
"spec_path": "specs/tools/catalog.t27"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# NOW -- The Queen holds the scheduler: crons and skills as one Inngest app (2026-09-13)

## The Queen holds the scheduler: crons and skills as one Inngest app (Closes #3594)

- `specs/automation/inngest-queen-scheduler.t27` (module `automation::inngest_queen_scheduler`, `KIND = "automation"`) states how the 33 cron cards and 26 skill cards of `specs/crons` and `specs/skills` become functions of one Inngest app, `APP_ID = "t27-queen"`, served by the Queen's runtime (gHashTag/BrowserOS `trios/agent-server`, `SERVE_PATH = "/api/inngest"`) against the self-hosted Inngest server of Railway project 999. Function identity from the card's `ID` (`cron-<slug>`, `skill-<slug>`), a tick event per cron (`cron/<ID>.tick`), an event per skill (`skill/<ID>.run`), `RUNS_FANOUT = true`.
- Dispatch is derived from the card's `HOST`, never from a name: `github-actions` -> `workflow-dispatch` on the repository's default branch as the API reports it; `inngest`, `timer`, `railway-cron` -> `tick-only` (the six 999 functions already carry their own schedule, a second one would fire them twice; the fourteen timers have no remote handle). A skill run is a `queen-issue` (`[skill] <ID>`, `## Success Criteria` + `## Boundary`, an open issue with the same title is reused), never a shell command.
- THE MOVE is ordered: a function is seen firing, then a PR removes the workflow's `schedule:` block, then `CONTROL` becomes `"inngest"`. No `CONTROL` field changes in this entry. Measured on the default branches: 9 of the 12 github-actions workflows declare `workflow_dispatch`; 999 `ci.yml`, 999 `security.yml` and t27 `formal-mutation.yml` do not.
- `specs/tools/mcp/inngest-dev.t27`: the tool card of the server's MCP face, written from the live `tools/list` (20 tools, their first description lines and input keys; the server marks 4 as deprecated), `TRANSPORT = "http"`, `ENV = ["INNGEST_SIGNING_KEY"]`. Measured without the key: `health`, `get_apps`, `list_runs` answer `REST API v2 returned HTTP 401: Authentication failed`; `list_docs` and `grep_docs` answer. `WITNESS = "help-output"` is the nearest word the catalog vocabulary has for "diffed against the server's own listing on a named host"; nothing claims runtime.
- `specs/agents/t.t27`: Tau (the Queen) `TOOLS` gains `mcp/inngest-dev`; the binding source is the scheduler spec's `OWNER = "T"` and `specs/OWNERS.md` (skills/ and crons/ under T-Queen).
- Checked with the bootstrap `t27c` (v0.2.0, this checkout): the three files parse, typecheck with 0 errors, `parse-complete` consumes all tokens, ASCII only. Under the trinity generator at schema 2 (gHashTag/trinity#991): tools 92 specs, mcp 11 servers, 255 tools, agents `with tools 5`, i18n tools 92/92 once the Russian row is in `apps/website/i18n/agents.ru.json`.
- `specs/tools/catalog.t27`: `LEGACY_IDS`/`LEGACY_TARGETS` gain the row (`[63]`), `LEGACY_COUNT = 63`, `MCP_CARDS = 11`; the invariant `the_legacy_table_covers_every_legacy_card` holds. `tools/trinity_tools_registry.py check` then reports one finding, `catalog MCP_CARDS is 11, the inventory measures 10`: `conformance/trinity/tools_inventory.json` is left at its 2026-09-12 measurement because `inventory` on this host reads the pinned consumer (976df517) as `table 0, mcp_enabled 0` and would replace a measured file with 54 findings of its own; the next run on a host that reads the table should pick up the eleventh card.
- Not claimed: no function of the app has been synced or fired yet; the host code is a separate PR in gHashTag/BrowserOS.
4 changes: 2 additions & 2 deletions specs/agents/t.t27
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ pub const SKILLS : [2]str = ["t27/phi-loop", "t27/tri-pipeline"];
pub const SKILLS_NOTE : str = ".claude/agents/trinity.md, Phase 2 PLAN: \"Identify required skills (phi-loop, tri-pipeline)\"; Phase 4 VERIFY: \"Run conformance tests via tri-pipeline\". specs/OWNERS.md lists skills/ and crons/ under T-Queen, which is catalog ownership, not a held skill.";
; Tool IDs (specs/tools) the agent holds. Bound only where a source line names the command
; for this letter; TOOLS_NOTE cites that line or says why the list is empty.
pub const TOOLS : [2]str = ["tri/gen", "tri/test"];
pub const TOOLS_NOTE : str = ".claude/agents/trinity.md:68 (5. Gen - Run tri gen) and :70 (7. Verify - Run tri test). No source binds tri loop or tri health to T.";
pub const TOOLS : [3]str = ["tri/gen", "tri/test", "mcp/inngest-dev"];
pub const TOOLS_NOTE : str = ".claude/agents/trinity.md:68 (5. Gen - Run tri gen) and :70 (7. Verify - Run tri test); specs/automation/inngest-queen-scheduler.t27 OWNER = \"T\" binds the scheduler mcp/inngest-dev to the Queen (specs/OWNERS.md: skills/ and crons/ under T-Queen). No source binds tri loop or tri health to T.";
; Where the agent logs episodes (AGENTS_ALPHABET.md: "Logs to .trinity/experience/").
pub const EXPERIENCE_LOG : str = ".trinity/experience/";
pub const ENABLED : bool = true;
90 changes: 90 additions & 0 deletions specs/automation/inngest-queen-scheduler.t27
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: Apache-2.0
// specs/automation/inngest-queen-scheduler.t27 -- every cron and every skill card of this
// repository (specs/crons, specs/skills) held as one Inngest app that the Queen's runtime serves.
// Host: gHashTag/BrowserOS trios/agent-server apps/server/src/inngest/ (the app), mounted on the
// same Hono server that serves /queen/*; the Inngest server is the self-hosted `inngest`
// of Railway project 999 (private address INNGEST_BASE_URL), reachable to people and bees
// through the MCP face described by specs/tools/mcp/inngest-dev.t27.
// Nothing below is inferred from a file name: the host reads these cards with the compiler
// (t27_compiler.wasm, t27_analyze -> ConstDecl) and derives every function from declared fields.
// The cron cards keep their CONTROL field; it says "inngest" only after the step this spec
// calls THE MOVE has been done for that card and the function has been seen firing.
// phi^2 + 1/phi^2 = 3 | TRINITY

module automation::inngest_queen_scheduler {

pub const KIND : str = "automation";
pub const ID : str = "inngest-queen-scheduler";
pub const REPO : str = "BrowserOS";
pub const HOST_PATH : str = "trios/agent-server/apps/server/src/inngest";
pub const VERSION : u8 = 1;
// The agent letter that holds the scheduler (specs/agents/t.t27 TOOLS names mcp/inngest-dev).
pub const OWNER : str = "T";
pub const TOOL : str = "mcp/inngest-dev";

// The app as the Inngest server sees it.
pub const APP_ID : str = "t27-queen";
pub const SERVE_PATH : str = "/api/inngest";
pub const ENV : [4]str = ["INNGEST_BASE_URL", "INNGEST_EVENT_KEY", "INNGEST_SIGNING_KEY", "INNGEST_SERVE_HOST"];
// The GitHub token the host already carries for the Queen's reads; dispatch reuses it.
pub const TOKEN_ENV : str = "TRIOS_GITHUB_API_TOKEN";
pub const GITHUB_OWNER : str = "gHashTag";

// Which cards become functions. Both directories, every *.t27, ENABLED or not.
pub const SCOPE : [2]str = ["specs/crons", "specs/skills"];
// A card that does not typecheck, or lacks a required field, is refused: the app then serves
// the cards that pass and lists the refused ones; it never guesses a field.
pub const ON_BAD_CARD : str = "refuse-card-serve-rest";

// Function identity. slug(ID) = ID lower-cased with every run outside [a-z0-9] replaced by "-".
pub const CRON_FUNCTION_ID : str = "cron-<slug>";
pub const SKILL_FUNCTION_ID : str = "skill-<slug>";
// Every cron function also answers this event, so an operator can fire it by hand.
pub const CRON_TICK_EVENT : str = "cron/<ID>.tick";
// A skill function is event-only: nothing schedules a skill directly.
pub const SKILL_RUN_EVENT : str = "skill/<ID>.run";
// A cron whose RUNS names skill IDs sends one SKILL_RUN_EVENT per ID after its own dispatch.
pub const RUNS_FANOUT : bool = true;

// What a cron function does when it fires, by the card's HOST field.
// github-actions: POST /repos/<GITHUB_OWNER>/<REPO>/actions/workflows/<basename SERVICE>/dispatches
// with ref = the repository's default branch (read from the API, not assumed).
pub const DISPATCH_GITHUB_ACTIONS : str = "workflow-dispatch";
// inngest: the card is already a function of the 999-multibots-telegraf app; registering a second
// schedule would fire it twice, so this app registers the tick event only.
pub const DISPATCH_INNGEST : str = "tick-only";
// timer: a setInterval inside a 999 process with no remote handle; tick event only, no schedule.
pub const DISPATCH_TIMER : str = "tick-only";
// railway-cron: Railway owns the schedule; tick event only.
pub const DISPATCH_RAILWAY_CRON : str = "tick-only";
// A card with ENABLED = false or an empty SCHEDULE gets no cron trigger, only the tick event.
pub const DISABLED_CARD : str = "tick-only";
// SCHEDULE is a five-field cron expression evaluated in the card's TZ.
pub const SCHEDULE_FIELDS : u8 = 5;

// What a skill function does: one issue for the Queen's bees, never a shell command.
pub const SKILL_DISPATCH : str = "queen-issue";
pub const SKILL_ISSUE_REPO : str = "<GITHUB_OWNER>/<REPO of the card>";
pub const SKILL_ISSUE_TITLE : str = "[skill] <ID>";
pub const SKILL_ISSUE_LABEL : str = "queen-skill";
// The issue body carries the two sections the Queen's brief requires.
pub const SKILL_ISSUE_SECTIONS : [2]str = ["## Success Criteria", "## Boundary"];
// An open issue with the same title is reused, not duplicated; the run reports its number.
pub const SKILL_ISSUE_DEDUP : str = "reuse-open-same-title";

// THE MOVE, per github-actions card, in this order and never the reverse:
// 1. the function is synced and seen firing (list_function_runs);
// 2. a PR to the card's REPO removes the `schedule:` block of SERVICE and keeps workflow_dispatch;
// 3. the card's CONTROL becomes "inngest".
pub const MOVE_STEPS : u8 = 3;
pub const CONTROL_AFTER_MOVE : str = "inngest";
// Measured 2026-09-13 on the default branches: 9 of the 12 github-actions SERVICE files declare
// workflow_dispatch; 999 ci.yml, 999 security.yml and t27 formal-mutation.yml do not, so their
// dispatch answers 422 until a PR adds the trigger.
pub const WORKFLOWS_WITH_DISPATCH : u8 = 9;
pub const WORKFLOWS_TOTAL : u8 = 12;

// Not claimed: no function of this app has fired yet at VERSION 1; the count of synced
// functions is read from the server (list_functions), not written here.
pub const ENABLED : bool = true;
}
7 changes: 4 additions & 3 deletions specs/tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,10 @@ Nothing in these files is typed by hand. Each file records where its text came f

Every card carries three fields beyond its family's: `REPO` (`gHashTag/t27` or
`gHashTag/trinity`), `QUALIFIED_ID` (`<owner>/<repo>:<family>/<name>`, unique across
repositories by construction) and `SCHEMA = 2`. The 62 cards written before schema 2 keep
their short `ID` (`tri/<command>`, `mcp/<server>`): the site route and the agents' `TOOLS`
arrays use it, and `QUALIFIED_ID = REPO:ID`. A card of the Trinity `tri` has
repositories by construction) and `SCHEMA = 2`. The 62 cards written before schema 2, and
`mcp/inngest-dev` (the Queen's scheduler, 2026-09-13, written with the same short form), keep
a short `ID` (`tri/<command>`, `mcp/<server>`): the site route and the agents' `TOOLS`
arrays use it, and `QUALIFIED_ID = REPO:ID`; `LEGACY_COUNT = 63` in `catalog.t27`. A card of the Trinity `tri` has
`ID = QUALIFIED_ID` and no short form, so a same-named command (`fpga`, `test` at the pin;
`COLLISIONS` in `catalog.t27`) can never be selected by the wrong repository.

Expand Down
Loading
Loading