Skip to content

Commit 850cf5e

Browse files
ralyodioclaude
andauthored
feat(agentstack): add @logicsrc/agentstack coordination module (#5)
* feat(agentstack): add @logicsrc/agentstack coordination module AgentStack is the LogicSRC module for portable agent, task, payment, and reputation coordination across Profullstack apps. Reference implementation of the `agentstack` capability in the Profullstack Shared AppKit OpenSpec. - packages/agentstack: DID helpers (did:coinpay:user/agent), DidTask model + lifecycle, AgentStack in-memory coordinator (agents, tasks, delegation, events), and a validated LogicSRC plugin definition. 9 vitest cases. - Wire @logicsrc/agentstack into the root build chain (after plugin-core). - docs/agentstack.md + mention in openspec-comparison.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(agentstack): note dual-runtime support (Bun + Node.js + Workers + browser) Matches the revised Shared AppKit PRD's Runtime Compatibility Strategy. AgentStack is runtime-neutral (no Bun/Node-only APIs; time is injected). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent c23ce42 commit 850cf5e

11 files changed

Lines changed: 632 additions & 2 deletions

File tree

docs/agentstack.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# AgentStack
2+
3+
Status: draft module
4+
5+
AgentStack (`@logicsrc/agentstack`) is the LogicSRC module for **portable agent, task,
6+
payment, and reputation coordination** across Profullstack microsaas apps. It is the
7+
reference implementation of the `agentstack` capability defined in the Profullstack Shared
8+
AppKit OpenSpec (`profullstack-web/openspec/specs/agentstack`).
9+
10+
## Why
11+
12+
Profullstack apps (sh1pt, uGig, qaaas.dev, crawlproof, commandboard.run, coinpayportal,
13+
logicsrc, intr0s) need to share agents, tasks, reputation, and payment context without
14+
forcing a shared login or one global account database. AgentStack provides a small,
15+
provider-neutral coordination layer on top of CoinPay DIDs.
16+
17+
## Identity model
18+
19+
```txt
20+
User DID: did:coinpay:user:123
21+
Agent DID: did:coinpay:agent:abc
22+
Task: task_123
23+
```
24+
25+
Each app keeps a local `users.id` and links it to a CoinPay DID. The same person can appear
26+
in many apps while every app independently owns its account:
27+
28+
```txt
29+
sh1pt.users.id -> did:coinpay:user:123
30+
ugig.users.id -> did:coinpay:user:123
31+
qaaas.users.id -> did:coinpay:user:123
32+
crawlproof.users.id -> did:coinpay:user:123
33+
```
34+
35+
## Task lifecycle
36+
37+
```txt
38+
pending -> queued -> running -> blocked -> complete | failed | cancelled
39+
```
40+
41+
A task may carry `paymentIntentId`, `escrowId`, and `reputationEventId` so coordination,
42+
payment, escrow, and reputation stay linked. Terminal statuses (`complete`, `failed`,
43+
`cancelled`) are final.
44+
45+
## Surface
46+
47+
- DID helpers: `userDid`, `agentDid`, `makeDid`, `parseDid`
48+
- `DidTask`, `AgentProfile`, `DelegationGrant` types
49+
- `AgentStack` coordinator: `registerAgent`, `createTask`, `assignTask`,
50+
`updateTaskStatus`, `delegate`, `revokeDelegation`, `listTasks`, `snapshot`, `on`
51+
- `agentStackPlugin` — a validated LogicSRC `PluginDefinition`
52+
53+
## Runtime
54+
55+
Runtime-neutral by design — pure TypeScript, no Bun- or Node-only APIs (time is injected via
56+
the `AgentStack` constructor). Runs on Bun, Node.js, Cloudflare Workers, and the browser,
57+
matching the Profullstack dual-runtime standard (Bun + Node.js both first-class).
58+
59+
## Plugin manifest
60+
61+
```jsonc
62+
{
63+
"id": "agentstack",
64+
"name": "AgentStack",
65+
"type": ["agents", "tasks", "coordination"],
66+
"capabilities": [
67+
"agents.register", "agents.delegate",
68+
"tasks.create", "tasks.assign", "tasks.update", "tasks.publish",
69+
"reputation.sync", "payments.link", "escrow.link"
70+
],
71+
"commands": ["agents", "tasks", "delegate"],
72+
"env": ["AGENTSTACK_API_URL", "AGENTSTACK_API_KEY", "COINPAY_API_BASE_URL"]
73+
}
74+
```
75+
76+
## Relationship to other modules
77+
78+
- **CoinPay plugin** — provides the DID/wallet/payment/escrow/reputation backend AgentStack
79+
references.
80+
- **uGig plugin** — publishes tasks to the jobs/gigs marketplace via `tasks.publish`.
81+
- **AgentSwarm orchestration** — higher-level multi-agent orchestration can consume
82+
AgentStack tasks and delegation grants.
83+
84+
See also [`openspec-comparison.md`](openspec-comparison.md) and the `agentstack` OpenSpec
85+
capability.

docs/openspec-comparison.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The projects can be complementary. LogicSRC should support an `--openspec` compa
1414
| CLI direction | `logicsrc` as the canonical OpenStandards CLI. | `@fission-ai/openspec` CLI and slash-command integrations with coding tools. |
1515
| MCP | LogicSRC has a standards MCP server and should expose resources, tools, and prompts. | Site states "No MCP" as a product trait. |
1616
| SDK/API | Planned Rust, Bun, Node, Python, curl, and PWA surfaces with matching contracts. | Focus appears to be repo workflow and agent planning artifacts rather than a cross-language SDK/API standard. |
17-
| Plugins | Plugin manifest standard plus CoinPay, uGig, AgentByte, Credential Sharing, and future integration specs. | Integrates with many coding agents and editors; plugin-contract scope is not the main positioning. |
17+
| Plugins | Plugin manifest standard plus CoinPay, uGig, AgentStack, AgentByte, Credential Sharing, and future integration specs. | Integrates with many coding agents and editors; plugin-contract scope is not the main positioning. |
1818
| Compatibility idea | `logicsrc --openspec` reads/writes OpenSpec.dev-style specs/proposals/tasks where useful. | Can remain the lightweight planning layer inside repos. |
1919

2020
## CLI Flags

package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"apps/*"
1313
],
1414
"scripts": {
15-
"build": "npm --workspace @logicsrc/schemas run build && npm --workspace @logicsrc/validators run build && npm --workspace @logicsrc/sdk run build && npm --workspace @logicsrc/plugin-core run build && npm --workspace @logicsrc/account-core run build && npm --workspace @logicsrc/plugin-coinpay run build && npm --workspace @logicsrc/plugin-ugig run build && npm --workspace @logicsrc/plugin-sh1pt run build && npm --workspace @logicsrc/plugin-c0mpute run build && npm --workspace @logicsrc/plugin-feed-discovery run build && npm --workspace @logicsrc/plugin-social-accounts run build && npm --workspace @logicsrc/plugin-email-accounts run build && npm --workspace @logicsrc/tui run build && npm --workspace @logicsrc/cli run build && npm --workspace @profullstack/logicsrc-mcp run build && npm --workspace @logicsrc/commandboard-api run build && npm --workspace @logicsrc/commandboard-web run build && npm --workspace @logicsrc/web run build",
15+
"build": "npm --workspace @logicsrc/schemas run build && npm --workspace @logicsrc/validators run build && npm --workspace @logicsrc/sdk run build && npm --workspace @logicsrc/plugin-core run build && npm --workspace @logicsrc/agentstack run build && npm --workspace @logicsrc/account-core run build && npm --workspace @logicsrc/plugin-coinpay run build && npm --workspace @logicsrc/plugin-ugig run build && npm --workspace @logicsrc/plugin-sh1pt run build && npm --workspace @logicsrc/plugin-c0mpute run build && npm --workspace @logicsrc/plugin-feed-discovery run build && npm --workspace @logicsrc/plugin-social-accounts run build && npm --workspace @logicsrc/plugin-email-accounts run build && npm --workspace @logicsrc/tui run build && npm --workspace @logicsrc/cli run build && npm --workspace @profullstack/logicsrc-mcp run build && npm --workspace @logicsrc/commandboard-api run build && npm --workspace @logicsrc/commandboard-web run build && npm --workspace @logicsrc/web run build",
1616
"start": "npm --workspace @logicsrc/web run start",
1717
"test": "npm run test --workspaces --if-present",
1818
"check": "npm run build && npm run test",

packages/agentstack/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# @logicsrc/agentstack
2+
3+
AgentStack is the LogicSRC module for **portable agent, task, payment, and reputation
4+
coordination** across Profullstack microsaas apps (sh1pt, uGig, qaaas.dev, crawlproof,
5+
commandboard.run, coinpayportal, logicsrc, intr0s).
6+
7+
It is the reference implementation of the `agentstack` capability in the Profullstack
8+
Shared AppKit OpenSpec (`profullstack-web/openspec/specs/agentstack`).
9+
10+
## What it provides
11+
12+
- **DID helpers** for CoinPay-linked identities: `userDid`, `agentDid`, `makeDid`, `parseDid`
13+
(`did:coinpay:user:123`, `did:coinpay:agent:abc`).
14+
- **`DidTask`** — a portable task model with a defined status lifecycle
15+
(`pending → queued → running → blocked → complete | failed | cancelled`) that can bind to
16+
payment, escrow, and reputation events.
17+
- **`AgentStack`** — an in-memory coordinator that registers agents, tracks tasks, records
18+
delegation grants, and emits coordination events. Storage backends can wrap the same API.
19+
- **`agentStackPlugin`** — a LogicSRC `PluginDefinition` (validated against the plugin
20+
manifest schema) exposing AgentStack as a coordination plugin with routes, events,
21+
permissions, and a TUI panel.
22+
23+
## Usage
24+
25+
```ts
26+
import { AgentStack, userDid, agentDid } from "@logicsrc/agentstack";
27+
28+
const stack = new AgentStack();
29+
const owner = userDid("123");
30+
31+
stack.registerAgent({
32+
did: agentDid("abc"),
33+
name: "Build Agent",
34+
sourceApp: "commandboard.run",
35+
supportedProtocols: ["logicsrc/1"]
36+
});
37+
38+
const task = stack.createTask({ ownerDid: owner, sourceApp: "sh1pt.com", title: "Ship build" });
39+
stack.assignTask(task.id, agentDid("abc"));
40+
stack.updateTaskStatus(task.id, "running");
41+
stack.updateTaskStatus(task.id, "complete", { reputationEventId: "rep_1" });
42+
```
43+
44+
## Cross-app identity
45+
46+
Each app keeps a local `users.id` and links it to a CoinPay DID, giving cross-app identity
47+
without shared cookies or one global account database:
48+
49+
```txt
50+
sh1pt.users.id -> did:coinpay:user:123
51+
ugig.users.id -> did:coinpay:user:123
52+
```
53+
54+
## Runtime
55+
56+
Runtime-neutral by design — pure TypeScript with no Bun- or Node-only APIs (time is injected
57+
via the `AgentStack` constructor). Runs on **Bun, Node.js, Cloudflare Workers, and the
58+
browser**, matching the Profullstack dual-runtime standard.
59+
60+
## Environment
61+
62+
```txt
63+
AGENTSTACK_API_URL
64+
AGENTSTACK_API_KEY
65+
COINPAY_API_BASE_URL
66+
```
67+
68+
## Scripts
69+
70+
```bash
71+
npm run build # tsc -> dist
72+
npm test # vitest
73+
```

packages/agentstack/package.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@logicsrc/agentstack",
3+
"version": "0.1.0",
4+
"description": "AgentStack: portable agent, task, payment, and reputation coordination module for LogicSRC.",
5+
"type": "module",
6+
"main": "./dist/index.js",
7+
"types": "./dist/index.d.ts",
8+
"scripts": {
9+
"build": "tsc -p tsconfig.json",
10+
"test": "vitest run src --passWithNoTests"
11+
},
12+
"dependencies": {
13+
"@logicsrc/plugin-core": "file:../../packages/plugin-core"
14+
},
15+
"devDependencies": {
16+
"vitest": "^4.0.8"
17+
}
18+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
import { validateManifest } from "@logicsrc/plugin-core";
3+
import {
4+
AgentStack,
5+
agentDid,
6+
agentStackManifest,
7+
agentStackPlugin,
8+
makeDid,
9+
parseDid,
10+
userDid
11+
} from "./index.js";
12+
import type { AgentProfile } from "./types.js";
13+
14+
const owner = userDid("123");
15+
const agent: AgentProfile = {
16+
did: agentDid("abc"),
17+
name: "Build Agent",
18+
sourceApp: "commandboard.run",
19+
supportedProtocols: ["logicsrc/1"]
20+
};
21+
22+
describe("DID helpers", () => {
23+
it("builds and parses CoinPay DIDs", () => {
24+
expect(makeDid("user", "123")).toBe("did:coinpay:user:123");
25+
expect(parseDid(owner)).toEqual({ kind: "user", id: "123" });
26+
expect(parseDid(agentDid("abc"))).toEqual({ kind: "agent", id: "abc" });
27+
});
28+
29+
it("rejects non-CoinPay DIDs", () => {
30+
expect(parseDid("did:web:example.com")).toBeNull();
31+
expect(parseDid("did:coinpay:bot:abc")).toBeNull();
32+
});
33+
});
34+
35+
describe("AgentStack manifest", () => {
36+
it("is a valid LogicSRC plugin manifest", () => {
37+
expect(() => validateManifest(agentStackManifest)).not.toThrow();
38+
expect(agentStackPlugin.manifest.id).toBe("agentstack");
39+
});
40+
});
41+
42+
describe("AgentStack coordinator", () => {
43+
it("creates pending tasks and queues assigned ones", () => {
44+
const stack = new AgentStack();
45+
const pending = stack.createTask({ ownerDid: owner, sourceApp: "ugig.net", title: "Crawl site" });
46+
expect(pending.status).toBe("pending");
47+
48+
stack.registerAgent(agent);
49+
const assigned = stack.createTask({
50+
ownerDid: owner,
51+
sourceApp: "ugig.net",
52+
title: "Crawl site 2",
53+
assigneeDid: agent.did
54+
});
55+
expect(assigned.status).toBe("queued");
56+
});
57+
58+
it("moves a task through its lifecycle and binds reputation", () => {
59+
const stack = new AgentStack();
60+
stack.registerAgent(agent);
61+
const task = stack.createTask({ ownerDid: owner, sourceApp: "sh1pt.com", title: "Ship build" });
62+
63+
stack.assignTask(task.id, agent.did);
64+
stack.updateTaskStatus(task.id, "running");
65+
const done = stack.updateTaskStatus(task.id, "complete", { reputationEventId: "rep_1" });
66+
67+
expect(done.status).toBe("complete");
68+
expect(done.assigneeDid).toBe(agent.did);
69+
expect(done.reputationEventId).toBe("rep_1");
70+
});
71+
72+
it("refuses to transition out of a terminal status", () => {
73+
const stack = new AgentStack();
74+
const task = stack.createTask({ ownerDid: owner, sourceApp: "qaaas.dev", title: "Test run" });
75+
stack.updateTaskStatus(task.id, "cancelled");
76+
expect(() => stack.updateTaskStatus(task.id, "running")).toThrow(/cancelled/);
77+
});
78+
79+
it("records delegation grants and emits events", () => {
80+
const stack = new AgentStack();
81+
const listener = vi.fn();
82+
stack.on(listener);
83+
stack.registerAgent(agent);
84+
const grant = stack.delegate(owner, agent.did, ["tasks:create"]);
85+
86+
expect(grant.ownerDid).toBe(owner);
87+
expect(grant.agentDid).toBe(agent.did);
88+
expect(listener).toHaveBeenCalledWith(expect.objectContaining({ type: "agent.registered" }));
89+
expect(listener).toHaveBeenCalledWith(expect.objectContaining({ type: "delegation.granted" }));
90+
});
91+
92+
it("rejects unknown agents and invalid DIDs", () => {
93+
const stack = new AgentStack();
94+
expect(() => stack.createTask({ ownerDid: "nope", sourceApp: "x", title: "t" })).toThrow();
95+
const task = stack.createTask({ ownerDid: owner, sourceApp: "x", title: "t" });
96+
expect(() => stack.assignTask(task.id, agentDid("ghost"))).toThrow(/Unknown agent/);
97+
});
98+
99+
it("filters tasks in snapshots", () => {
100+
const stack = new AgentStack();
101+
stack.createTask({ ownerDid: owner, sourceApp: "x", title: "a" });
102+
stack.createTask({ ownerDid: userDid("999"), sourceApp: "x", title: "b" });
103+
expect(stack.listTasks({ ownerDid: owner })).toHaveLength(1);
104+
expect(stack.snapshot().tasks).toHaveLength(2);
105+
});
106+
});

0 commit comments

Comments
 (0)