Skip to content
Open
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
85 changes: 85 additions & 0 deletions docs/agentstack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# AgentStack

Status: draft module

AgentStack (`@logicsrc/agentstack`) is the LogicSRC module for **portable agent, task,
payment, and reputation coordination** across Profullstack microsaas apps. It is the
reference implementation of the `agentstack` capability defined in the Profullstack Shared
AppKit OpenSpec (`profullstack-web/openspec/specs/agentstack`).

## Why

Profullstack apps (sh1pt, uGig, qaaas.dev, crawlproof, commandboard.run, coinpayportal,
logicsrc, intr0s) need to share agents, tasks, reputation, and payment context without
forcing a shared login or one global account database. AgentStack provides a small,
provider-neutral coordination layer on top of CoinPay DIDs.

## Identity model

```txt
User DID: did:coinpay:user:123
Agent DID: did:coinpay:agent:abc
Task: task_123
```

Each app keeps a local `users.id` and links it to a CoinPay DID. The same person can appear
in many apps while every app independently owns its account:

```txt
sh1pt.users.id -> did:coinpay:user:123
ugig.users.id -> did:coinpay:user:123
qaaas.users.id -> did:coinpay:user:123
crawlproof.users.id -> did:coinpay:user:123
```

## Task lifecycle

```txt
pending -> queued -> running -> blocked -> complete | failed | cancelled
```

A task may carry `paymentIntentId`, `escrowId`, and `reputationEventId` so coordination,
payment, escrow, and reputation stay linked. Terminal statuses (`complete`, `failed`,
`cancelled`) are final.

## Surface

- DID helpers: `userDid`, `agentDid`, `makeDid`, `parseDid`
- `DidTask`, `AgentProfile`, `DelegationGrant` types
- `AgentStack` coordinator: `registerAgent`, `createTask`, `assignTask`,
`updateTaskStatus`, `delegate`, `revokeDelegation`, `listTasks`, `snapshot`, `on`
- `agentStackPlugin` — a validated LogicSRC `PluginDefinition`

## Runtime

Runtime-neutral by design — pure TypeScript, no Bun- or Node-only APIs (time is injected via
the `AgentStack` constructor). Runs on Bun, Node.js, Cloudflare Workers, and the browser,
matching the Profullstack dual-runtime standard (Bun + Node.js both first-class).

## Plugin manifest

```jsonc
{
"id": "agentstack",
"name": "AgentStack",
"type": ["agents", "tasks", "coordination"],
"capabilities": [
"agents.register", "agents.delegate",
"tasks.create", "tasks.assign", "tasks.update", "tasks.publish",
"reputation.sync", "payments.link", "escrow.link"
],
"commands": ["agents", "tasks", "delegate"],
"env": ["AGENTSTACK_API_URL", "AGENTSTACK_API_KEY", "COINPAY_API_BASE_URL"]
}
```

## Relationship to other modules

- **CoinPay plugin** — provides the DID/wallet/payment/escrow/reputation backend AgentStack
references.
- **uGig plugin** — publishes tasks to the jobs/gigs marketplace via `tasks.publish`.
- **AgentSwarm orchestration** — higher-level multi-agent orchestration can consume
AgentStack tasks and delegation grants.

See also [`openspec-comparison.md`](openspec-comparison.md) and the `agentstack` OpenSpec
capability.
2 changes: 1 addition & 1 deletion docs/openspec-comparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The projects can be complementary. LogicSRC should support an `--openspec` compa
| CLI direction | `logicsrc` as the canonical OpenStandards CLI. | `@fission-ai/openspec` CLI and slash-command integrations with coding tools. |
| MCP | LogicSRC has a standards MCP server and should expose resources, tools, and prompts. | Site states "No MCP" as a product trait. |
| 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. |
| 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. |
| 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. |
| Compatibility idea | `logicsrc --openspec` reads/writes OpenSpec.dev-style specs/proposals/tasks where useful. | Can remain the lightweight planning layer inside repos. |

