forked from Cotal-AI/Cotal
-
Notifications
You must be signed in to change notification settings - Fork 0
docs(agents): wave coordination structure design #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
ec59694
feat(core,cli,manager,delivery): declarative command kernel — dispatc…
davidfarah2003 c45f1c0
fix(cli): --help reaches rawArgs commands; only __-internal skips the…
davidfarah2003 4b3fb6d
feat(cli,manager,workspace): one launch grammar — spawn --detach abso…
davidfarah2003 ffed39d
fix(cli,manager): --name is a real identity override in detached mode…
davidfarah2003 60bc02c
fix(cli): migrate the server-resolution live smoke with the moved res…
davidfarah2003 3bb3f68
fix(cli): attach hint shows the configured detach key, not hardcoded …
davidfarah2003 78bf3c8
test(manager): start-overrides fake ep learns the #159B readiness roster
davidfarah2003 83bf026
fix(cli): spawn --detach outlives the manager's readiness window (#15…
davidfarah2003 d00d09d
test(manager): attach smokes follow attach-client into @cotal-ai/cli
davidfarah2003 1e10664
feat(cli,delivery): setup is configure-only; go is gone; feedback int…
davidfarah2003 0d5c8c0
fix(cli): up's teardown covers the manager it now starts; control-pla…
davidfarah2003 5149769
fix(cli): up -f hands the launch spec to the ONE control-plane manager
davidfarah2003 d245b77
test(cli): poll for graceful teardown in the up live smokes
davidfarah2003 cb1f99e
fix(cli): up -f never claims a launch the control plane didn't deliver
davidfarah2003 9669543
feat(cli,workspace): operator-installed CLI extensions — cotal ext ad…
davidfarah2003 51e792d
fix(cli): ext add fails ext-vs-ext name collisions; deterministic spe…
davidfarah2003 fd9f979
feat(cli,workspace,web,demo): dogfood cotal ext — web and demo move o…
davidfarah2003 d874aaf
fix(cli): help groups render in an explicit order, not registration o…
davidfarah2003 3767474
Merge pull request #170 from Cotal-AI/worktree-cli-rework-s1
davidfarah2003 47b9cd0
Merge pull request #171 from Cotal-AI/worktree-cli-rework-s2a
davidfarah2003 ef28e51
Merge pull request #173 from Cotal-AI/worktree-cli-rework-s2b
davidfarah2003 66d30d0
Merge pull request #175 from Cotal-AI/worktree-cli-rework-s3
davidfarah2003 b86e00c
Merge pull request #177 from Cotal-AI/worktree-cli-rework-s4
davidfarah2003 9e70b1e
docs(agents): wave coordination structure — channels, routing, spawn,…
mattwilkinsonn 3f34c8e
docs(agents): harden replay + bring-up citations
mattwilkinsonn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| /** | ||
| * DOGFOOD LIVE e2e (stage 4): the REAL `cotal-web` + `@cotal-ai/demo` packages installed through | ||
| * the REAL `cotal ext` mechanism and exercised against a REAL mesh — the full operator journey: | ||
| * | ||
| * A. `web` left the core surface (unknown command; the built-in count shrank). | ||
| * B. `cotal ext add ./implementations/web` — the first real MULTI-PEER extension: BOTH | ||
| * @cotal-ai/core and @cotal-ai/workspace get linked to this binary's copies (provenance | ||
| * proves it); help + <TAB> list `web` from the manifest cache. | ||
| * C. `cotal up --detach` (JWT auth) then `cotal web`: the dashboard serves /, /app.js (packaged | ||
| * assets) and /api/meta over HTTP against the live mesh — the admin-mint + purger-pre-mint | ||
| * path, exactly as an operator runs it. | ||
| * D. `@cotal-ai/demo` on an OPEN mesh: `cotal demo --once` replays the scripted trace; the | ||
| * traffic LANDS in real channel history. | ||
| * E. `ext remove` both; `web` is unknown again. | ||
| * | ||
| * Needs dist built (the packages install per their `files: ["dist"]`), `nats-server` + npm on | ||
| * PATH. Sandboxes COTAL_HOME/XDG_CONFIG_HOME + a temp root; kills only its own pids. | ||
| * Run: pnpm smoke:dogfood:live | ||
| */ | ||
| import { spawn, spawnSync } from "node:child_process"; | ||
| import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs"; | ||
| import { tmpdir } from "node:os"; | ||
| import { join, resolve } from "node:path"; | ||
|
|
||
| const AUTH_PORT = 14361; | ||
| const OPEN_PORT = 14363; | ||
| const WEB_PORT = 14371; | ||
| const REPO = resolve(import.meta.dirname, "..", ".."); | ||
|
|
||
| const sandbox = mkdtempSync(join(tmpdir(), "cotal-dogfood-")); | ||
| const configDir = join(sandbox, "xdg"); | ||
| const home = join(sandbox, "home"); | ||
| const root = join(sandbox, "proj"); | ||
| for (const d of [configDir, home, root]) mkdirSync(d, { recursive: true }); | ||
|
|
||
| let pass = 0; | ||
| const ok = (name: string, cond: boolean, extra?: unknown) => { | ||
| if (!cond) throw new Error(`FAIL: ${name}${extra !== undefined ? ` — ${JSON.stringify(extra)}` : ""}`); | ||
| pass++; | ||
| console.log(` ✓ ${name}`); | ||
| }; | ||
|
|
||
| const env = { ...process.env, XDG_CONFIG_HOME: configDir, COTAL_HOME: home }; | ||
| const realNode = spawnSync("which", ["node"], { encoding: "utf8" }).stdout.trim(); | ||
| const tsxCli = join(REPO, "node_modules", "tsx", "dist", "cli.mjs"); | ||
| const binCotal = join(REPO, "bin", "cotal.ts"); | ||
| const cotal = (args: string[], timeout = 180_000) => | ||
| spawnSync(realNode, [tsxCli, binCotal, ...args], { encoding: "utf8", env, cwd: root, timeout }); | ||
| const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); | ||
| const alive = (pid: number) => { | ||
| try { | ||
| process.kill(pid, 0); | ||
| return true; | ||
| } catch { | ||
| return false; | ||
| } | ||
| }; | ||
|
|
||
| let webChild: ReturnType<typeof spawn> | undefined; | ||
| const ownPids: number[] = []; | ||
| try { | ||
| // -- A: web left the core surface --------------------------------------------------------------- | ||
| { | ||
| const r = cotal(["web", "--help"]); | ||
| ok("`cotal web` is unknown before the extension is installed", r.status === 1 && /unknown command: web/.test(r.stderr), r.stderr.slice(0, 150)); | ||
| } | ||
|
|
||
| // -- B: install the REAL cotal-web package (multi-peer link) -------------------------------------- | ||
| { | ||
| const r = cotal(["ext", "add", join(REPO, "implementations", "web")]); | ||
| ok("ext add cotal-web exits 0", r.status === 0, (r.stdout + r.stderr).slice(-500)); | ||
| ok("core peer linked to this binary's copy", /→ wrote @cotal-ai\/core link/.test(r.stderr), r.stderr.slice(-400)); | ||
| ok("workspace peer linked to this binary's copy", /→ wrote @cotal-ai\/workspace link/.test(r.stderr), r.stderr.slice(-400)); | ||
| ok("the add names the contributed `web` command", /web/.test(r.stdout), r.stdout); | ||
| const help = cotal(["--help"]); | ||
| ok("--help lists web (from the cache, no import)", help.status === 0 && /web\s+.*dashboard/.test(help.stdout), help.stdout.slice(-400)); | ||
| const comp = cotal(["__complete", "web", "--"]); | ||
| ok("<TAB> offers web's cached flags", comp.status === 0 && /--port/.test(comp.stdout), comp.stdout); | ||
| } | ||
|
|
||
| // -- C: the dashboard runs against a real JWT-authed mesh ----------------------------------------- | ||
| { | ||
| const up = cotal(["up", "--detach", "--server", `nats://127.0.0.1:${AUTH_PORT}`]); | ||
| ok("up --detach (auth) exits 0", up.status === 0, (up.stdout + up.stderr).slice(-400)); | ||
| for (const f of ["nats.pid", "delivery.pid", "manager.pid"] as const) { | ||
| const pid = Number(readFileSync(join(root, ".cotal", f), "utf8").trim()); | ||
| ownPids.push(pid); | ||
| } | ||
| webChild = spawn(realNode, [tsxCli, binCotal, "web", "--port", String(WEB_PORT), "--no-open"], { | ||
| env, | ||
| cwd: root, | ||
| stdio: ["ignore", "pipe", "pipe"], | ||
| }); | ||
| let webErr = ""; | ||
| webChild.stderr?.on("data", (d: Buffer) => (webErr += d.toString())); | ||
| let page: Response | undefined; | ||
| for (let i = 0; i < 30 && !page; i++) { | ||
| await sleep(1000); | ||
| page = await fetch(`http://127.0.0.1:${WEB_PORT}/`).catch(() => undefined); | ||
| } | ||
| ok("the extension `web` command serves the dashboard", page?.status === 200, webErr.slice(-400)); | ||
| const html = await page!.text(); | ||
| ok("dashboard page is the real asset (packaged via files:[dist])", /<html|<!doctype/i.test(html) && html.length > 200, html.slice(0, 120)); | ||
| const appJs = await fetch(`http://127.0.0.1:${WEB_PORT}/app.js`); | ||
| ok("static asset /app.js serves", appJs.status === 200); | ||
| const meta = (await (await fetch(`http://127.0.0.1:${WEB_PORT}/api/meta`)).json()) as { space?: string }; | ||
| ok("live /api/meta answers with the mesh's space", typeof meta.space === "string" && meta.space.length > 0, meta); | ||
| webChild.kill("SIGTERM"); | ||
| const down = cotal(["down"]); | ||
| ok("down stops the auth mesh", down.status === 0, down.stderr.slice(-200)); | ||
| } | ||
|
|
||
| // -- D: the demo trace generator on an OPEN mesh --------------------------------------------------- | ||
| { | ||
| const up = cotal(["up", "--detach", "--open", "--server", `nats://127.0.0.1:${OPEN_PORT}`]); | ||
| ok("up --detach --open exits 0", up.status === 0, (up.stdout + up.stderr).slice(-400)); | ||
| const add = cotal(["ext", "add", join(REPO, "implementations", "demo")]); | ||
| ok("ext add @cotal-ai/demo exits 0 (private package, by path)", add.status === 0, (add.stdout + add.stderr).slice(-400)); | ||
| const r = cotal(["demo", "--once", "--interval", "25", "--server", `nats://127.0.0.1:${OPEN_PORT}`], 240_000); | ||
| ok("cotal demo --once completes a full trace", r.status === 0, (r.stdout + r.stderr).slice(-400)); | ||
| ok("demo announced its agents", /agents live in space/.test(r.stdout), r.stdout.slice(0, 300)); | ||
| // The trace really landed on the mesh: read channel history through the wire protocol. | ||
| const { CotalEndpoint } = await import("@cotal-ai/core"); | ||
| const ep = new CotalEndpoint({ | ||
| space: "main", | ||
| servers: `nats://127.0.0.1:${OPEN_PORT}`, | ||
| channels: [], | ||
| consume: false, | ||
| registerPresence: false, | ||
| watchPresence: false, | ||
| card: { name: "probe", kind: "endpoint" }, | ||
| }); | ||
| ep.on("error", () => {}); | ||
| await ep.start(); | ||
| const hist = await ep.channelHistory("general", { limit: 50 }); | ||
| await ep.stop(); | ||
| ok("demo traffic landed in real channel history", hist.length > 0, hist.length); | ||
| const down = cotal(["down"]); | ||
| ok("down stops the open mesh", down.status === 0, down.stderr.slice(-200)); | ||
| } | ||
|
|
||
| // -- E: remove both; the surface shrinks back ------------------------------------------------------ | ||
| { | ||
| ok("ext remove cotal-web exits 0", cotal(["ext", "remove", "cotal-web"]).status === 0); | ||
| ok("ext remove @cotal-ai/demo exits 0", cotal(["ext", "remove", "@cotal-ai/demo"]).status === 0); | ||
| const r = cotal(["web"]); | ||
| ok("`cotal web` is unknown again after remove", r.status === 1 && /unknown command: web/.test(r.stderr), r.stderr.slice(0, 150)); | ||
| } | ||
|
|
||
| console.log(`\nDOGFOOD LIVE SMOKE OK ✅ (${pass} checks)`); | ||
| } finally { | ||
| webChild?.kill("SIGKILL"); | ||
| spawnSync(realNode, [tsxCli, binCotal, "down"], { encoding: "utf8", env, cwd: root }); | ||
| for (const p of ownPids) if (alive(p)) { try { process.kill(p, "SIGTERM"); } catch { /* gone */ } } | ||
| rmSync(sandbox, { recursive: true, force: true }); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: sealedsecurity/Cotal
Length of output: 158
🏁 Script executed:
Repository: sealedsecurity/Cotal
Length of output: 50379
Remove the stray “Codex” connector mention
README.md:89-90 only lists Claude and OpenCode as connectors; this should say “OpenCode auto-wires at spawn.”
🤖 Prompt for AI Agents
Source: Coding guidelines