@atollhq/skill-codex 0.4.6 → 0.4.8

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/README.md CHANGED
@@ -12,9 +12,9 @@ npx @atollhq/skill-codex --profile agent-a --key sk_atoll_... --org your-org-id
12
12
  ATOLL_API_KEY=sk_atoll_... ATOLL_ORG_ID=your-org-id npx @atollhq/skill-codex
13
13
  ```
14
14
 
15
- Optional defaults: `--project`, `--team`, and `--base-url` are stored with the selected mode. Use `--no-project`, `--no-team`, or `--no-base-url` to clear previously saved defaults. When `--profile` is set, credentials and defaults are stored only in that named Atoll CLI profile. The installer does not write global `ATOLL_*` exports to `~/.zshrc` or `~/.bashrc`. Use `atoll --profile agent-a ...` for profile-scoped commands, or omit `--profile` to use env-var mode.
15
+ Optional defaults: `--project`, `--team`, and `--base-url` are stored with the selected mode. Use `--no-project`, `--no-team`, or `--no-base-url` to clear previously saved defaults. Pass `--profile` to store credentials and defaults only in that named Atoll CLI profile. The installer does not write global `ATOLL_*` exports to `~/.zshrc` or `~/.bashrc` in profile mode. Use `atoll --profile agent-a ...` for profile-scoped commands, or omit `--profile` to use env-var mode.
16
16
 
17
- Get an API key from **Settings > Members > Add Agent** (or **Create API Key** for integrations) in the Atoll app.
17
+ Get an agent API key from **Agents** in the Atoll app. Integration keys are still managed from **Settings > Members**.
18
18
 
19
19
  This does five things:
20
20
 
@@ -24,7 +24,7 @@ This does five things:
24
24
  4. Creates or updates the named Atoll CLI profile when `--profile` is provided
25
25
  5. Appends Atoll env var exports to your shell profile (`~/.zshrc` or `~/.bashrc`) only when no profile is provided
26
26
 
27
- For profile mode, Codex has the Atoll skill immediately and terminal commands can use `atoll --profile agent-a ...`. For env-var mode, open a fresh shell or `source` your profile.
27
+ For profile mode, Codex has the Atoll skill immediately and terminal commands can use `atoll --profile agent-a ...`. For env-var mode, the installer writes `ATOLL_ENV_MODE=1` with the credential exports; open a fresh shell or `source` your profile.
28
28
 
29
29
  ## Using the integration
30
30
 
package/bin/install.mjs CHANGED
@@ -170,8 +170,25 @@ for (const file of ['api-endpoints.md', 'api-fields.md']) {
170
170
  }
171
171
  console.log(`Copied API references to ${refsDir}`)
172
172
 
173
+ const shell = process.env.SHELL || '/bin/bash'
174
+ const profilePath = shell.includes('zsh')
175
+ ? join(homedir(), '.zshrc')
176
+ : join(homedir(), '.bashrc')
177
+
173
178
  // 4. In profile mode, keep credentials scoped to the Atoll CLI profile.
174
179
  if (args.profile) {
180
+ if (existsSync(profilePath)) {
181
+ let profile = readFileSync(profilePath, 'utf-8')
182
+ profile = removeExport(profile, 'ATOLL_PROFILE')
183
+ profile = removeExport(profile, 'ATOLL_API_KEY')
184
+ profile = removeExport(profile, 'ATOLL_ORG_ID')
185
+ profile = removeExport(profile, 'ATOLL_PROJECT')
186
+ profile = removeExport(profile, 'ATOLL_TEAM')
187
+ profile = removeExport(profile, 'ATOLL_BASE_URL')
188
+ profile = removeExport(profile, 'ATOLL_ENV_MODE')
189
+ writeFileSync(profilePath, profile)
190
+ console.log(`Removed stale Atoll shell exports from ${profilePath}`)
191
+ }
175
192
  writeAtollProfile()
176
193
  console.log('No Atoll shell exports were written.')
177
194
  console.log(`Run profile-scoped commands with: atoll --profile ${args.profile} ...`)
@@ -180,11 +197,6 @@ if (args.profile) {
180
197
  }
181
198
 
182
199
  // 4. Set env vars in shell profile for env-var mode.
183
- const shell = process.env.SHELL || '/bin/bash'
184
- const profilePath = shell.includes('zsh')
185
- ? join(homedir(), '.zshrc')
186
- : join(homedir(), '.bashrc')
187
-
188
200
  function upsertExport(profile, name, value) {
189
201
  const line = `export ${name}="${value}"`
190
202
  const pattern = new RegExp(`^export ${name}=.*$`, 'm')
@@ -211,10 +223,11 @@ if (existsSync(profilePath)) {
211
223
  else profile = removeExport(profile, 'ATOLL_TEAM')
212
224
  if (args.baseUrl) profile = upsertExport(profile, 'ATOLL_BASE_URL', args.baseUrl)
213
225
  else profile = removeExport(profile, 'ATOLL_BASE_URL')
226
+ profile = upsertExport(profile, 'ATOLL_ENV_MODE', '1')
214
227
  writeFileSync(profilePath, profile)
215
228
 
216
229
  const configuredVars = []
217
- configuredVars.push('ATOLL_API_KEY', 'ATOLL_ORG_ID')
230
+ configuredVars.push('ATOLL_API_KEY', 'ATOLL_ORG_ID', 'ATOLL_ENV_MODE')
218
231
  if (args.project) configuredVars.push('ATOLL_PROJECT')
219
232
  if (args.team) configuredVars.push('ATOLL_TEAM')
220
233
  if (args.baseUrl) configuredVars.push('ATOLL_BASE_URL')
@@ -227,6 +240,7 @@ if (existsSync(profilePath)) {
227
240
  args.project ? `export ATOLL_PROJECT="${args.project}"` : null,
228
241
  args.team ? `export ATOLL_TEAM="${args.team}"` : null,
229
242
  args.baseUrl ? `export ATOLL_BASE_URL="${args.baseUrl}"` : null,
243
+ 'export ATOLL_ENV_MODE="1"',
230
244
  ].filter(Boolean)
231
245
  const envBlock = `\n${envLines.join('\n')}\n`
232
246
  writeFileSync(profilePath, envBlock)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atollhq/skill-codex",
3
- "version": "0.4.6",
3
+ "version": "0.4.8",
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
@@ -26,7 +26,7 @@ Agents are org members with the same API, same permissions, same ability to crea
26
26
 
27
27
  All requests require: `Authorization: Bearer sk_atoll_<key>`
28
28
 
29
- API keys are generated in **Settings > Members > Add Agent** (for agents) or **Settings > Members > Create API Key** (for integrations). Each key is scoped to one org. Store both values as env vars:
29
+ API keys are generated in **Agents** (for agents) or **Settings > Members > Create API Key** (for integrations). Each key is scoped to one org. Store both values as env vars:
30
30
 
31
31
  ```bash
