@atollhq/skill-codex 0.4.10 → 0.4.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atollhq/skill-codex",
3
- "version": "0.4.10",
3
+ "version": "0.4.12",
4
4
  "description": "Install the Atoll project management integration for Codex CLI",
5
5
  "bin": {
6
6
  "skill-codex": "bin/install.mjs"
package/skill/SKILL.md CHANGED
@@ -111,6 +111,7 @@ atoll agent-context
111
111
  # List tasks
112
112
  atoll issue list --json
113
113
  atoll issue list --status todo --priority 1 --limit 25
114
+ atoll issue list --scope blocked --initiative initiative-uuid --order-by due_date --order-dir asc
114
115
 
115
116
  # View a task
116
117
  atoll issue get ATOLL-42
@@ -118,11 +119,13 @@ atoll issue view ATOLL-42 # alias kept for humans
118
119
 
119
120
  # Create a task
120
121
  atoll issue create --title "Fix login bug" --status todo --priority 1
122
+ atoll issue create --title "Weekly status review" --due-date 2026-07-06 --recurrence weekly
121
123
  atoll issue upsert --match-title --project <project-id> --title "Fix login bug" --status todo
122
124
  atoll issue bulk-create --file ./issues.json --continue-on-error
123
125
 
124
126
  # Update a task
125
127
  atoll issue update ATOLL-42 --status in_progress
128
+ atoll issue update ATOLL-42 --status in_progress --comment-body "Starting this because the activation KPI is off pace."
126
129
  atoll issue upsert ATOLL-42 --status in_progress
127
130
  atoll issue bulk-update --file ./updates.json --dry-run
128
131
 
@@ -133,6 +136,17 @@ atoll issue assign ATOLL-42 --to self
133
136
  # Comments
134
137
  atoll comment add ATOLL-42 --body "Working on this now"
135
138
 
139
+ # Labels, notifications, subtasks, activity
140
+ atoll label list
141
+ atoll label add ATOLL-42 bug
142
+ atoll notification list --json
143
+ atoll notification ack notification-uuid
144
+ atoll subtask create ATOLL-42 --title "Verify recurrence"
145
+ atoll activity issue ATOLL-42
146
+
147
+ # Read-only API fallback for uncommon inspection gaps
148
+ atoll api get /api/orgs/$ATOLL_ORG_ID/labels --json
149
+
136
150
  # Dependencies
137
151
  atoll dependency bulk-add --file ./dependencies.json --continue-on-error
138
152
 
@@ -161,6 +175,9 @@ atoll kpi create --name paying_customers --goal "Reach 100 paying customers by Q
161
175
  atoll kpi create --name mvp_tasks_done --goal "Launch MVP" --internal-task-completion
162
176
  atoll initiative create --title "Content pipeline" --goal "Reach 100 paying customers by Q2" --status active
163
177
  atoll initiative kpi link "Content pipeline" paying_customers --impact "+30 customers/mo"
178
+ atoll initiative target create "Content pipeline" --title "Publish 10 comparison posts" --mode progress --target 10 --current 0 --unit count --unit-label posts
179
+ atoll initiative target create "Retailer coverage" --title "Get 5 retailers live by July 5" --mode gate --target 5 --current 0 --unit count --unit-label retailers --target-date 2026-07-05 --due-soon-days 7
180
+ atoll initiative target issue link "Retailer coverage" "Get 5 retailers live by July 5" ATOLL-42
164
181
  atoll kpi snapshot add paying_customers --value 42 --initiative "Content pipeline" --note "End-of-week Stripe check"
165
182
 
166
183
  # Audit the strategy chain for gaps (orphaned initiatives, goals with no KPI, etc.)
@@ -179,7 +196,7 @@ CLI JSON conventions:
179
196
  - Diagnostics and errors go to stderr.
180
197
  - Interactive CLI update notices also go to stderr and are suppressed for JSON/non-TTY/CI/completion flows.
181
198
  - `atoll agent-context` returns a versioned command/flag manifest, available profile context, and structured `cli.update_available` metadata.
182
- - `atoll heartbeat --json` includes the same structured `cli` update metadata for agents.
199
+ - `atoll heartbeat --json` includes the same structured `cli` update metadata for agents, plus `attention_items`, `attention_summary`, and `recommended_action` when Atoll can propose one concrete strategy-backed next action. `atoll heartbeat --signals-only --json` preserves filtered `signals`, `attention_items`, `attention_summary`, and `recommended_action` for short polling. Handle direct attention items first, then call each handled item's `ack_endpoint`. Follow `recommended_action.usage_guidance`: prefer `suggested_write.operation` when it still matches the board, preserve KPI/initiative/initiative_target/why-now/expected-impact/first-step/success-criteria evidence, and avoid copying deferred busywork into issue or comment payloads. If a `start_work` recommendation uses `issue.update` with a body, update the issue status and preserve that body as an issue comment; `PATCH /issues/{issueId}` accepts `comment_body` for this same-request progress note.
183
200
  - `atoll plan validate/apply` consumes `schemaVersion: "atoll.plan.v1"` files with `milestones`, `issues`, `dependencies`, `initiativeLinks`, and `milestoneLinks`; local `key` values can be referenced by `milestoneKey`, `issueKey`, `dependsOn`, `blockedBy`, or `blocks`.
184
201
 
185
202
  ## KPI HTTP Sync Drafts
@@ -292,7 +309,11 @@ Keep it practical. I want the smallest strategy layer that would help an AI agen
292
309
 
293
310
  ## Quick Start — API (for advanced use)
294
311
 
295
- All CLI commands map to REST endpoints. Use the API directly when the CLI doesn't cover a specific operation.
312
+ All CLI commands map to REST endpoints. Use `atoll api get` for GET-only inspection gaps when a typed command does not exist yet. The CLI blocks `/api/internal/*`, billing, and KPI sync admin routes because some GET endpoints can run jobs, synchronize external state, or require human-admin review. Use direct API calls for writes only when the CLI does not cover a specific operation and the workflow is not human-admin-gated.
313
+
314
+ ```bash
315
+ atoll api get "/api/orgs/$ATOLL_ORG_ID/issues?status=todo" --json
316
+ ```
296
317
 
297
318
  ```bash
298
319
  # Prereq: both env vars exported (see Authentication above)
@@ -313,14 +334,18 @@ The primary pattern for autonomous agents. Prefer `atoll heartbeat --json` when
313
334
 
314
335
  - **Goal status** with days remaining
315
336
  - **KPI pace**: `pace_needed` vs `pace_actual`, trend (`accelerating`/`decelerating`/`flat`), staleness
316
- - **Initiative progress**: total/completed/stalled/blocked issue counts, expected KPI impacts
337
+ - **Initiative progress**: total/completed/stalled/blocked issue counts, expected KPI impacts, and initiative targets
317
338
  - **Assigned work** for this agent
318
339
  - **Project context**: relevant board columns, including optional descriptions that explain stage criteria for agents
319
340
  - **Signals** sorted by severity — the agent's prioritized to-do list
341
+ - **Attention items**: direct current-member notifications such as mentions, assignments, assignee comments, and creator-visible status changes, with an `ack_endpoint` to call after handling
342
+ - **Recommended action**: one deterministic strategy-backed next action when Atoll has enough evidence (`create_work`, `start_work`, `escalate_blocker`, or `refresh_metric`), including why-now, expected impact, first step, success criteria, quality warnings, and any suggested write.
320
343
 
321
344
  Heartbeat is org-scoped, but project-bound payload details are filtered by the caller's project access. Owners/admins receive full org context; members/guests only receive project-bound strategy, work health, assigned work, milestone signals, and board context for accessible projects. Non-guest members can also see unprojected org-level strategy. Shared initiatives can appear with counts and signals based only on accessible work.
322
345
 
323
- Signal types: `kpi_off_pace`, `kpi_stale`, `issue_stale`, `issue_blocked`, `milestone_overdue`, `initiative_stalled`, `webhook_failing`. Severity: `info`, `warning`, `critical`.
346
+ Signal types: `kpi_off_pace`, `kpi_stale`, `issue_stale`, `issue_blocked`, `milestone_overdue`, `initiative_stalled`, `initiative_target_due_soon`, `initiative_target_overdue`, `initiative_target_blocked`, `webhook_failing`. Severity: `info`, `warning`, `critical`.
347
+
348
+ Targets under initiatives are commitments, not business KPIs. KPIs measure business outcomes such as MRR, traffic, paying customers, or onboarding success. Use progress targets for initiative outputs such as "publish 10 comparison posts." Use gate targets for launch prerequisites such as "get 5 retailers live by July 5." Gate targets emit stateful due/blocked messages and should not be converted into fractional KPI pace such as "0.07 retailers/day."
324
349
 
325
350
  Useful CLI forms:
326
351
 
@@ -333,10 +358,12 @@ atoll heartbeat --json
333
358
 
334
359
  **The agent loop:**
335
360
  1. Call heartbeat
336
- 2. Read signals (highest severity first)
337
- 3. Reason about highest-leverage action given KPI pace and initiative state
338
- 4. Execute (unblock issues, update KPIs, create work, report progress)
339
- 5. Repeat
361
+ 2. Handle direct `attention_items` that need a reply, task update, or blocker follow-up
362
+ 3. Call each handled item's `ack_endpoint`
363
+ 4. Read remaining signals (highest severity first)
364
+ 5. Reason about highest-leverage action given direct attention, gate targets, KPI pace, and initiative state
365
+ 6. Execute (unblock issues, update KPIs, create work, report progress)
366
+ 7. Repeat
340
367
 
341
368
  ## Other Common Workflows
342
369
 
@@ -345,7 +372,7 @@ atoll heartbeat --json
345
372
  ```bash
346
373
  atoll heartbeat --signals-only # orient first
347
374
  atoll issue list --status todo --assignee self --json # find assigned work
348
- atoll issue update ATOLL-42 --status in_progress # start work
375
+ atoll issue update ATOLL-42 --status in_progress --comment-body "Starting because the linked KPI is off pace." # start work with durable context
349
376
  atoll comment add ATOLL-42 --body "Progress update…" # report progress
350
377
  atoll issue update ATOLL-42 --status done # complete
351
378
  ```
@@ -357,7 +384,8 @@ atoll issue update ATOLL-42 --status done # complete
357
384
  3. `POST /api/orgs/{id}/kpis/{kpiId}/snapshots` -- record measurement (auto-updates `current_value`)
358
385
  4. `POST /api/orgs/{id}/initiatives` -- create initiative linked to goal
359
386
  5. `POST /api/orgs/{id}/initiatives/{id}/kpi-impacts` -- declare expected KPI impact
360
- 6. Link issues and milestones to the initiative
387
+ 6. `POST /api/orgs/{id}/initiatives/{id}/targets` -- create progress or gate targets for initiative commitments
388
+ 7. Link issues and milestones to the initiative and to specific targets when the work exists to satisfy that target
361
389
 
362
390
  CLI equivalent:
363
391
 
@@ -366,6 +394,8 @@ atoll goal create --title "Reach 100 paying customers by Q2" --target-date 2026-
366
394
  atoll kpi create --name paying_customers --goal "Reach 100 paying customers by Q2" --unit count --target 100 --current 34
367
395
  atoll initiative create --title "Content pipeline" --goal "Reach 100 paying customers by Q2" --status active
368
396
  atoll initiative kpi link "Content pipeline" paying_customers --impact "+30 customers/mo"
397
+ atoll initiative target create "Content pipeline" --title "Publish 10 comparison posts" --mode progress --target 10 --current 0 --unit count --unit-label posts
398
+ atoll initiative target create "Retailer coverage" --title "Get 5 retailers live by July 5" --mode gate --target 5 --current 0 --unit count --unit-label retailers --target-date 2026-07-05 --due-soon-days 7
369
399
  atoll kpi snapshot add paying_customers --value 42 --initiative "Content pipeline" --note "End-of-week Stripe check"
370
400
  ```
371
401
 
@@ -412,7 +442,7 @@ Delivery rows expose `delivery_id`, `status`, and `next_retry_at`. Network failu
412
442
 
413
443
  ### Billing and plan limits
414
444
 
415
- Owners/admins can read billing state with `GET /api/orgs/{id}/billing` and start Stripe checkout with `POST /api/orgs/{id}/billing/checkout` using `{ "plan": "starter" }` or `{ "plan": "team" }`.
445
+ Owners/admins can read billing state with `GET /api/orgs/{id}/billing` and start a self-serve Stripe billing flow with `POST /api/orgs/{id}/billing/checkout` using `{ "plan": "starter" }`, `{ "plan": "team" }`, or `{ "plan": "pro" }`. Owner/admin read requests sync Stripe first and return `502` with `Stripe billing sync failed` if that sync cannot complete, rather than serving stale local billing state. New subscribers use Checkout; existing active, trialing, or past-due subscribers use a Billing Portal update confirmation.
416
446
 
417
447
  Creation endpoints can return `402` with `code: "PLAN_LIMIT_REACHED"` when an org reaches limits for humans, agents/integrations, active projects, or active issues.
418
448
 
@@ -440,6 +470,10 @@ Initiative create accepts `title` or legacy `name`, plus camelCase aliases `goal
440
470
 
441
471
  All endpoints are under `/api/orgs/{orgId}/...`.
442
472
 
473
+ Issue comments inherit issue project permissions: listing comments requires access to the issue's project, comment writes (add, edit, delete) require write access to that project, edit/delete still require comment authorship, and guests cannot access comments on unprojected issues.
474
+
475
+ Comment bodies accept Markdown/plain text or existing rich-text HTML. Atoll stores and returns comment bodies as sanitized HTML. If sanitization leaves no visible text or safe media, the request returns `400` with `body is required` for direct comments or `comment_body is required` for issue updates with `comment_body`.
476
+
443
477
  † `DELETE /issues/{id}` requires `owner` or `admin` role — any caller without that role (including member-role agents) gets `403`. If you just need to remove a task, use `POST /api/orgs/{orgId}/issues/{issueId}/archive` (soft delete, no role gate); reverse with `DELETE` on the same path (unarchive). In the CLI, prefer `atoll issue archive <id>`. Permanent `atoll issue delete <id>` requires `--force` and supports `--dry-run`.
444
478
 
445
479
  ### Quick enum reference
@@ -488,7 +522,7 @@ atoll feedback resend fb_123
488
522
  ## Notes
489
523
 
490
524
  - Request bodies accept camelCase; responses use snake_case
491
- - Descriptions and comments support Markdown
525
+ - Descriptions support Markdown; comment bodies accept Markdown/plain text or rich-text HTML and are stored as sanitized HTML
492
526
  - All timestamps are ISO 8601 UTC
493
527
  - Board statuses are customizable per project -- query `/board-columns` for available values and optional column descriptions
494
528
  - API changes appear in real-time on the web board
@@ -89,12 +89,12 @@ Access levels: `view`, `edit`, `admin` (default: `view`).
89
89
 
90
90
  ## Billing
91
91
 
92
- Org billing is managed through Stripe. Owners/admins can create checkout and billing portal sessions.
92
+ Org billing is managed through Stripe. Owners/admins can start self-serve billing flows and create billing portal sessions.
93
93
 
94
94
  | Method | Endpoint | Description |
95
95
  |--------|----------|-------------|
96
- | GET | `/api/orgs/{id}/billing` | Get plan, status, usage, limits, and subscription summary |
97
- | POST | `/api/orgs/{id}/billing/checkout` | Create Stripe Checkout Session (`{ plan: "starter" \| "team" }`) |
96
+ | GET | `/api/orgs/{id}/billing` | Get plan, status, usage, limits, and subscription summary; owner/admin read requests sync Stripe first and return `502` if that sync fails |
97
+ | POST | `/api/orgs/{id}/billing/checkout` | Start Stripe billing flow (`{ plan: "starter" \| "team" \| "pro" }`); new subscribers use Checkout and existing active/trialing/past-due subscribers use Billing Portal update confirmation |
98
98
  | POST | `/api/orgs/{id}/billing/portal` | Create Stripe Billing Portal Session |
99
99
 
100
100
  Plan limits are enforced when creating projects, human members, agents/integrations, and active tasks. Limit errors return `402` with `code: "PLAN_LIMIT_REACHED"`.
@@ -106,7 +106,7 @@ Plan limits are enforced when creating projects, human members, agents/integrati
106
106
  | GET | `/api/orgs/{id}/issues` | List tasks (see filters below) |
107
107
  | POST | `/api/orgs/{id}/issues` | Create task |
108
108
  | GET | `/api/orgs/{id}/issues/{issueId}` | Get task detail |
109
- | PATCH | `/api/orgs/{id}/issues/{issueId}` | Update task |
109
+ | PATCH | `/api/orgs/{id}/issues/{issueId}` | Update task; optional `comment_body` also adds a task comment in the same request |
110
110
  | DELETE | `/api/orgs/{id}/issues/{issueId}` | Delete task (admin/owner only) |
111
111
  | POST | `/api/orgs/{id}/issues/bulk` | Bulk create tasks (up to 50) |
112
112
  | GET | `/api/orgs/{id}/issues/search?q=...` | Search tasks by title |
@@ -120,7 +120,8 @@ Issue-centric initiative links follow task project permissions: reading links re
120
120
  - `status` -- `backlog`, `todo`, `in_progress`, `done`, `cancelled`
121
121
  - `priority` -- `0` (urgent), `1` (high), `2` (medium), `3` (low)
122
122
  - `projectId`, `assigneeId`, `teamId`, `milestoneId`
123
- - `q` -- search title and description (case-insensitive)
123
+ - `q` -- full issue lists search title and description (case-insensitive)
124
+ - Compact views (`view=board` or `view=list`) also support `assignee` (member ID or `unassigned`, including multi-assignee links), `initiativeId`, `scope` (`mine` or `blocked`), and `q` over title plus issue number
124
125
  - `includeArchived` -- `true` to include archived tasks
125
126
  - `orderBy` -- `created_at` (default), `updated_at`, `priority`, `due_date`, `title`, `status`
126
127
  - `orderDir` -- `asc` or `desc` (default)
@@ -149,6 +150,10 @@ Add with `{ "blockedByIssueId": "uuid" }` or `{ "blockingIssueId": "uuid" }`. Ci
149
150
  | PATCH | `/api/orgs/{id}/issues/{issueId}/comments/{commentId}` | Edit comment |
150
151
  | DELETE | `/api/orgs/{id}/issues/{issueId}/comments/{commentId}` | Delete comment |
151
152
 
153
+ Issue comments inherit issue project permissions: listing comments requires access to the issue's project, comment writes (add, edit, delete) require write access to that project, edit/delete still require comment authorship, and guests cannot access comments on unprojected issues.
154
+
155
+ Comment bodies accept Markdown/plain text or existing rich-text HTML. Atoll stores and returns comment bodies as sanitized HTML. If sanitization leaves no visible text or safe media, the request returns `400` with `body is required` for direct comments or `comment_body is required` for issue updates with `comment_body`.
156
+
152
157
  ## Subtasks
153
158
 
154
159
  | Method | Endpoint | Description |
@@ -245,6 +250,19 @@ Create accepts `title` or legacy `name`, plus camelCase aliases `goalId`, `owner
245
250
  | GET | `.../initiatives/{id}/milestones` | List linked milestones |
246
251
  | POST | `.../initiatives/{id}/milestones` | Link milestone (`{ milestone_id }`) |
247
252
  | DELETE | `.../initiatives/{id}/milestones/{milestoneId}` | Unlink milestone |
253
+ | GET | `.../initiatives/{id}/targets` | List initiative targets |
254
+ | POST | `.../initiatives/{id}/targets` | Create target (`{ title, mode?, current_value?, target_value?, unit?, unit_label?, target_date?, due_soon_days? }`) |
255
+ | GET | `.../initiatives/{id}/targets/{targetId}` | Get target |
256
+ | PATCH | `.../initiatives/{id}/targets/{targetId}` | Update target |
257
+ | DELETE | `.../initiatives/{id}/targets/{targetId}` | Delete target |
258
+ | GET | `.../initiatives/{id}/targets/{targetId}/issues` | List target issue links |
259
+ | POST | `.../initiatives/{id}/targets/{targetId}/issues` | Link issue to target (`{ issue_id }`) |
260
+ | DELETE | `.../initiatives/{id}/targets/{targetId}/issues/{issueId}` | Unlink issue from target |
261
+ | GET | `.../initiatives/{id}/targets/{targetId}/milestones` | List target milestone links |
262
+ | POST | `.../initiatives/{id}/targets/{targetId}/milestones` | Link milestone to target (`{ milestone_id }`) |
263
+ | DELETE | `.../initiatives/{id}/targets/{targetId}/milestones/{milestoneId}` | Unlink milestone from target |
264
+
265
+ Targets are initiative-level commitments. Use `mode: "progress"` for normal output tracking and `mode: "gate"` for launch blockers or prerequisites where KPI pace language would be misleading. Targets do not create KPI snapshots.
248
266
 
249
267
  ## Strategy
250
268
 
@@ -260,7 +278,7 @@ Returns findings only (not the full graph). Use it for a high-level review — o
260
278
  |--------|----------|-------------|
261
279
  | GET | `/api/orgs/{id}/heartbeat` | Get heartbeat context for the authenticated agent |
262
280
 
263
- Returns computed briefing with goal status, KPI pace/trend, initiative progress, assigned work, and signals. The endpoint is org-scoped, but project-bound payload details are filtered by the caller's project access; non-guest members can also see unprojected org-level strategy, and shared initiatives can appear with counts and signals based only on accessible work.
281
+ Returns computed briefing with goal status, KPI pace/trend, initiative progress, assigned work, direct `attention_items`, `attention_summary`, signals, and a deterministic `recommended_action` when Atoll can propose one concrete strategy-backed next action. The endpoint is org-scoped, but project-bound payload details are filtered by the caller's project access; non-guest members can also see unprojected org-level strategy, and shared initiatives can appear with counts and signals based only on accessible work.
264
282
 
265
283
  Signal types: `kpi_off_pace`, `kpi_stale`, `issue_stale`, `issue_blocked`, `milestone_overdue`, `initiative_stalled`, `webhook_failing`. Severity: `info`, `warning`, `critical`.
266
284
 
@@ -272,6 +290,8 @@ atoll heartbeat --signals-only
272
290
  atoll heartbeat --severity critical
273
291
  ```
274
292
 
293
+ `atoll heartbeat --signals-only --json` returns filtered `signals`, direct `attention_items`, `attention_summary`, and `recommended_action` for polling agents.
294
+
275
295
  ## Activity
276
296
 
277
297
  | Method | Endpoint | Description |
@@ -420,10 +440,16 @@ URL must be an HTTPS DNS hostname. IP literals, `localhost`, and `.local` hosts
420
440
 
421
441
  | Method | Endpoint | Description |
422
442
  |--------|----------|-------------|
443
+ | GET | `/api/orgs/{id}/notifications` | List unread actionable notifications for current org member |
444
+ | POST | `/api/orgs/{id}/notifications/{notificationId}/ack` | Acknowledge current-member notification |
445
+ | GET | `/api/orgs/{id}/notifications/preferences` | Read current-member notification preferences, including default-on mention notifications |
446
+ | POST | `/api/orgs/{id}/notifications/preferences` | Update current-member notification preferences, including mention opt-out and cleanup |
423
447
  | GET | `/api/notifications` | List notifications (last 50, unread first) |
424
448
  | POST | `/api/notifications/{id}/read` | Mark as read |
425
449
  | POST | `/api/notifications/read-all` | Mark all as read |
426
450
 
451
+ Current-member notifications can include `mention.created`, `issue.assigned`, `comment.added`, and `issue.status_changed`. Notification preferences currently support mention opt-out for `mention.created`. Disabling in-app `mention.created` delivery also attempts to acknowledge that member's currently unread mention notifications; when cleanup succeeds, muted mentions leave both the bell and heartbeat `attention_items`.
452
+
427
453
  ## Agents
428
454
 
429
455
  | Method | Endpoint | Description |
@@ -43,7 +43,7 @@ Request bodies accept **camelCase** (`assigneeId`, `projectId`). Snake_case also
43
43
  }
44
44
  ```
45
45
 
46
- All fields work on both POST (create) and PATCH (update).
46
+ Most fields work on both POST (create) and PATCH (update). `labelIds` is accepted on task create and bulk create. For existing tasks, use the label endpoints or `atoll label add/remove`.
47
47
 
48
48
  - **Multiple assignees**: Use `assigneeIds` (array). Legacy `assigneeId` (single) still works. Responses include `assignees` array with `id`, `display_name`, `type`, `avatar_url`.
49
49
  - **Start date**: Sets when work begins. Combined with `dueDate`, defines the Gantt time span.
@@ -201,6 +201,27 @@ Use `title` for create/update requests; create also accepts legacy `name`. Atoll
201
201
 
202
202
  Add/remove projects with `{ "project_id": "uuid" }`.
203
203
 
204
+ ## Initiative Target Fields
205
+
206
+ Targets attach to initiatives and track commitments separately from business KPIs. Use `mode: "progress"` for initiative outputs and `mode: "gate"` for hard launch prerequisites. Gate target heartbeat signals use stateful copy such as `0/5 retailers complete`; agents must not convert them into fractional KPI pace.
207
+
208
+ ```json
209
+ {
210
+ "title": "Get 5 retailers live by July 5",
211
+ "description": "Prerequisite before price comparison launch",
212
+ "mode": "gate",
213
+ "unit": "count",
214
+ "unit_label": "retailers",
215
+ "current_value": 0,
216
+ "target_value": 5,
217
+ "target_direction": "increase",
218
+ "target_date": "2026-07-05",
219
+ "due_soon_days": 7
220
+ }
221
+ ```
222
+
223
+ Target work links use `{ "issue_id": "issue-uuid" }` at `.../targets/{targetId}/issues` and `{ "milestone_id": "milestone-uuid" }` at `.../targets/{targetId}/milestones`. Target response rows include linked `issueIds` and `milestoneIds` when returned by the target list/get endpoints.
224
+
204
225
  ## Automation Rule Fields
205
226
 
206
227
  ```json
@@ -233,7 +254,7 @@ Add/remove projects with `{ "project_id": "uuid" }`.
233
254
 
234
255
  ## Board Context Response
235
256
 
236
- `GET /api/orgs/{id}/projects/{projectId}/board-context` returns the strategy data used by the board context rail:
257
+ `GET /api/orgs/{id}/projects/{projectId}/board-context` returns the strategy data used by the board filter toolbar:
237
258
 
238
259
  ```json
239
260
  {
@@ -333,7 +354,20 @@ Proposal JSON currently supports at most one item in each collection: `projects`
333
354
  "total_issues": 8,
334
355
  "completed_issues": 3,
335
356
  "stalled_issues": 2,
336
- "blocked_issues": 1
357
+ "blocked_issues": 1,
358
+ "project_ids": ["..."],
359
+ "linked_issues": [{
360
+ "id": "...",
361
+ "title": "Publish comparison page",
362
+ "status": "todo",
363
+ "priority": 1,
364
+ "assignee_id": "...",
365
+ "project_id": "...",
366
+ "milestone_id": null,
367
+ "number": 42,
368
+ "blocked": false,
369
+ "updated_at": "2026-03-28T12:00:00Z"
370
+ }]
337
371
  }]
