@acnlabs/paperclip-plugin-acn 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,82 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@acnlabs/paperclip-plugin-acn` are documented here.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
6
+ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.0] - 2026-07-22
9
+
10
+ ### Changed
11
+
12
+ - **P2c C0/C1 — Issue create → Org work.** Human-created Paperclip issues now
13
+ call `POST /api/v1/orgs/{org_id}/work` instead of Task Pool `createTask`.
14
+ - **P2c C2 — Inbound `org.work_*` / `org.loop_tick`.** Harness webhooks for
15
+ Org work create/update mirror into Issues via `issue-work-map`; loop ticks
16
+ leave one throttled comment on the first mapped open work. In-flight binding
17
+ covers ACN's synchronous harness POST during `createWork` (no twin Issue);
18
+ late retries use a post-persist echo set. ACN issue tab renders Org work
19
+ ids without crashing on null Task fields. Note: for org.* events ACN's
20
+ `task_id` field carries `org_id` — the plugin keys off `event` + `data.work_id`.
21
+ - New config `acnOrgId`. When empty, setup creates an Org bound to
22
+ `acnSubnetId` and stores the id in company-scoped plugin state.
23
+ - New state map `issue-work-map` (`work_id` → issue id). Legacy
24
+ `issue-task-map` remains for inbound `task.*` mirroring and review.
25
+ - On `subnet_already_bound` (409): reuse Org id from error message when
26
+ present; otherwise fail with an explicit “set `acnOrgId`” instruction.
27
+ - Warn when `acnSubnetId` disagrees with the Org fence (prefer Org fence).
28
+ - Warn when multiple Paperclip companies exist (only the first is bound).
29
+ - `SKILL.md` rewritten for the Org work path (no longer teaches `createTask`).
30
+
31
+ - **P2c C3 — Issue status → Org work PATCH.** Moving an Org-mapped issue to
32
+ `done` / `cancelled` calls `PATCH /orgs/{id}/work/{work_id}`. `done` still
33
+ respects `autoApproveOnDone`; `cancelled` always syncs. Legacy Task `/review`
34
+ remains only for issues linked via `issue-task-map`.
35
+
36
+ ### Deprecated
37
+
38
+ - Outbound Issue → Task Pool create (removed).
39
+ - Inbound `task.*` mirror remains for transition; Issue → Task `/review` only
40
+ for legacy Task-mirrored issues.
41
+
42
+ ## [0.1.1] - 2026-05-16
43
+
44
+ ### Fixed
45
+
46
+ - **Default `acnBaseUrl` now points at the live ACN production endpoint
47
+ (`https://api.acnlabs.dev`)**. The `v0.1.0` release shipped with a
48
+ placeholder vanity domain (`https://acn.agentplanet.io`) that was never
49
+ actually registered — installing the plugin without overriding the URL would
50
+ fail at the first ACN call with `getaddrinfo ENOTFOUND`. With this release,
51
+ new users can install the plugin and connect to ACN Labs' hosted production
52
+ with zero additional infrastructure; self-hosters can still override
53
+ `acnBaseUrl` to point at their own deployment.
54
+
55
+ ### Changed
56
+
57
+ - `instanceConfigSchema.acnBaseUrl.description` now spells out the hosted /
58
+ self-host trade-off so the choice is visible in Paperclip's Instance
59
+ Settings UI without having to read the README.
60
+ - README `Prerequisites` and `Configuration` sections updated to reflect that
61
+ an ACN deployment is no longer something the user has to bring — the
62
+ default is a working public endpoint.
63
+
64
+ ## [0.1.0] - 2026-05-15
65
+
66
+ ### Added
67
+
68
+ - Initial public release on npm.
69
+ - Bidirectional sync between Paperclip issues and ACN tasks:
70
+ - ACN → Paperclip: `task.created` / `accepted` / `submitted` / `completed`
71
+ / `rejected` / `cancelled` / `participation.rejected` webhooks mirror
72
+ state into issue lifecycle + comments.
73
+ - Paperclip → ACN: human-created issues spawn ACN tasks in the configured
74
+ subnet; moving an issue to `done` (with `autoApproveOnDone`) or
75
+ `cancelled` posts the corresponding `/tasks/:id/review` decision.
76
+ - HMAC-SHA256 signed harness webhooks (`X-ACN-Signature: sha256=<hex>`),
77
+ with a compatibility layer for Paperclip's `secrets.read-ref` capability.
78
+ - Issue-detail "ACN" tab showing task ID, status, reward, participants, and
79
+ approve / reject actions for pending submissions.
80
+ - GitHub Actions: `ci.yml` (typecheck + build + tests + pack dry-run on
81
+ push/PR to main) and `release.yml` (npm publish + GitHub Release on
82
+ `v*` tags).
package/README.md CHANGED
@@ -2,20 +2,19 @@
2
2
 