32
32
  export ATOLL_API_KEY="sk_atoll_..."
@@ -94,6 +94,8 @@ atoll --profile agent-b issue list
94
94
 
95
95
  Profiles can store default org ID, project, team, and base URL values. For named profiles, always persist `--org-id` or pass `--org-id` per command. Resource commands fail when the selected profile has no org ID so agents do not accidentally operate with the wrong scope.
96
96
 
97
+ Env vars remain supported for CI, containers, and one-off runtime usage, but persistent developer/agent machines should prefer profiles. When a profile is selected, ambient `ATOLL_*` env vars do not silently override profile context; conflicting env values fail before network calls. Pass `--profile`, use repo-local `.atoll/context.json`, or opt into env mode with `--env-mode` / `ATOLL_ENV_MODE=1`.
98
+
97
99
  `atoll issue list` and `atoll issue create` apply the selected default team unless a command-level `--team` override is passed.
98
100
 
99
101
  Common commands:
@@ -173,6 +175,7 @@ CLI JSON conventions:
173
175
  - Use `--json` for machine-readable output.
174
176
  - List commands return `{ resource, items, total, limit, offset, nextOffset, truncated, hint }`.
175
177
  - Project-scoped `atoll issue list --json` includes `project_context`; `atoll issue get/view --json` includes `status_column` plus `project_context` when available.