338
372
  }],
339
373
  "standalone_kpis": [...],
@@ -349,12 +383,59 @@ Proposal JSON currently supports at most one item in each collection: `projects`
349
383
  }],
350
384
  "signals": [
351
385
  { "type": "kpi_off_pace", "severity": "warning", "message": "..." }
352
- ]
386
+ ],
387
+ "recommended_action": {
388
+ "id": "create_work:...",
389
+ "action_type": "create_work",
390
+ "title": "Create Content pipeline work for paying_customers",
391
+ "target_type": "initiative",
392
+ "target_id": "...",
393
+ "goal_id": "...",
394
+ "kpi_id": "...",
395
+ "initiative_id": "...",
396
+ "source_signal_ids": ["kpi_off_pace:..."],
397
+ "why_now": "paying_customers is off pace, and Content pipeline has no active linked issue.",
398
+ "expected_impact": "Create the missing execution path for the initiative expected to move paying_customers: +30 signups/mo.",
399
+ "evidence": ["KPI \"paying_customers\" is off pace..."],
400
+ "first_step": "Open Content pipeline and define the smallest task that can move paying_customers.",
401
+ "success_criteria": ["Create or update concrete follow-up actions tied to paying_customers."],
402
+ "suggested_write": {
403
+ "operation": "issue.create",
404
+ "title": "Create Content pipeline work for paying_customers",
405
+ "body": "<h2>Why now</h2>...",
406
+ "status": "todo",
407
+ "priority": 1,
408
+ "project_id": "...",
409
+ "initiative_id": "...",
410
+ "kpi_id": "...",
411
+ "initiative_target_id": "..."
412
+ },
413
+ "confidence": "high",
414
+ "caveats": [],
415
+ "quality_checks": [{ "id": "kpi_link", "status": "pass", "message": "Recommendation includes a KPI link." }],
416
+ "usage_guidance": {
417
+ "instructions": [
418
+ "Prefer suggested_write.operation when it matches the current board state and the recommendation is still current.",
419
+ "Preserve goal, KPI, initiative, initiative target, why-now, expected impact, first step, suggested_write, and success criteria evidence in any issue, status update, KPI refresh, or comment you create.",
420
+ "Do not copy deferred busywork, unrelated tasks, or caveat text into write payloads unless it is directly needed for the recommended action."
421
+ ],
422
+ "preserve_fields": ["goal_id", "kpi_id", "initiative_id", "initiative_target_id", "why_now", "expected_impact", "first_step", "success_criteria", "suggested_write"],
423
+ "avoid_payload_sources": ["deferred_busywork", "unrelated_assigned_issues", "stale_recommendations_after_board_change"]
424
+ }
425
+ }
353
426
  }