3
3
  A [Paperclip](https://github.com/paperclipai/paperclip) plugin that connects ACN (Agent Collaboration Network) as the **identity, communication, and settlement** layer for agent organizations.
4
4
 
5
+ > **For AI agents helping a user set this up:** load [`SKILL.md`](./SKILL.md) — an agent-oriented, copy-pastable integration guide that complements this human-oriented README.
6
+
5
7
  ## What it does
6
8
 
7
9
  | Direction | Trigger | Action |
8
10
  |-----------|---------|--------|
9
- | ACNPaperclip | `task.created` webhook | Create a Paperclip issue (`todo`) mirroring the ACN task |
10
- | ACN → Paperclip | `task.accepted` webhook | Move issue to `in_progress`, post the assignee as a comment |
11
- | ACN → Paperclip | `task.submitted` webhook | Move issue to `in_review`, prompt reviewer to open the ACN tab |
12
- | ACNPaperclip | `task.completed` webhook | Move issue to `done`, post settlement comment |
13
- | ACN Paperclip | `task.rejected` / `task.cancelled` | Move issue to `cancelled`, post reason |
14
- | ACN → Paperclip | `participation.rejected` | Post rejection reason + resubmit-count comment |
15
- | Paperclip ACN | Issue **created** by a human (not by this plugin) | Create a corresponding ACN task in the configured subnet |
16
- | Paperclip → ACN | Issue moved to `done` (and `Auto-approve` enabled) | Call `/tasks/:id/review` → approve & settle |
17
- | Paperclip → ACN | Issue moved to `cancelled` | Call `/tasks/:id/review` → reject |
18
- | UI | ACN tab on issue | Show task ID, status, reward, participants; approve / reject pending submission |
11
+ | PaperclipACN | Issue **created** by a human (not by this plugin) | Create **Org work** on the configured ACN Org (`POST /orgs/{id}/work`) **not** Task Pool |
12
+ | ACN → Paperclip | `org.work_created` / `org.work_updated` / `org.loop_tick` | Mirror Org work into Issues (preferred inbound) |
13
+ | ACN → Paperclip | `task.*` webhooks (**legacy**) | Mirror Task Pool tasks into issues |
14
+ | PaperclipACN | Issue moved to `done` / `cancelled` | Org work `PATCH` when linked via `issue-work-map`; Task `/review` only for legacy Task mirrors |
15
+ | UI | ACN tab on issue | Shows `work_id` for Org-backed issues; Task fields for legacy mirrors |
16
+
17
+ > **P2c C0–C3 (v0.2):** Org Harness Work Port for create, inbound `org.*` webhooks, and Issue work status PATCH. Configure **ACN Org ID** (or leave empty + set **ACN Subnet ID** so setup can `POST /orgs` once).
19
18
 
20
19
  > **Note (v0.1):** the plugin does **not** create or sync Paperclip agents from ACN. The Paperclip Plugin SDK does not yet expose a dynamic-agent-creation capability, so each agent type is provisioned independently (see *Agent topology* below).
21
20
 
@@ -45,7 +44,7 @@ receive task lifecycle events.
45
44
  ### Prerequisites
46
45
 
47
46
  - A running Paperclip instance (self-hosted, with the plugin worker enabled)
48
- - An ACN deployment you can reach from the Paperclip host
47
+ - An ACN deployment you can reach from the Paperclip host — defaults to ACN Labs' hosted production at `https://api.acnlabs.dev`; point `acnBaseUrl` at your own ACN to self-host
49
48
  - An ACN **agent API key** (`acn_…`) with `task.write` scope
50
49
  - An ACN **subnet** owned by that agent (the plugin will register itself as the subnet's Org Harness)
51
50
  - A shared **HMAC secret** for signing harness webhook deliveries (any high-entropy random string, e.g. `openssl rand -hex 32`)
@@ -72,13 +71,14 @@ Paperclip → **Instance Settings → Plugins → ACN**:
72
71
 
73
72
  | Field | Required | Description |
74
73
  |-------|----------|-------------|
75
- | `acnBaseUrl` | yes | Base URL of the ACN instance (no trailing slash), e.g. `https://acn.agentplanet.io` |
74
+ | `acnBaseUrl` | no (default `https://api.acnlabs.dev`) | Base URL of the ACN instance (no trailing slash). Leave the default to use ACN Labs' hosted production, or set it to your self-hosted ACN. |
76
75
  | `paperclipBaseUrl` | **strongly recommended** | Publicly reachable base URL of **this** Paperclip instance (e.g. `https://app.paperclip.ai`). Used to construct the harness webhook URL ACN posts to. If omitted, the plugin still calls into ACN outbound (Paperclip → ACN direction works) but cannot register itself as a webhook target, so inbound ACN events will be lost. |
77
76
  | `acnApiKeyRef` | yes | Secret reference to the ACN agent API key (`acn_…`). Resolved at runtime via Paperclip's secret provider. |
77
+ | `acnOrgId` | recommended | Existing Org id (`org_…`). If empty, setup creates an Org bound to `acnSubnetId` and persists it in plugin state. |
78
78
  | `acnHarnessSecretRef` | **strongly recommended** | Secret reference to the HMAC-SHA256 secret shared with ACN. The plugin verifies every inbound webhook against `X-ACN-Signature: sha256=<hex>`. **Leave blank only in trusted dev environments** — without a secret anyone who can reach `/api/plugins/acnlabs.acn/webhooks/acn-events` can forge ACN events. |
79
79
  | `acnSubnetId` | yes | The ACN subnet whose tasks this plugin syncs |
80
80
  | `autoCreateIssues` | no (default `true`) | Auto-create Paperclip issues for new ACN tasks |
81
- | `autoApproveOnDone` | no (default `false`) | When a Paperclip user moves an ACN-linked issue to `done`, automatically call `/review?approved=true` and release payment. Off by default keeps a human in the loop. |
81
+ | `autoApproveOnDone` | no (default `false`) | When a Paperclip user moves a linked issue to `done`: Org-mapped issues PATCH work status; legacy Task mirrors call `/review?approved=true`. Off by default. `cancelled` always syncs. |
82
82
 
83
83
  ### 3. Verify
84
84
 
package/SKILL.md ADDED
@@ -0,0 +1,155 @@
1
+ ---
2
+ name: paperclip-plugin-acn
3
+ description: Connect a Paperclip instance to ACN Org Harness. Use when installing or configuring `@acnlabs/paperclip-plugin-acn`, wiring Paperclip issue → ACN Org work, registering the Paperclip side as an ACN Org Harness webhook, or debugging issue/work mirroring, webhook delivery, or HMAC signature verification. Task Pool mirroring is legacy inbound only.
4
+ license: MIT
5
+ compatibility: "Required: a self-hosted Paperclip instance with plugin worker enabled (Paperclip SDK >= 2026.512.0), HTTPS access to an ACN instance (defaults to https://api.acnlabs.dev). Required config: ACN agent API key (acn_*) with write access, either acnOrgId or acnSubnetId (to create/bind Org), and an HMAC-SHA256 secret for harness webhook signing. Load the ACN skill when the user does not yet have credentials."
6
+ metadata:
7
+ author: acnlabs
8
+ version: "0.2.0"
9
+ npm: "@acnlabs/paperclip-plugin-acn"
10
+ homepage: "https://github.com/acnlabs/paperclip-acn-plugin"
11
+ repository: "https://github.com/acnlabs/paperclip-acn-plugin"
12
+ acn_default_base_url: "https://api.acnlabs.dev"
13
+ prerequisite_skill: "acn (https://api.acnlabs.dev/skill.md)"
14
+ allowed-tools: Bash(paperclipai:*) Bash(curl:api.acnlabs.dev) Bash(curl:acn.acnlabs.cn) Bash(openssl:rand) WebFetch
15
+ ---
16
+
17
+ # Paperclip Plugin for ACN (Org Harness)
18
+
19
+ Bridges [Paperclip](https://github.com/paperclipai/paperclip) to ACN **Org Harness**:
20
+ human-created issues become **Org work items** (`POST /api/v1/orgs/{id}/work`),
21
+ not Task Pool tasks. Inbound `task.*` webhooks remain as a **legacy** mirror.
22
+
23
+ **Package:** `@acnlabs/paperclip-plugin-acn` ≥ 0.2.0
24
+ **Defaults to:** `https://api.acnlabs.dev` (use `https://acn.acnlabs.cn` for CN)
25
+ **Prerequisite skill:** [`acn`](https://api.acnlabs.dev/skill.md)
26
+
27
+ ---
28
+
29
+ ## When to use this skill
30
+
31
+ - Install / configure `@acnlabs/paperclip-plugin-acn`
32
+ - Diagnose "issue not creating Org work" or harness webhook problems
33
+ - Switch `acnBaseUrl` (global vs CN) or bind an existing `org_…`
34
+
35
+ If the user has **no Paperclip** and wants raw ACN, load the ACN skill instead.
36
+
37
+ ---
38
+
39
+ ## Quickstart (Org work path)
40
+
41
+ ```bash
42
+ paperclipai plugin install @acnlabs/paperclip-plugin-acn
43
+
44
+ # Bridge agent + subnet (ACN skill / CLI)
45
+ acn join --name "paperclip-bridge"
46
+ ACN_API_KEY=$(acn config get api_key)
47
+ SUBNET_ID=$(curl -s "$ACN_BASE/api/v1/subnets" \
48
+ -H "Authorization: Bearer $ACN_API_KEY" \
49
+ -H "Content-Type: application/json" \
50
+ -d '{"name":"paperclip-org","description":"Paperclip Org fence"}' \
51
+ | jq -r '.slug // .subnet_id')
52
+
53
+ HARNESS_SECRET=$(openssl rand -hex 32)
54
+ paperclipai secrets set acn_api_key "$ACN_API_KEY"
55
+ paperclipai secrets set acn_harness_secret "$HARNESS_SECRET"
56
+
57
+ # Instance Settings → Plugins → ACN:
58
+ # acnApiKeyRef = acn_api_key
59
+ # acnHarnessSecretRef = acn_harness_secret
60
+ # acnSubnetId = $SUBNET_ID # plugin will POST /orgs once if acnOrgId empty
61
+ # # OR set acnOrgId = org_… for an existing Org
62
+ # paperclipBaseUrl = https://<your-paperclip>
63
+ # acnBaseUrl = blank (global) or https://acn.acnlabs.cn
64
+ ```
65
+
66
+ Expect setup logs:
67
+
68
+ ```
69
+ acn-plugin: created ACN Org for company { org_id: "org_…", subnet_id: "…" }
70
+ # or: reusing / configured org
71
+ acn-plugin: registered harness { subnet_id: "…", org_id: "…", signed: true }
72
+ acn-plugin: setup complete { org_id: "…", subnet_id: "…" }
73
+ ```
74
+
75
+ Copy the logged `org_id` into `acnOrgId` for stable restarts.
76
+
77
+ ---
78
+
79
+ ## Configuration
80
+
81
+ | Field | Required | Purpose |
82
+ |---|---|---|
83
+ | `acnApiKeyRef` | yes | Secret ref → `acn_…` key |
84
+ | `acnOrgId` | recommended | Existing `org_…`. Empty → create Org bound to `acnSubnetId` |
85
+ | `acnSubnetId` | yes if no Org | Fence subnet; also used when creating Org |
86
+ | `acnHarnessSecretRef` | strongly recommended | HMAC for inbound harness webhooks |
87
+ | `paperclipBaseUrl` | strongly recommended | Public Paperclip URL for webhook registration |
88
+ | `acnBaseUrl` | no | Default `https://api.acnlabs.dev` |
89
+ | `autoCreateIssues` | no | Legacy: inbound `task.*` → Issue |
90
+ | `autoApproveOnDone` | no | Issue done → Org work PATCH (or legacy Task `/review`) |
91
+
92
+ **Subnet already bound:** if create Org returns 409 and the error message includes
93
+ `org_…`, the plugin reuses that Org. Otherwise set `acnOrgId` explicitly and restart.
94
+
95
+ **Multi-company:** only the first Paperclip company is bound to one ACN Org (v0.2).
96
+
97
+ ---
98
+
99
+ ## Behavior (v0.2)
100
+
101
+ ### Paperclip → ACN (primary)
102
+
103
+ | Event | ACN effect |
104
+ |---|---|
105
+ | `issue.created` (human, not plugin echo) | `POST /orgs/{acnOrgId}/work` with issue title |
106
+ | `issue.updated` → `done` / `cancelled` | `PATCH /orgs/{id}/work/{work_id}` when in `issue-work-map` (`done` respects `autoApproveOnDone`) |
107
+
108
+ State: company-scoped `issue-work-map` (`work_id` → issue id).
109
+
110
+ ### ACN → Paperclip (preferred)
111
+
112
+ | Event | Effect |
113
+ |---|---|
114
+ | `org.work_created` | Create Issue + `issue-work-map` (skipped if we just created the work outbound) |
115
+ | `org.work_updated` | Sync Issue status (`todo`/`done`/`cancelled`); `in_progress` → comment only |
116
+ | `org.loop_tick` | Comment on mapped open Issues (no L1 wakeup) |
117
+
118
+ ### ACN → Paperclip (legacy)
119
+
120
+ | Event | Effect |
121
+ |---|---|
122
+ | `task.*` / `participation.*` | Mirror into Issues (same as 0.1.x) |
123
+
124
+ Issue done/cancelled → Task `/review` only when the issue was Task-mirrored (`issue-task-map`).
125
+
126
+ ---
127
+
128
+ ## Verify
129
+
130
+ ```bash
131
+ # 1. Create a Paperclip issue as a human
132
+ # 2. List Org work on ACN
133
+ curl -s -H "Authorization: Bearer $ACN_API_KEY" \
134
+ "$ACN_BASE/api/v1/orgs/$ORG_ID/work" | jq .
135
+ # Expect a work item with the issue title — NOT a row under /api/v1/tasks
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Common issues
141
+
142
+ | Symptom | Fix |
143
+ |---|---|
144
+ | Setup skipped: need org or subnet | Set `acnOrgId` or `acnSubnetId` |
145
+ | 409 subnet already bound, no org hint | Set `acnOrgId` to the Org that owns the subnet |
146
+ | Issue created, no Org work | Bridge agent must govern the Org (steward); check plugin logs |
147
+ | `signed: false` | Set `acnHarnessSecretRef` |
148
+ | Still creating Tasks | Upgrade to plugin ≥ 0.2.0 and restart |
149
+
150
+ ---
151
+
152
+ ## When to use the ACN skill
153
+
154
+ Agent join, subnet admission, A2A messaging, payments, key rotation — use the ACN skill.
155
+ This skill only covers Paperclip ↔ Org Harness wiring.
@@ -1,5 +1,5 @@
1
1
  export declare const PLUGIN_ID = "acnlabs.acn";
2
- export declare const PLUGIN_VERSION = "0.1.0";
2
+ export declare const PLUGIN_VERSION = "0.2.0";
3
3
  export declare const WEBHOOK_KEYS: {
4
4
  readonly acnEvents: "acn-events";
5
5
  };
@@ -11,7 +11,11 @@ export declare const EXPORT_NAMES: {
11
11
  };
12
12
  /** Plugin state keys. State is company-scoped (see `loadMap`/`saveMap`). */
13
13
  export declare const STATE_KEYS: {
14
- /** Map of ACN taskId → Paperclip issueId. */
14
+ /** Map of ACN taskId → Paperclip issueId (legacy Task Pool mirror). */
15
15
  readonly issueTaskMap: "issue-task-map";
16
+ /** Map of ACN workId → Paperclip issueId (Org Harness Work Port). */
17
+ readonly issueWorkMap: "issue-work-map";
18
+ /** Persisted Org id when auto-created on setup (company-scoped string). */
19
+ readonly acnOrgId: "acn-org-id";
16
20
  };
17
21
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,gBAAgB,CAAC;AACvC,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,eAAO,MAAM,YAAY;;CAEf,CAAC;AAEX,eAAO,MAAM,QAAQ;;CAEX,CAAC;AAEX,eAAO,MAAM,YAAY;;CAEf,CAAC;AAEX,4EAA4E;AAC5E,eAAO,MAAM,UAAU;IACrB,6CAA6C;;CAErC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,gBAAgB,CAAC;AACvC,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,eAAO,MAAM,YAAY;;CAEf,CAAC;AAEX,eAAO,MAAM,QAAQ;;CAEX,CAAC;AAEX,eAAO,MAAM,YAAY;;CAEf,CAAC;AAEX,4EAA4E;AAC5E,eAAO,MAAM,UAAU;IACrB,uEAAuE;;IAEvE,qEAAqE;;IAErE,2EAA2E;;CAEnE,CAAC"}
package/dist/constants.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export const PLUGIN_ID = "acnlabs.acn";
2
- export const PLUGIN_VERSION = "0.1.0";
2
+ export const PLUGIN_VERSION = "0.2.0";
3
3
  export const WEBHOOK_KEYS = {
4
4
  acnEvents: "acn-events",
5
5
  };
@@ -11,7 +11,11 @@ export const EXPORT_NAMES = {
11
11
  };
12
12
  /** Plugin state keys. State is company-scoped (see `loadMap`/`saveMap`). */
13
13
  export const STATE_KEYS = {
14
- /** Map of ACN taskId → Paperclip issueId. */
14
+ /** Map of ACN taskId → Paperclip issueId (legacy Task Pool mirror). */
15
15
  issueTaskMap: "issue-task-map",
16
+ /** Map of ACN workId → Paperclip issueId (Org Harness Work Port). */
17
+ issueWorkMap: "issue-work-map",
18
+ /** Persisted Org id when auto-created on setup (company-scoped string). */
19
+ acnOrgId: "acn-org-id",
16
20
  };
17
21
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG,aAAa,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,SAAS,EAAE,YAAY;CACf,CAAC;AAEX,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,QAAQ,EAAE,eAAe;CACjB,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,QAAQ,EAAE,aAAa;CACf,CAAC;AAEX,4EAA4E;AAC5E,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,6CAA6C;IAC7C,YAAY,EAAE,gBAAgB;CACtB,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG,aAAa,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,SAAS,EAAE,YAAY;CACf,CAAC;AAEX,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,QAAQ,EAAE,eAAe;CACjB,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,QAAQ,EAAE,aAAa;CACf,CAAC;AAEX,4EAA4E;AAC5E,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,uEAAuE;IACvE,YAAY,EAAE,gBAAgB;IAC9B,qEAAqE;IACrE,YAAY,EAAE,gBAAgB;IAC9B,2EAA2E;IAC3E,QAAQ,EAAE,YAAY;CACd,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Minimal Org Harness HTTP helpers (Phase 2c C0–C3).
3
+ *
4
+ * `acn-client` 0.13.x has no Org APIs yet — call REST directly until the
5
+ * published SDK catches up. Keep this surface tiny: resolve/create Org +
6
+ * create/update work items.
7
+ */
8
+ export type OrgWorkStatus = "todo" | "in_progress" | "done" | "cancelled";
9
+ export interface OrgRecord {
10
+ org_id: string;
11
+ display_name: string;
12
+ subnet_id?: string;
13
+ fencing?: {
14
+ subnet_id?: string;
15
+ };
16
+ plugins?: Record<string, string>;
17
+ }
18
+ export interface OrgWorkItem {
19
+ work_id: string;
20
+ org_id: string;
21
+ title: string;
22
+ status: string;
23
+ assignee_agent_id?: string | null;
24
+ }
25
+ /** Structured HTTP failure from ACN (keeps status + parsed JSON body). */
26
+ export declare class AcnHttpError extends Error {
27
+ readonly status: number;
28
+ readonly bodyText: string;
29
+ readonly body: Record<string, unknown> | null;
30
+ constructor(method: string, path: string, status: number, bodyText: string);
31
+ get reason(): string | undefined;
32
+ /** Best-effort extract `org_…` from body/message (ACN may only put it in prose). */
33
+ get boundOrgIdHint(): string | undefined;
34
+ }
35
+ export declare class AcnOrgApi {
36
+ private readonly baseUrl;
37
+ private readonly apiKey;
38
+ constructor(baseUrl: string, apiKey: string);
39
+ private url;
40
+ private request;
41
+ getOrg(orgId: string): Promise<OrgRecord>;
42
+ createOrg(opts: {
43
+ display_name: string;
44
+ subnet_id?: string;
45
+ join_policy?: "open" | "approval";
46
+ }): Promise<OrgRecord>;
47
+ createWork(orgId: string, opts: {
48
+ title: string;
49
+ assignee_agent_id?: string | null;
50
+ }): Promise<OrgWorkItem>;
51
+ updateWorkStatus(orgId: string, workId: string, opts: {
52
+ status: OrgWorkStatus;
53
+ assignee_agent_id?: string | null;
54
+ }): Promise<OrgWorkItem>;
55
+ }
56
+ /** Prefer fencing.subnet_id, fall back to top-level subnet_id. */
57
+ export declare function orgSubnetId(org: OrgRecord): string | undefined;
58
+ //# sourceMappingURL=org-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-api.d.ts","sourceRoot":"","sources":["../../src/lib/org-api.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,aAAa,GAAG,MAAM,GAAG,WAAW,CAAC;AAE1E,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,0EAA0E;AAC1E,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;gBAElC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAiB1E,IAAI,MAAM,IAAI,MAAM,GAAG,SAAS,CAO/B;IAED,oFAAoF;IACpF,IAAI,cAAc,IAAI,MAAM,GAAG,SAAS,CAYvC;CACF;AAED,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAGjC,OAAO,CAAC,GAAG;YAKG,OAAO;IAkBf,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAIzC,SAAS,CAAC,IAAI,EAAE;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;KACnC,GAAG,OAAO,CAAC,SAAS,CAAC;IAQhB,UAAU,CACd,KAAK,EAAE,MAAM,EACb,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GACzD,OAAO,CAAC,WAAW,CAAC;IAYjB,gBAAgB,CACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;QAAE,MAAM,EAAE,aAAa,CAAC;QAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GACjE,OAAO,CAAC,WAAW,CAAC;CAWxB;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAE9D"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Minimal Org Harness HTTP helpers (Phase 2c C0–C3).
3
+ *
4
+ * `acn-client` 0.13.x has no Org APIs yet — call REST directly until the
5
+ * published SDK catches up. Keep this surface tiny: resolve/create Org +
6
+ * create/update work items.
7
+ */
8
+ /** Structured HTTP failure from ACN (keeps status + parsed JSON body). */
9
+ export class AcnHttpError extends Error {
10
+ status;
11
+ bodyText;
12
+ body;
13
+ constructor(method, path, status, bodyText) {
14
+ super(`ACN ${method} ${path} → ${status}: ${bodyText.slice(0, 300)}`);
15
+ this.name = "AcnHttpError";
16
+ this.status = status;
17
+ this.bodyText = bodyText;
18
+ let parsed = null;
19
+ try {
20
+ const v = JSON.parse(bodyText);
21
+ if (v && typeof v === "object" && !Array.isArray(v)) {
22
+ parsed = v;
23
+ }
24
+ }
25
+ catch {
26
+ parsed = null;
27
+ }
28
+ this.body = parsed;
29
+ }
30
+ get reason() {
31
+ const details = this.body?.details;
32
+ if (details && typeof details === "object" && !Array.isArray(details)) {
33
+ const r = details.reason;
34
+ return typeof r === "string" ? r : undefined;
35
+ }
36
+ return undefined;
37
+ }
38
+ /** Best-effort extract `org_…` from body/message (ACN may only put it in prose). */
39
+ get boundOrgIdHint() {
40
+ const details = this.body?.details;
41
+ if (details && typeof details === "object" && !Array.isArray(details)) {
42
+ const id = details.bound_org_id;
43
+ if (typeof id === "string" && id.startsWith("org_"))
44
+ return id;
45
+ }
46
+ const msg = (typeof this.body?.message === "string" ? this.body.message : "") +
47
+ " " +
48
+ this.bodyText;
49
+ const m = msg.match(/\borg_[0-9a-fA-F]+\b/);
50
+ return m?.[0];
51
+ }
52
+ }
53
+ export class AcnOrgApi {
54
+ baseUrl;
55
+ apiKey;
56
+ constructor(baseUrl, apiKey) {
57
+ this.baseUrl = baseUrl;
58
+ this.apiKey = apiKey;
59
+ }
60
+ url(path) {
61
+ const base = this.baseUrl.replace(/\/$/, "");
62
+ return `${base}${path.startsWith("/") ? path : `/${path}`}`;
63
+ }
64
+ async request(method, path, body) {
65
+ const res = await fetch(this.url(path), {
66
+ method,
67
+ headers: {
68
+ Authorization: `Bearer ${this.apiKey}`,
69
+ Accept: "application/json",
70
+ ...(body !== undefined ? { "Content-Type": "application/json" } : {}),
71
+ },
72
+ body: body !== undefined ? JSON.stringify(body) : undefined,
73
+ });
74
+ if (!res.ok) {
75
+ const text = await res.text().catch(() => "");
76
+ throw new AcnHttpError(method, path, res.status, text);
77
+ }
78
+ if (res.status === 204)
79
+ return undefined;
80
+ return (await res.json());
81
+ }
82
+ async getOrg(orgId) {
83
+ return this.request("GET", `/api/v1/orgs/${encodeURIComponent(orgId)}`);
84
+ }
85
+ async createOrg(opts) {
86
+ return this.request("POST", "/api/v1/orgs", {
87
+ display_name: opts.display_name,
88
+ subnet_id: opts.subnet_id,
89
+ join_policy: opts.join_policy ?? "open",
90
+ });
91
+ }
92
+ async createWork(orgId, opts) {
93
+ const body = { title: opts.title };
94
+ if (opts.assignee_agent_id != null && opts.assignee_agent_id !== "") {
95
+ body.assignee_agent_id = opts.assignee_agent_id;
96
+ }
97
+ return this.request("POST", `/api/v1/orgs/${encodeURIComponent(orgId)}/work`, body);
98
+ }
99
+ async updateWorkStatus(orgId, workId, opts) {
100
+ const body = { status: opts.status };
101
+ if (opts.assignee_agent_id != null && opts.assignee_agent_id !== "") {
102
+ body.assignee_agent_id = opts.assignee_agent_id;
103
+ }
104
+ return this.request("PATCH", `/api/v1/orgs/${encodeURIComponent(orgId)}/work/${encodeURIComponent(workId)}`, body);
105
+ }
106
+ }
107
+ /** Prefer fencing.subnet_id, fall back to top-level subnet_id. */
108
+ export function orgSubnetId(org) {
109
+ return org.fencing?.subnet_id || org.subnet_id || undefined;
110
+ }
111
+ //# sourceMappingURL=org-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-api.js","sourceRoot":"","sources":["../../src/lib/org-api.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AASzE,QAAA,MAAM,QAAQ,EAAE,yBAyGf,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AASzE,QAAA,MAAM,QAAQ,EAAE,yBAmHf,CAAC;AAEF,eAAe,QAAQ,CAAC"}
package/dist/manifest.js CHANGED
@@ -4,7 +4,7 @@ const manifest = {
4
4
  apiVersion: 1,
5
5
  version: PLUGIN_VERSION,
6
6
  displayName: "ACN — Agent Collaboration Network",
7
- description: "Connect Paperclip to ACN: sync tasks, manage agent identity, and settle work through the ACN protocol layer.",
7
+ description: "Connect Paperclip to ACN Org Harness: issues Org work, identity/fencing via subnet, optional legacy Task mirror inbound.",
8
8
  author: "acnlabs",
9
9
  categories: ["connector", "automation"],
10
10
  entrypoints: {
@@ -34,8 +34,8 @@ const manifest = {
34
34
  acnBaseUrl: {
35
35
  type: "string",
36
36
  title: "ACN Base URL",
37
- default: "https://acn.agentplanet.io",
38
- description: "Base URL of the ACN instance (no trailing slash).",
37
+ default: "https://api.acnlabs.dev",
38
+ description: "Base URL of the ACN instance (no trailing slash). Defaults to ACN Labs' hosted production ACN — point at your own deployment to self-host.",
39
39
  },
40
40
  paperclipBaseUrl: {
41
41
  type: "string",
@@ -55,30 +55,37 @@ const manifest = {
55
55
  default: "",
56
56
  description: "Secret reference to the shared HMAC-SHA256 secret used to sign and verify ACN harness webhook deliveries (X-ACN-Signature). Leave blank to skip verification (NOT recommended in production).",
57
57
  },
58
+ acnOrgId: {
59
+ type: "string",
60
+ title: "ACN Org ID",
61
+ default: "",
62
+ description: "Existing Org Harness org_id (org_…). If empty, the plugin creates one bound to ACN Subnet ID on first setup and stores it in plugin state.",
63
+ },
58
64
  acnSubnetId: {
59
65
  type: "string",
60
66
  title: "ACN Subnet ID",
61
67
  default: "",
62
- description: "The ACN subnet whose tasks this plugin syncs into Paperclip issues.",
68
+ description: "Fence subnet for harness webhooks. Required when ACN Org ID is empty (used to create/bind the Org). Prefer the Org's fence subnet.",
63
69
  },
64
70
  autoCreateIssues: {
65
71
  type: "boolean",
66
- title: "Auto-create Paperclip issues for new ACN tasks",
72
+ title: "Auto-create Paperclip issues for new ACN tasks (legacy)",
67
73
  default: true,
74
+ description: "Inbound task.* → Issue mirror. Outbound Issue create now writes Org work (not Task Pool).",
68
75
  },
69
76
  autoApproveOnDone: {
70
77
  type: "boolean",
71
- title: "Auto-approve ACN task when Paperclip issue moves to 'done'",
78
+ title: "Sync 'done' to ACN when Paperclip issue completes",
72
79
  default: false,
73
- description: "When disabled, a board member must click Approve in the ACN tab to release payment.",
80
+ description: "When true: Org-mapped issues PATCH work status to done; legacy Task-mirrored issues call /review approve. Cancelled always syncs.",
74
81
  },
75
82
  },
76
83
  },
77
84
  webhooks: [
78
85
  {
79
86
  endpointKey: WEBHOOK_KEYS.acnEvents,
80
- displayName: "ACN Task Events",
81
- description: "Receives HMAC-signed lifecycle events from ACN (task.created, task.submitted, task.completed, ...).",
87
+ displayName: "ACN Harness Events",
88
+ description: "Receives HMAC-signed lifecycle events from ACN (org.work_* / org.loop_tick preferred; task.* legacy).",
82
89
  },
83
90
  ],
84
91
  ui: {
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,SAAS,EACT,cAAc,EACd,QAAQ,EACR,YAAY,GACb,MAAM,gBAAgB,CAAC;AAExB,MAAM,QAAQ,GAA8B;IAC1C,EAAE,EAAE,SAAS;IACb,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,cAAc;IACvB,WAAW,EAAE,mCAAmC;IAChD,WAAW,EACT,8GAA8G;IAChH,MAAM,EAAE,SAAS;IACjB,UAAU,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC;IAEvC,WAAW,EAAE;QACX,MAAM,EAAE,gBAAgB;QACxB,EAAE,EAAE,SAAS;KACd;IAED,YAAY,EAAE;QACZ,gBAAgB;QAChB,aAAa;QACb,eAAe;QACf,eAAe;QACf,qBAAqB;QACrB,uBAAuB;QACvB,aAAa;QACb,kBAAkB;QAClB,kBAAkB;QAClB,eAAe;QACf,kBAAkB;QAClB,mBAAmB;QACnB,oBAAoB;QACpB,uBAAuB;QACvB,4BAA4B;KAC7B;IAED,oBAAoB,EAAE;QACpB,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,cAAc;gBACrB,OAAO,EAAE,4BAA4B;gBACrC,WAAW,EAAE,mDAAmD;aACjE;YACD,gBAAgB,EAAE;gBAChB,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,oBAAoB;gBAC3B,OAAO,EAAE,EAAE;gBACX,WAAW,EACT,4HAA4H;aAC/H;YACD,YAAY,EAAE;gBACZ,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,0BAA0B;gBACjC,OAAO,EAAE,EAAE;gBACX,WAAW,EACT,oFAAoF;aACvF;YACD,mBAAmB,EAAE;gBACnB,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,yCAAyC;gBAChD,OAAO,EAAE,EAAE;gBACX,WAAW,EACT,+LAA+L;aAClM;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,eAAe;gBACtB,OAAO,EAAE,EAAE;gBACX,WAAW,EACT,qEAAqE;aACxE;YACD,gBAAgB,EAAE;gBAChB,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,gDAAgD;gBACvD,OAAO,EAAE,IAAI;aACd;YACD,iBAAiB,EAAE;gBACjB,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,4DAA4D;gBACnE,OAAO,EAAE,KAAK;gBACd,WAAW,EACT,qFAAqF;aACxF;SACF;KACF;IAED,QAAQ,EAAE;QACR;YACE,WAAW,EAAE,YAAY,CAAC,SAAS;YACnC,WAAW,EAAE,iBAAiB;YAC9B,WAAW,EACT,qGAAqG;SACxG;KACF;IAED,EAAE,EAAE;QACF,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,WAAW;gBACjB,EAAE,EAAE,QAAQ,CAAC,QAAQ;gBACrB,WAAW,EAAE,KAAK;gBAClB,UAAU,EAAE,YAAY,CAAC,QAAQ;gBACjC,WAAW,EAAE,CAAC,OAAO,CAAC;aACvB;SACF;KACF;CACF,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,SAAS,EACT,cAAc,EACd,QAAQ,EACR,YAAY,GACb,MAAM,gBAAgB,CAAC;AAExB,MAAM,QAAQ,GAA8B;IAC1C,EAAE,EAAE,SAAS;IACb,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,cAAc;IACvB,WAAW,EAAE,mCAAmC;IAChD,WAAW,EACT,4HAA4H;IAC9H,MAAM,EAAE,SAAS;IACjB,UAAU,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC;IAEvC,WAAW,EAAE;QACX,MAAM,EAAE,gBAAgB;QACxB,EAAE,EAAE,SAAS;KACd;IAED,YAAY,EAAE;QACZ,gBAAgB;QAChB,aAAa;QACb,eAAe;QACf,eAAe;QACf,qBAAqB;QACrB,uBAAuB;QACvB,aAAa;QACb,kBAAkB;QAClB,kBAAkB;QAClB,eAAe;QACf,kBAAkB;QAClB,mBAAmB;QACnB,oBAAoB;QACpB,uBAAuB;QACvB,4BAA4B;KAC7B;IAED,oBAAoB,EAAE;QACpB,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,cAAc;gBACrB,OAAO,EAAE,yBAAyB;gBAClC,WAAW,EACT,4IAA4I;aAC/I;YACD,gBAAgB,EAAE;gBAChB,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,oBAAoB;gBAC3B,OAAO,EAAE,EAAE;gBACX,WAAW,EACT,4HAA4H;aAC/H;YACD,YAAY,EAAE;gBACZ,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,0BAA0B;gBACjC,OAAO,EAAE,EAAE;gBACX,WAAW,EACT,oFAAoF;aACvF;YACD,mBAAmB,EAAE;gBACnB,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,yCAAyC;gBAChD,OAAO,EAAE,EAAE;gBACX,WAAW,EACT,+LAA+L;aAClM;YACD,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,YAAY;gBACnB,OAAO,EAAE,EAAE;gBACX,WAAW,EACT,4IAA4I;aAC/I;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,eAAe;gBACtB,OAAO,EAAE,EAAE;gBACX,WAAW,EACT,oIAAoI;aACvI;YACD,gBAAgB,EAAE;gBAChB,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,yDAAyD;gBAChE,OAAO,EAAE,IAAI;gBACb,WAAW,EACT,2FAA2F;aAC9F;YACD,iBAAiB,EAAE;gBACjB,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,mDAAmD;gBAC1D,OAAO,EAAE,KAAK;gBACd,WAAW,EACT,mIAAmI;aACtI;SACF;KACF;IAED,QAAQ,EAAE;QACR;YACE,WAAW,EAAE,YAAY,CAAC,SAAS;YACnC,WAAW,EAAE,oBAAoB;YACjC,WAAW,EACT,uGAAuG;SAC1G;KACF;IAED,EAAE,EAAE;QACF,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,WAAW;gBACjB,EAAE,EAAE,QAAQ,CAAC,QAAQ;gBACrB,WAAW,EAAE,KAAK;gBAClB,UAAU,EAAE,YAAY,CAAC,QAAQ;gBACjC,WAAW,EAAE,CAAC,OAAO,CAAC;aACvB;SACF;KACF;CACF,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -1,11 +1,15 @@
1
1
  import { type PluginDetailTabProps } from "@paperclipai/plugin-sdk/ui";
2
2
  export interface AcnTaskInfo {
3
- task_id: string;
4
- title: string;
5
- status: string;
3
+ /** Org Harness work path vs legacy Task Pool mirror. */
4
+ source?: "org_work" | "task_pool";
5
+ work_id?: string | null;
6
+ org_id?: string | null;
7
+ task_id: string | null;
8
+ title: string | null;
9
+ status: string | null;
6
10
  /** Decimal string from ACN backend (e.g. "10.00"). */
7
- reward: string;
8
- reward_currency: string;
11
+ reward: string | null;
12
+ reward_currency: string | null;
9
13
  participations: Array<{
10
14
  participation_id: string;
11
15
  agent_id: string;