178
+ - For initiative execution context via API, `GET /api/orgs/{id}/initiatives/{initiativeId}/issues?details=1` returns accessible task details from linked projects, direct issue links, and linked milestones.
176
179
  - Diagnostics and errors go to stderr.
177
180
  - Interactive CLI update notices also go to stderr and are suppressed for JSON/non-TTY/CI/completion flows.
178
181
  - `atoll agent-context` returns a versioned command/flag manifest, available profile context, and structured `cli.update_available` metadata.
@@ -315,6 +318,8 @@ The primary pattern for autonomous agents. Prefer `atoll heartbeat --json` when
315
318
  - **Project context**: relevant board columns, including optional descriptions that explain stage criteria for agents
316
319
  - **Signals** sorted by severity — the agent's prioritized to-do list
317
320
 
321
+ 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
+
318
323
  Signal types: `kpi_off_pace`, `kpi_stale`, `issue_stale`, `issue_blocked`, `milestone_overdue`, `initiative_stalled`, `webhook_failing`. Severity: `info`, `warning`, `critical`.
319
324
 
320
325
  Useful CLI forms:
@@ -364,6 +369,8 @@ atoll initiative kpi link "Content pipeline" paying_customers --impact "+30 cust
364
369
  atoll kpi snapshot add paying_customers --value 42 --initiative "Content pipeline" --note "End-of-week Stripe check"
365
370
  ```
366
371
 
372
+ Project-scoped agent profiles apply their default project to `atoll initiative list` and `atoll initiative create`. Use `--project <id-or-slug>` to override that project, or `--org-wide` to intentionally suppress the default project. API callers can pass `project_id` or `projectId` on create, and `?project_id=...` on list; guest/project-scoped callers must use a project they can access, and create requires edit/admin project access.
373
+
367
374
  Every KPI snapshot can be attributed to an initiative or issue, building a record of *what actually moved the numbers*.
368
375
 
369
376
  ### Audit and improve the strategy
@@ -392,6 +399,17 @@ This is the structural-health lens (is the strategy well-formed?), complementary
392
399
 
393
400
  `POST /api/orgs/{id}/issues/bulk` with `{ "issues": [{...}, ...] }` (max 50).
394
401
 
402
+ ### Outbound webhooks
403
+
404
+ `POST /api/webhooks` creates outbound webhooks. Receiver URLs must be HTTPS DNS hostnames; Atoll rejects IP literals, `localhost`, `.local` hosts, URL credentials, and fragments at creation. Delivery also resolves DNS and refuses private, loopback, link-local, documentation, multicast, and other non-public addresses; redirects are not followed.
405
+
406
+ Webhook creation returns a raw `whsec_...` secret once. Delivery requests include:
407
+
408
+ - `X-Atoll-Signature`: `sha256=` plus an HMAC-SHA256 over the raw body, keyed by the SHA-256 hex digest of the raw secret.
409
+ - `X-Atoll-Delivery-Id`: stable delivery id for receiver-side deduplication.
410
+
411
+ Delivery rows expose `delivery_id`, `status`, and `next_retry_at`. Network failures and 5xx responses retry quickly in-process, then persist `status: retry_pending` with `next_retry_at`; an internal drain retries due deliveries every 15 minutes.
412
+
395
413
  ### Billing and plan limits
396
414
 
397
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" }`.
@@ -413,7 +431,7 @@ Full endpoint tables and field schemas:
413
431
  | Tasks | POST `.../issues` | GET `.../issues` | PATCH `.../issues/{id}` | DELETE `.../issues/{id}` † |
414
432
  | Goals | POST `.../goals` | GET `.../goals` | PATCH `.../goals/{id}` | DELETE `.../goals/{id}` |
415
433
  | KPIs | POST `.../kpis` | GET `.../kpis` | PATCH `.../kpis/{id}` | DELETE `.../kpis/{id}` |