354
427
  ```
355
428
 
356
429
  Heartbeat is org-scoped, but project-bound goals, KPIs, initiatives, issue health, milestone signals, assigned work, and `project_context` are filtered by the caller's project access. Non-guest members can also see unprojected org-level strategy. Shared initiatives can appear with counts and signals based only on accessible work.
357
430
 
431
+ Heartbeat also includes `attention_items` for direct current-member notifications such as mentions, assignments, assignee comments, and creator-visible status changes. Each attention item includes `id`, `source`, `event_type`, `severity`, `action_kind`, resource fields, `target_path`, `created_at`, and `ack_endpoint`; after handling the referenced item, call `ack_endpoint` so the notification is acknowledged and removed from later heartbeat attention results. `attention_summary` includes counts such as `mentions`, `assignments`, `blockers`, and `total_unread`.
432
+
433
+ Current-member notifications can use `event_type` values such as `mention.created`, `issue.assigned`, `comment.added`, and `issue.status_changed`. Notification preferences use `event_type` (currently `mention.created`), `channel` (currently `in_app`), and `enabled` for current-member mention opt-out. Setting `enabled: false` for in-app `mention.created` also attempts to acknowledge that member's currently unread mention notifications; when cleanup succeeds, they no longer appear in notification lists or heartbeat `attention_items`.
434
+
435
+ Agents should follow `recommended_action.usage_guidance`: prefer `suggested_write.operation` when it still matches the board, preserve KPI/initiative/initiative-target/why-now/expected-impact/first-step/success-criteria evidence in any write, and avoid copying deferred busywork or unrelated assigned tasks into issue or comment payloads. When `start_work` uses `suggested_write.operation: "issue.update"` with a body, apply the status update and preserve that body as an issue comment; `PATCH /issues/{issueId}` accepts `comment_body` for this same-request progress note.
436
+
437
+ `recommended_action` is a deterministic strategy-backed next action built from heartbeat context. MVP action types are `create_work`, `start_work`, `escalate_blocker`, and `refresh_metric`; suggested writes may prefill issue creation, issue status updates, blocker comments, or KPI refresh requests. Issue-create bodies are HTML for Atoll's rich-text issue description; blocker/comment and metric-refresh bodies are plain text.
438
+
358
439
  ## Strategy Audit Response
359
440
 
360
441
  `GET /api/orgs/{id}/strategy/audit` returns findings (sorted critical → warning → info), each with a concrete `suggested_fix`, plus summary counts.
@@ -376,11 +457,11 @@ Heartbeat is org-scoped, but project-bound goals, KPIs, initiatives, issue healt
376
457
  }
377
458
  ```