## CLI Flags
Expand Down
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"apps/*"
],
"scripts": {
"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",
"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",
"start": "npm --workspace @logicsrc/web run start",
"test": "npm run test --workspaces --if-present",
"check": "npm run build && npm run test",
Expand Down
73 changes: 73 additions & 0 deletions packages/agentstack/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# @logicsrc/agentstack

AgentStack is the LogicSRC module for **portable agent, task, payment, and reputation
coordination** across Profullstack microsaas apps (sh1pt, uGig, qaaas.dev, crawlproof,
commandboard.run, coinpayportal, logicsrc, intr0s).

It is the reference implementation of the `agentstack` capability in the Profullstack
Shared AppKit OpenSpec (`profullstack-web/openspec/specs/agentstack`).

## What it provides

- **DID helpers** for CoinPay-linked identities: `userDid`, `agentDid`, `makeDid`, `parseDid`
(`did:coinpay:user:123`, `did:coinpay:agent:abc`).
- **`DidTask`** — a portable task model with a defined status lifecycle
(`pending → queued → running → blocked → complete | failed | cancelled`) that can bind to
payment, escrow, and reputation events.
- **`AgentStack`** — an in-memory coordinator that registers agents, tracks tasks, records
delegation grants, and emits coordination events. Storage backends can wrap the same API.
- **`agentStackPlugin`** — a LogicSRC `PluginDefinition` (validated against the plugin
manifest schema) exposing AgentStack as a coordination plugin with routes, events,
permissions, and a TUI panel.

## Usage

```ts
import { AgentStack, userDid, agentDid } from "@logicsrc/agentstack";

const stack = new AgentStack();
const owner = userDid("123");

stack.registerAgent({
did: agentDid("abc"),
name: "Build Agent",
sourceApp: "commandboard.run",
supportedProtocols: ["logicsrc/1"]
});

const task = stack.createTask({ ownerDid: owner, sourceApp: "sh1pt.com", title: "Ship build" });
stack.assignTask(task.id, agentDid("abc"));
stack.updateTaskStatus(task.id, "running");
stack.updateTaskStatus(task.id, "complete", { reputationEventId: "rep_1" });
```

## Cross-app identity

Each app keeps a local `users.id` and links it to a CoinPay DID, giving cross-app identity
without shared cookies or one global account database:

```txt
sh1pt.users.id -> did:coinpay:user:123
ugig.users.id -> did:coinpay:user:123
```

## Runtime

Runtime-neutral by design — pure TypeScript with no Bun- or Node-only APIs (time is injected
via the `AgentStack` constructor). Runs on **Bun, Node.js, Cloudflare Workers, and the
browser**, matching the Profullstack dual-runtime standard.

## Environment

```txt
AGENTSTACK_API_URL
AGENTSTACK_API_KEY
COINPAY_API_BASE_URL
```

## Scripts

```bash
npm run build # tsc -> dist
npm test # vitest
```
18 changes: 18 additions & 0 deletions packages/agentstack/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@logicsrc/agentstack",
"version": "0.1.0",
"description": "AgentStack: portable agent, task, payment, and reputation coordination module for LogicSRC.",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"scripts": {
"build": "tsc -p tsconfig.json",
"test": "vitest run src --passWithNoTests"
},
"dependencies": {
"@logicsrc/plugin-core": "file:../../packages/plugin-core"
},
"devDependencies": {
"vitest": "^4.0.8"
}
}
106 changes: 106 additions & 0 deletions packages/agentstack/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { describe, expect, it, vi } from "vitest";
import { validateManifest } from "@logicsrc/plugin-core";
import {
AgentStack,
agentDid,
agentStackManifest,
agentStackPlugin,
makeDid,
parseDid,
userDid
} from "./index.js";
import type { AgentProfile } from "./types.js";

const owner = userDid("123");
const agent: AgentProfile = {
did: agentDid("abc"),
name: "Build Agent",
sourceApp: "commandboard.run",
supportedProtocols: ["logicsrc/1"]
};

describe("DID helpers", () => {
it("builds and parses CoinPay DIDs", () => {
expect(makeDid("user", "123")).toBe("did:coinpay:user:123");
expect(parseDid(owner)).toEqual({ kind: "user", id: "123" });
expect(parseDid(agentDid("abc"))).toEqual({ kind: "agent", id: "abc" });
});

it("rejects non-CoinPay DIDs", () => {
expect(parseDid("did:web:example.com")).toBeNull();
expect(parseDid("did:coinpay:bot:abc")).toBeNull();
});
});

describe("AgentStack manifest", () => {
it("is a valid LogicSRC plugin manifest", () => {
expect(() => validateManifest(agentStackManifest)).not.toThrow();
expect(agentStackPlugin.manifest.id).toBe("agentstack");
});
});

describe("AgentStack coordinator", () => {
it("creates pending tasks and queues assigned ones", () => {
const stack = new AgentStack();
const pending = stack.createTask({ ownerDid: owner, sourceApp: "ugig.net", title: "Crawl site" });
expect(pending.status).toBe("pending");

stack.registerAgent(agent);
const assigned = stack.createTask({
ownerDid: owner,
sourceApp: "ugig.net",
title: "Crawl site 2",
assigneeDid: agent.did
});
expect(assigned.status).toBe("queued");
});

it("moves a task through its lifecycle and binds reputation", () => {
const stack = new AgentStack();
stack.registerAgent(agent);
const task = stack.createTask({ ownerDid: owner, sourceApp: "sh1pt.com", title: "Ship build" });

stack.assignTask(task.id, agent.did);
stack.updateTaskStatus(task.id, "running");
const done = stack.updateTaskStatus(task.id, "complete", { reputationEventId: "rep_1" });

expect(done.status).toBe("complete");
expect(done.assigneeDid).toBe(agent.did);
expect(done.reputationEventId).toBe("rep_1");
});

it("refuses to transition out of a terminal status", () => {
const stack = new AgentStack();
const task = stack.createTask({ ownerDid: owner, sourceApp: "qaaas.dev", title: "Test run" });
stack.updateTaskStatus(task.id, "cancelled");
expect(() => stack.updateTaskStatus(task.id, "running")).toThrow(/cancelled/);
});

it("records delegation grants and emits events", () => {
const stack = new AgentStack();
const listener = vi.fn();
stack.on(listener);
stack.registerAgent(agent);
const grant = stack.delegate(owner, agent.did, ["tasks:create"]);

expect(grant.ownerDid).toBe(owner);
expect(grant.agentDid).toBe(agent.did);
expect(listener).toHaveBeenCalledWith(expect.objectContaining({ type: "agent.registered" }));
expect(listener).toHaveBeenCalledWith(expect.objectContaining({ type: "delegation.granted" }));
});

it("rejects unknown agents and invalid DIDs", () => {
const stack = new AgentStack();
expect(() => stack.createTask({ ownerDid: "nope", sourceApp: "x", title: "t" })).toThrow();
const task = stack.createTask({ ownerDid: owner, sourceApp: "x", title: "t" });
expect(() => stack.assignTask(task.id, agentDid("ghost"))).toThrow(/Unknown agent/);
});

it("filters tasks in snapshots", () => {
const stack = new AgentStack();
stack.createTask({ ownerDid: owner, sourceApp: "x", title: "a" });
stack.createTask({ ownerDid: userDid("999"), sourceApp: "x", title: "b" });
expect(stack.listTasks({ ownerDid: owner })).toHaveLength(1);
expect(stack.snapshot().tasks).toHaveLength(2);
});
});
Loading
Loading