416
- | Initiatives | POST `.../initiatives` | GET `.../initiatives` | PATCH `.../initiatives/{id}` | DELETE `.../initiatives/{id}` |
434
+ | Initiatives | POST `.../initiatives` (`project_id`/`projectId` optional; required for guests) | GET `.../initiatives` (`project_id` optional; required for guests) | PATCH `.../initiatives/{id}` | DELETE `.../initiatives/{id}` |
417
435
  | Milestones | POST `.../milestones` | GET `.../milestones` | PATCH `.../milestones/{id}` | DELETE `.../milestones/{id}` |
418
436
  | Comments | POST `.../comments` | GET `.../comments` | PATCH `.../comments/{id}` | DELETE `.../comments/{id}` |
419
437
  | Subtasks | POST `.../subtasks` | GET `.../subtasks` | PATCH `.../subtasks/{id}` | DELETE `.../subtasks/{id}` |
@@ -114,7 +114,7 @@ Plan limits are enforced when creating projects, human members, agents/integrati
114
114
  | POST | `/api/orgs/{id}/issues/{issueId}/initiatives` | Link task to initiative (`{ initiative_id }`) |
115
115
  | DELETE | `/api/orgs/{id}/issues/{issueId}/initiatives/{initiativeId}` | Unlink task from initiative |
116
116
 
117
- Issue-centric initiative links follow task project permissions: reading links requires access to the task's project; linking and unlinking requires a non-guest member with non-view access.
117
+ Issue-centric initiative links follow task project permissions: reading links requires access to the task's project; linking and unlinking require edit/admin access to that project. Guest callers may link only to initiatives already linked to the same accessible project.
118
118
 
119
119
  **List filters** (query params):
120
120
  - `status` -- `backlog`, `todo`, `in_progress`, `done`, `cancelled`
@@ -221,8 +221,8 @@ Roles: `owner`, `admin`, `member`, `guest`.
221
221
 
222
222
  | Method | Endpoint | Description |
223
223
  |--------|----------|-------------|
224
- | GET | `/api/orgs/{id}/initiatives` | List (optional `?goal_id=...&status=...&owner_id=...`) |
225
- | POST | `/api/orgs/{id}/initiatives` | Create initiative |
224
+ | GET | `/api/orgs/{id}/initiatives` | List (optional `?goal_id=...&status=...&owner_id=...&project_id=...`; guests require `project_id`) |
225
+ | POST | `/api/orgs/{id}/initiatives` | Create initiative (`project_id`/`projectId` optional; guests require editable project access) |
226
226
  | GET | `/api/orgs/{id}/initiatives/{initiativeId}` | Get initiative |
227
227
  | PATCH | `/api/orgs/{id}/initiatives/{initiativeId}` | Update initiative |
228
228
  | DELETE | `/api/orgs/{id}/initiatives/{initiativeId}` | Delete initiative (admin/owner only) |
@@ -238,7 +238,7 @@ Create accepts `title` or legacy `name`, plus camelCase aliases `goalId`, `owner
238
238
  | GET | `.../initiatives/{id}/kpi-impacts` | List KPI impact links |
239
239
  | POST | `.../initiatives/{id}/kpi-impacts` | Add (`{ kpi_id, expected_impact? }`) |
240
240
  | DELETE | `.../initiatives/{id}/kpi-impacts/{impactId}` | Remove link |
241
- | GET | `.../initiatives/{id}/issues` | List linked issues |
241
+ | GET | `.../initiatives/{id}/issues` | List linked issue links; add `?details=1` for accessible task details from linked projects, direct issue links, and linked milestones |
242
242
  | POST | `.../initiatives/{id}/issues` | Link issue (`{ issue_id }`) |
243
243
  | DELETE | `.../initiatives/{id}/issues/{issueId}` | Unlink issue |
244
244
  | GET | `.../initiatives/{id}/milestones` | List linked milestones |
@@ -251,7 +251,7 @@ Create accepts `title` or legacy `name`, plus camelCase aliases `goalId`, `owner
251
251
  |--------|----------|-------------|
252
252
  | GET | `/api/orgs/{id}/strategy/audit` | Audit the strategy chain for structural gaps + health issues, each with a suggested fix |
253
253
 