378
459
 
379
- Each finding carries whichever entity ids apply: `goal_id`, `kpi_id`, `initiative_id`, `issue_id`, `milestone_id`, `project_id`. Finding `type` values:
460
+ Each finding carries whichever entity ids apply: `goal_id`, `kpi_id`, `initiative_id`, `initiative_target_id`, `issue_id`, `milestone_id`, `project_id`. Finding `type` values:
380
461
 
381
462
  - Structural: `initiative_orphaned`, `kpi_orphaned`, `goal_missing_kpi`, `goal_missing_initiative`, `dangling_initiative_project`, `dangling_initiative_issue`, `dangling_initiative_milestone`
382
463
  - KPI health: `kpi_unrecorded`, `kpi_missing_target`, `kpi_stale`, `kpi_off_pace`
383
- - Initiative health: `initiative_missing_impact`, `initiative_missing_execution`, `initiative_stalled`
464
+ - Initiative health: `initiative_missing_impact`, `initiative_missing_execution`, `initiative_stalled`, `initiative_target_missing_execution`, `initiative_target_overdue`, `initiative_target_blocked`
384
465
  - Execution: `issue_blocked`, `issue_overdue`, `milestone_overdue`
385
466
 
386
467
  ## Analytics Response
@@ -403,6 +484,7 @@ Each finding carries whichever entity ids apply: `goal_id`, `kpi_id`, `initiativ
403
484
  | Task | `status` | `backlog`, `todo`, `in_progress`, `done`, `cancelled` (custom per project via board-columns) |
404
485
  | Board column | `description` | Optional stage criteria or agent guidance |
405
486
  | Task | `priority` | `0` (urgent), `1` (high), `2` (medium), `3` (low) |
487
+ | Task update request | `comment_body` | Optional Markdown/plain text or rich-text HTML comment body created with the issue update; stored and returned as sanitized HTML |
406
488
  | Task | `recurrenceType` | `daily`, `weekly`, `monthly`, `yearly` |
407
489
  | Goal | `status` | `active`, `achieved`, `missed`, `paused`, `cancelled` |
408
490
  | KPI | `unit` | `count`, `percentage`, `currency`, `duration`, `ratio`, `custom` |
@@ -417,7 +499,7 @@ Each finding carries whichever entity ids apply: `goal_id`, `kpi_id`, `initiativ
417
499
  | Member | `role` | `owner`, `admin`, `member`, `guest` |