254
- Returns findings only (not the full graph). Use it for a high-level review — orphaned initiatives/KPIs (no goal), goals with no KPI or no initiative, KPIs missing targets/stale/off-pace, initiatives missing impact/execution or stalled, blocked/overdue work — then remediate with the goal/KPI/initiative write endpoints above. Forbidden for guests. CLI: `atoll strategy audit [--severity critical|warning|info] [--json]`.
254
+ Returns findings only (not the full graph). Use it for a high-level review — orphaned initiatives/KPIs (no goal), goals with no KPI or no initiative, dangling initiative execution links, KPIs missing targets/stale/off-pace, initiatives missing impact/execution or stalled, blocked/overdue work — then remediate with the goal/KPI/initiative write endpoints above. Forbidden for guests. CLI: `atoll strategy audit [--severity critical|warning|info] [--json]`.
255
255
 
256
256
  ## Heartbeat
257
257
 
@@ -259,7 +259,7 @@ Returns findings only (not the full graph). Use it for a high-level review — o
259
259
  |--------|----------|-------------|
260
260
  | GET | `/api/orgs/{id}/heartbeat` | Get heartbeat context for the authenticated agent |
261
261
 
262
- Returns computed briefing with goal status, KPI pace/trend, initiative progress, assigned work, and signals.
262
+ 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.
263
263
 
264
264
  Signal types: `kpi_off_pace`, `kpi_stale`, `issue_stale`, `issue_blocked`, `milestone_overdue`, `initiative_stalled`, `webhook_failing`. Severity: `info`, `warning`, `critical`.
265
265
 
@@ -413,7 +413,7 @@ Trigger events: `issue.created`, `issue.status_changed`, `issue.assigned`, `issu
413
413
  | POST | `/api/webhooks/{id}/redeliver/{deliveryId}` | Redeliver a past payload |
414
414
  | POST | `/api/webhooks/{id}/test` | Send ping test event |
415
415
 
416
- URL must be HTTPS. Returns webhook record plus `secret` for HMAC verification.
416
+ URL must be an HTTPS DNS hostname. IP literals, `localhost`, and `.local` hosts are rejected at creation; delivery refuses non-public DNS results and does not follow redirects. Returns webhook record plus `secret` for HMAC verification. Store the secret immediately; it is shown only once. Delivery requests include `X-Atoll-Signature: sha256=<hmac>`, where the HMAC-SHA256 key is the SHA-256 hex digest of the webhook secret and the message is the exact raw request body. Delivery requests also include `X-Atoll-Delivery-Id` so receivers can dedupe retries. Atoll retries network failures and 5xx responses after 5s and 30s, then records `status: retry_pending` with `next_retry_at`; an internal cron drains due retries every 15 minutes.
417
417
 
418
418
  ## Notifications
419
419
 
@@ -428,13 +428,16 @@ URL must be HTTPS. Returns webhook record plus `secret` for HMAC verification.
428
428
  | Method | Endpoint | Description |
429
429
  |--------|----------|-------------|
430
430
  | GET | `/api/orgs/{id}/agents` | List agents (owner/admin) |
431
- | POST | `/api/orgs/{id}/agents` | Create agent (`{ name, role?, setupScoped? }`) |
432
- | DELETE | `/api/orgs/{id}/agents/{agentId}` | Revoke agent |
433
- | GET | `/api/orgs/{id}/agents/{agentId}/keys` | List API keys |
434
- | POST | `/api/orgs/{id}/agents/{agentId}/keys` | Generate new key |
435
- | DELETE | `/api/orgs/{id}/agents/{agentId}/keys/{keyId}` | Revoke key |
436
- | POST | `/api/orgs/{id}/agents/{agentId}/rotate` | Rotate all keys |
437
- | POST | `/api/orgs/{id}/agents/{agentId}/install-snippets` | Get install snippets (`{ key, profileName?, projectId?, teamId?, baseUrl? }`) |
431
+ | GET | `/api/orgs/{id}/agents/manageable` | List agents the current human can manage |
432
+ | POST | `/api/orgs/{id}/agents` | Create org, project-scoped, or personal agent |
433
+ | DELETE | `/api/orgs/{id}/agents/{agentId}` | Revoke manageable agent |
434
+ | PATCH | `/api/orgs/{id}/agents/{agentId}/projects` | Replace project access for a manageable non-personal agent |
435
+ | POST | `/api/orgs/{id}/projects/{projectId}/agents` | Grant selected manageable agents access to a project |
436
+ | GET | `/api/orgs/{id}/agents/{agentId}/keys` | List API keys for a manageable agent |
437
+ | POST | `/api/orgs/{id}/agents/{agentId}/keys` | Generate new key for a manageable agent |
438
+ | DELETE | `/api/orgs/{id}/agents/{agentId}/keys/{keyId}` | Revoke key for a manageable agent |
439
+ | POST | `/api/orgs/{id}/agents/{agentId}/rotate` | Rotate all keys for a manageable agent |
440
+ | POST | `/api/orgs/{id}/agents/{agentId}/install-snippets` | Get install snippets for a manageable agent (`{ key, profileName?, projectId?, teamId?, baseUrl? }`) |
438
441
 
439
442
  Install snippets returns config for `claude-code`, `codex`, `gemini`, `openclaw` (agent prompt), `openclaw-manual`, `hermes` (agent prompt), and `hermes-manual`. The server resolves the org slug and validates optional project/team IDs before generating snippets.
440
443
 
@@ -174,10 +174,13 @@ V1 syncs are `GET` only, `https` only, JSON only, exact-host allowlisted, no red
174
174
  "goal_id": "goal-uuid",
175
175
  "owner_id": "member-uuid",
176
176
  "status": "active",
177
- "target_date": "2026-05-15"
177
+ "target_date": "2026-05-15",
178
+ "project_id": "project-uuid"
178
179
  }
179
180
  ```
180
181
 
182
+ Create accepts `projectId` as a camelCase alias for `project_id`. Guest/project-scoped callers must pass a project they can edit when creating initiatives.
183
+
181
184
  For portfolio-style initiatives (grouping projects):
182
185
  ```json
183
186
  {
@@ -276,7 +279,7 @@ Add/remove projects with `{ "project_id": "uuid" }`.
276
279
  }
277
280
  ```
278
281
 
279
- URL must be HTTPS. Response includes `secret` for HMAC signature verification.
282
+ URL must be an HTTPS DNS hostname. IP literals, `localhost`, and `.local` hosts are rejected at creation; delivery refuses non-public DNS results and does not follow redirects. Response includes `secret` for HMAC signature verification. Store it immediately; it is shown only once. Delivery requests include `X-Atoll-Signature: sha256=<hmac>`, where the HMAC-SHA256 key is the SHA-256 hex digest of the webhook secret and the message is the exact raw request body. Delivery requests also include `X-Atoll-Delivery-Id` for receiver-side deduplication. Delivery history includes retry `status` and `next_retry_at`.
280
283
 
281
284
  ## Setup Proposal Fields
282
285
 
@@ -345,6 +348,8 @@ Proposal JSON currently supports at most one item in each collection: `projects`
345
348
  }
346
349
  ```
347
350
 
351
+ 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.
352
+
348
353
  ## Strategy Audit Response
349
354
 
350
355
  `GET /api/orgs/{id}/strategy/audit` returns findings (sorted critical → warning → info), each with a concrete `suggested_fix`, plus summary counts.
@@ -368,7 +373,7 @@ Proposal JSON currently supports at most one item in each collection: `projects`
368
373
 
369
374
  Each finding carries whichever entity ids apply: `goal_id`, `kpi_id`, `initiative_id`, `issue_id`, `milestone_id`, `project_id`. Finding `type` values:
370
375
 
371
- - Structural: `initiative_orphaned`, `kpi_orphaned`, `goal_missing_kpi`, `goal_missing_initiative`
376
+ - Structural: `initiative_orphaned`, `kpi_orphaned`, `goal_missing_kpi`, `goal_missing_initiative`, `dangling_initiative_project`, `dangling_initiative_issue`, `dangling_initiative_milestone`
372
377
  - KPI health: `kpi_unrecorded`, `kpi_missing_target`, `kpi_stale`, `kpi_off_pace`
373
378
  - Initiative health: `initiative_missing_impact`, `initiative_missing_execution`, `initiative_stalled`
374
379
  - Execution: `issue_blocked`, `issue_overdue`, `milestone_overdue`