418
500
  | Project member | `accessLevel` | `view`, `edit`, `admin` |
419
501
  | Automation | `trigger_event` | `issue.created`, `issue.status_changed`, `issue.assigned`, `issue.priority_changed` |
420
- | Heartbeat signal | `type` | `kpi_off_pace`, `kpi_stale`, `issue_stale`, `issue_blocked`, `milestone_overdue`, `initiative_stalled`, `webhook_failing` |
502
+ | Heartbeat signal | `type` | `kpi_off_pace`, `kpi_stale`, `issue_stale`, `issue_blocked`, `milestone_overdue`, `initiative_stalled`, `initiative_target_due_soon`, `initiative_target_overdue`, `initiative_target_blocked`, `webhook_failing` |
421
503
  | Heartbeat signal | `severity` | `info`, `warning`, `critical` |
422
504
  | Custom view | `display_mode` | `board`, `list` |
423
505
 
@@ -430,7 +512,7 @@ REST list responses use resource-specific keys by default. Main list endpoints s
430
512
  ## Notes
431
513
 
432
514
  - All timestamps are ISO 8601 in UTC
433
- - Description and comment fields support Markdown
515
+ - Descriptions support Markdown; comment bodies accept Markdown/plain text or rich-text HTML and are stored as sanitized HTML
434
516
  - Board columns (statuses) are customizable per project -- query `/board-columns` for available statuses and optional descriptions
435
517
  - Default statuses for new projects: `backlog`, `todo`, `in_progress`, `done`
436
518
  - `cancelled` is always valid but not shown on the board