@atollhq/skill-codex 0.4.30 → 0.4.31

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.30",
3
+ "version": "0.4.31",
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
@@ -34,6 +34,8 @@ Read only the references required for the current task:
34
34
  [execution-and-attention.md](references/execution-and-attention.md)
35
35
  - Remote MCP setup, AI-assisted setup, KPI HTTP sync, or advanced REST access:
36
36
  [integrations-and-api.md](references/integrations-and-api.md)
37
+ - GitHub pull-request delivery context, required checks, and exact-head evidence:
38
+ [api-fields.md](references/api-fields.md#external-operational-delivery-context)
37
39
  - Cross-resource authorization, privacy, automation, attachment, feedback, and
38
40
  other platform-specific rules: [platform-rules.md](references/platform-rules.md)
39
41
  - Exact endpoint inventory: [api-endpoints.md](references/api-endpoints.md)
@@ -41,7 +43,8 @@ Read only the references required for the current task:
41
43
  [api-fields.md](references/api-fields.md)
42
44
 
43
45
  For automation rule V1 actions (including create issue and send webhook), explicit project or
44
- organization scope, CI create-or-webhook rules, event conditions, validation, safe
46
+ organization scope, CI create-or-webhook rules, scheduled `schedule.issue_time`
47
+ rules, event conditions, validation, safe
45
48
  disabling, repair, and example-only CI dry runs, read [Automation Rule Fields](references/api-fields.md#automation-rule-fields).
46
49
  Use `atoll automation` for rule management, previews, and run history; see
47
50
  [CLI operations](references/cli-operations.md#automation-rules).
@@ -55,6 +58,16 @@ scope. An invalid rule executes no actions. Repair an invalid rule with
55
58
  separate `disable`, `update` while it is disabled, `test`, and `enable`
56
59
  operations. Enable only after the latest saved revision passes the dry run.
57
60
 
61
+ For recurring issues, completion remains the default materialization mode.
62
+ Scheduled recurrence uses the existing issue create/update REST and CLI inputs
63
+ with a local time and an IANA timezone. Its interval must be at most `10000`;
64
+ completion-mode roots can retain larger positive intervals. See
65
+ [Task Fields](references/api-fields.md#task-fields) and
66
+ [CLI operations](references/cli-operations.md). The recurrence root owns the
67
+ schedule. Its occurrences can remain open without delaying later occurrences.
68
+ Use only fields exposed by the connected tool: public MCP recurrence inputs
69
+ remain unchanged.
70
+
58
71
  Do not load every reference by default. Start with this entrypoint and load a
59
72
  topic reference only when the requested operation needs it.
60
73
 
@@ -206,7 +206,7 @@ offset }` and CLI-compatible REST `{ resource: "issues", items, ... }` upstream
206
206
  bodies, projects only declared public issue fields, preserves nullable
207
207
  `identifier` and `projectSlug`, and does not expose the CLI-derived `url` field.
208
208
 
209
- **GET task detail** returns enriched data: `milestone`, `creator`, `assignee`, `assignees`, `sub_tasks`, `issue_labels`, and `isBlocked`. Recurring tasks also return normalized `recurrence_days` and `recurrence_schedule`. Create, update, and bulk-create accept `recurrenceDays` only with `recurrenceType: "weekly"`; values must be unique weekdays from `mon` through `sun`.
209
+ **GET task detail** returns enriched data: `milestone`, `creator`, `assignee`, `assignees`, `sub_tasks`, `issue_labels`, and `isBlocked`. Recurring tasks also return normalized `recurrence_days` and `recurrence_schedule`. Create, update, and bulk-create accept `recurrenceDays` only with `recurrenceType: "weekly"` and effective `recurrenceMaterializationMode: "schedule"`; values must be unique weekdays from `mon` through `sun`. Set `recurrenceMaterializationMode: "schedule"` with `recurrenceTime` (`HH:MM`) and an IANA `recurrenceTimezone` to materialize the next task from the maintenance sweep while the current task remains open; scheduled intervals must be at most `10000`, while the default `completion` mode can retain larger positive intervals. `recurrence_next_run_at` is internal and omitted from public responses.
210
210
 
211
211
  ## Dependencies
212
212
 
@@ -655,11 +655,13 @@ requests also sweep a small due batch. Uploads over 2MB return `413`.
655
655
  | GET | `/api/orgs/{id}/issues/{issueId}/pr-links` | List linked pull requests |
656
656
  | POST | `/api/orgs/{id}/issues/{issueId}/pr-links` | Attach a GitHub PR URL (`{ url }`) |
657
657
 
658
- Attach PRs manually with a canonical GitHub pull request URL such as `https://github.com/owner/repo/pull/123`; malformed or non-PR URLs return `400`. On attach, Atoll refreshes GitHub metadata when available so title/status/head SHA reflect the PR instead of only the submitted URL. PR links can also be created or refreshed automatically via the GitHub webhook integration.
658
+ Attach PRs manually with a canonical GitHub pull request URL such as `https://github.com/owner/repo/pull/123`; malformed or non-PR URLs return `400`. On attach, Atoll refreshes GitHub metadata when available so title/status/head SHA reflect the PR instead of only the submitted URL. The compatibility link write succeeds independently of optional immutable identity enrichment; if that enrichment fails, POST still returns `201` with the committed link and nullable identity fields for later reconciliation. PR links can also be created or refreshed automatically via the GitHub webhook integration.
659
659
 
660
- GET returns `id`, `pr_number`, `github_repo`, nullable
660
+ GET returns `id`, `pr_number`, nullable `pr_id`, `github_repo`, nullable
661
661
  `github_repository_id`, nullable `external_reference_id`, `pr_url`, `pr_title`,
662
- `pr_status`, nullable `head_sha`, and `updated_at` for each link.
662
+ `pr_status`, nullable `head_sha`, nullable `base_ref`, nullable `base_sha`, and
663
+ `updated_at` for each link. The base and head values are the exact PR identity
664
+ tuple used by delivery evidence.
663
665
 
664
666
  For project-bound issues, listing requires project access and attaching requires
665
667
  `edit` or `admin` access. Eligible non-guests may list and attach links for
@@ -680,20 +682,38 @@ child reads or writes and occurs before URL parsing or GitHub metadata lookup.
680
682
  | GET | `/api/orgs/{id}/projects/{projectId}/external-references/{referenceId}` | Inspect a linked reference |
681
683
  | DELETE | `/api/orgs/{id}/projects/{projectId}/external-references/{referenceId}` | Unlink a reference |
682
684
 
683
- External Reference POST requests accept `{ "url": "https://github.com/owner/repo/pull/123" }`. They require an authorized GitHub connection and store a reference only when the live response proves numeric immutable repository and pull-request IDs. Missing proof returns `422` with `code: "github_identity_unavailable"`. URLs and caller owner/repo fields are not identity or authorization inputs. Manual PR-link operations remain available without an External Reference; verified delivery projection creates and binds the immutable PR reference. CLI/MCP tools are deferred to a later slice.
685
+ External Reference POST requests accept `{ "url": "https://github.com/owner/repo/pull/123" }`. They require an authorized GitHub connection and store a reference only when the live response proves numeric immutable repository and pull-request IDs. Missing proof returns `422` with `code: "github_identity_unavailable"`. URLs and caller owner/repo fields are not identity or authorization inputs. Manual PR-link operations remain available without an External Reference; verified delivery projection creates and binds the immutable PR reference.
684
686
 
685
687
  The external-operational-signals GET returns `{ deliveryContext }` for the
686
688
  selected current PR or `null` when there is no PR link. Selection prefers an
687
689
  open link, then the latest `updated_at`, then the highest PR number. It contains stable
688
- repository identity, exact head SHA, current PR/review/configured-workflow
689
- state, bounded source and provider-event provenance, freshness, a safe strongest
690
- blocker, and `partial`. Older-head signals are historical. Configured workflows
691
- are not GitHub branch-protection required checks and report `required: false`.
692
- Missing current-head review or configured-workflow evidence appears as
693
- `pending` with null provenance and does not by itself set `partial`. Disabled
694
- verification stops new projections. Workflow conclusions map `success` or
695
- `neutral` to `passed`; `cancelled`, `stale`, or `skipped` to `cancelled`; and
690
+ repository identity, exact head SHA, current PR/review/required-check/configured-
691
+ workflow state, bounded source and provider-event provenance, freshness, a safe
692
+ strongest blocker, and `partial`. Older-head signals are historical. Configured
693
+ workflows are not GitHub branch-protection required checks and report
694
+ `required: false`. Missing current-head review or configured-workflow evidence
695
+ appears as `pending` with null provenance and does not by itself set `partial`.
696
+ Disabled verification stops new projections. Workflow conclusions map `success`
697
+ or `neutral` to `passed`; `cancelled`, `stale`, or `skipped` to `cancelled`; and
696
698
  other supported terminal conclusions to `failed`.
699
+
700
+ `required_checks` is the actual read-only GitHub required-check projection. It
701
+ unions active ruleset requirements and classic branch-protection requirements
702
+ for the PR base branch by `(context, integration_id)`, with
703
+ `policy_sources: ["classic"]`, `["ruleset"]`, or both. Results are read from
704
+ check-runs and legacy commit statuses for the exact 40-character head SHA.
705
+ App-bound requirements match the check-run app ID; any-source requirements use
706
+ the latest result from each result type, and both must pass when both result
707
+ types share a required context. Collection `state` is `disabled`, `complete`,
708
+ `partial`, or `unavailable`; aggregate is `none`, `pending`, `passed`,
709
+ `failed`, `cancelled`, or `unknown`. The list is capped at 200 identities.
710
+ With the read flag off, collection state is `disabled` with aggregate `none`
711
+ and does not set context `partial`. When enabled, partial or unavailable
712
+ collection and stale, ambiguous, or missing evidence remain `unknown` and set
713
+ `partial`. The server-only `ATOLL_GITHUB_REQUIRED_CHECKS_READ_ENABLED=1` flag
714
+ enables the provider GET collection; it is disabled by default. The collector does not
715
+ change GitHub hooks or other provider state and does not prove merge,
716
+ deployment, production testing, or human acceptance.
697
717
  The selected PR-link state is authoritative. If a same-head PR observation
698
718
  disagrees, Atoll clears its observation/provider provenance, uses the link URL
699
719
  as `source_url`, excludes it from freshness, and sets `partial`.
@@ -702,7 +722,9 @@ comments, and removes dismissed opinions. Change requests win; `approved`
702
722
  means at least one effective approval and no effective change request. It does
703
723
  not prove required-review counts or branch protection.
704
724
  This read-only namespace is separate from heartbeat `signals[]` and does not
705
- dispatch agents or change tasks.
725
+ dispatch agents or change tasks. Use `atoll issue delivery-context <identifier>`
726
+ to read the same context from the private CLI; `--json` preserves the REST
727
+ envelope.
706
728
 
707
729
  ## Project Status Updates
708
730
 
@@ -781,7 +803,15 @@ require a canonical `event`; snapshots cannot establish transitions. See
781
803
  [Automation Rule Fields](api-fields.md#automation-rule-fields) for the grammar
782
804
  and legacy normalization. No public MCP tool is added.
783
805
 
784
- Trigger events: `issue.created`, `issue.status_changed`, `issue.assigned`, `issue.priority_changed`, `pr.merged`, `ci.run.completed`.
806
+ Scheduled dry runs use an `issue_id` or issue sample with the selected time
807
+ fields, return `scheduled_for`, `due`, and `conditions_matched`, and reject an
808
+ event preview. They remain side-effect free.
809
+
810
+ Trigger events: `issue.created`, `issue.status_changed`, `issue.assigned`, `issue.priority_changed`, `pr.merged`, `ci.run.completed`, `schedule.issue_time`.
811
+ The `schedule.issue_time` trigger requires `schedule_config` with an
812
+ `updated_at`, `status_changed_at`, or `due_date` anchor and an integer
813
+ `offset_minutes`; the first two anchors require a non-negative offset, while
814
+ due-date offsets may be signed. See [Automation Rule Fields](api-fields.md#automation-rule-fields).
785
815
  Create and update requests reject unsupported action types or malformed action
786
816
  values before persistence. Activity returns safe durable run/action history;
787
817
  non-matches, dry runs, and rules without executable actions create no history,
@@ -191,6 +191,9 @@ return `413`.
191
191
  "recurrenceType": "weekly",
192
192
  "recurrenceInterval": 1,
193
193
  "recurrenceDays": ["mon", "wed", "fri"],
194
+ "recurrenceMaterializationMode": "schedule",
195
+ "recurrenceTime": "09:00",
196
+ "recurrenceTimezone": "Europe/Stockholm",
194
197
  "labelIds": ["label-uuid-1", "label-uuid-2"]
195
198
  }
196
199
  ```
@@ -199,7 +202,7 @@ Most fields work on both POST (create) and PATCH (update). `labelIds` is accepte
199
202
 
200
203
  - **Multiple assignees**: Use `assigneeIds` (array). Legacy `assigneeId` (single) still works. Responses include `assignees` array with `id`, `display_name`, `type`, `avatar_url`.
201
204
  - **Start date**: Sets when work begins. Combined with `dueDate`, defines the Gantt time span.
202
- - **Recurring tasks**: Set `recurrenceType` + optional `recurrenceInterval` (default 1). Weekly series can set unique `recurrenceDays` values from `mon` through `sun`; Atoll sorts them into calendar order. When marked `done`, one next instance is auto-created in the same series. Responses include normalized `recurrence_days` and `recurrence_schedule: { type, interval, days }`.
205
+ - **Recurring tasks**: Set `recurrenceType` + optional `recurrenceInterval` (default 1). Completion mode is the default and creates the next occurrence when the current task is marked `done`. Set `recurrenceMaterializationMode` to `schedule` with `recurrenceTime` (`HH:MM`) and an IANA `recurrenceTimezone` to create occurrences from the maintenance sweep even while older tasks remain open; completing a scheduled occurrence does not create another task. Scheduled weekly series can set unique `recurrenceDays` values from `mon` through `sun`; Atoll sorts them into calendar order. Weekday arrays, including `[]`, require scheduled mode; `null` can clear selected weekdays in completion mode too. Scheduled intervals must be at most `10000`; completion mode retains its existing positive PostgreSQL integer range. Responses include normalized `recurrence_days` and `recurrence_schedule: { type, interval, days }`; the internal `recurrence_next_run_at` cursor is omitted. Appearance and due dates are separate, and the root due date is not advanced. Chains that have never entered scheduled mode retain and edit each occurrence's completion settings locally. Activating scheduled mode through a child adopts that child's cadence on the authorized root unless overridden. Once a chain has entered scheduled mode, the root owns recurrence settings even after a later switch back to completion; authorized list, detail, and update responses use those settings while preserving each child's identity. In those chains, send child-local task edits separately from root recurrence edits. Root deletion preserves completion-mode child recurrence, while scheduled-mode children become ordinary tasks. Do not PATCH `recurrenceParentId`.
203
206
  - **Archived tasks**: Have `archived_at` timestamp. Excluded by default; pass `includeArchived=true`.
204
207
  - **GET detail** returns enriched data: `milestone`, `creator`, `assignee`, `assignees`, `sub_tasks`, `issue_labels`, `isBlocked`.
205
208
 
@@ -493,6 +496,39 @@ multiple exact-name milestones already exist, upsert returns a structured
493
496
  }
494
497
  ```
495
498
 
499
+ Time-based rules use the same definition with `trigger_event:
500
+ "schedule.issue_time"` and a required `schedule_config`:
501
+
502
+ ```json
503
+ {
504
+ "trigger_event": "schedule.issue_time",
505
+ "schedule_config": {
506
+ "anchor": "due_date",
507
+ "offset_minutes": -60
508
+ }
509
+ }
510
+ ```
511
+
512
+ `anchor` is `updated_at`, `status_changed_at`, or `due_date`. An `updated_at`
513
+ rule represents inactivity; a `status_changed_at` rule represents time in the
514
+ current status; and a `due_date` rule represents deadline timing. Offsets for
515
+ `updated_at` and `status_changed_at` must be non-negative. A `due_date` offset
516
+ may be negative (before due), zero (at due), or positive (after due). Date-only
517
+ due dates are evaluated at midnight UTC. Scheduled rules reject change
518
+ conditions; combine a status field condition with `status_changed_at` when the
519
+ rule targets a specific status. Event-triggered rules must omit or clear
520
+ `schedule_config`.
521
+
522
+ Atoll evaluates scheduled rules from the existing authenticated maintenance
523
+ sweep every 15 minutes in bounded batches with a durable rotating rule cursor.
524
+ Busy workspaces can take multiple sweeps. It catches up occurrences whose time has
525
+ passed, excludes archived issues, and deduplicates each `(rule, issue,
526
+ scheduled_for)` occurrence. A condition mismatch is terminal for that
527
+ occurrence and is recorded as skipped. Scheduled execution reuses the existing
528
+ condition evaluator, action path, and `automation.executed` Activity history;
529
+ it does not add cron expressions, recurrence rules, calendars, or a second rule
530
+ store.
531
+
496
532
  Supported action values are: `set_status` (canonical project status key),
497
533
  `set_assignee` (replace the full assignee set with one member UUID, or `null` to
498
534
  clear it), `add_assignee` (add a member UUID without removing others), `unassign`
@@ -543,6 +579,12 @@ Dry runs create no issue and fail clearly when required content fields are missi
543
579
  Custom repository or branch conditions can fail to match this example; a preview
544
580
  does not verify a live run.
545
581
 
582
+ **Scheduled dry-run test:** Send `{ "issue_id": "issue-uuid" }` for a real
583
+ issue, or `{ "issue": { "updated_at": "2026-01-01T00:00:00Z", "status_changed_at": "2026-01-01T00:00:00Z", "due_date": "2026-01-03" } }`
584
+ for a sample. The existing test endpoint returns `scheduled_for`, `due`, and
585
+ `conditions_matched`, plus `matched` and `actions_that_would_run`. A scheduled
586
+ preview uses an issue, not a canonical event, and remains side-effect free.
587
+
546
588
  **Issue dry-run test**: Send `{ "issue_id": "uuid" }` or `{ "issue": { "status": "todo", "priority": 2 } }`. Returns `{ matched, actions_that_would_run }`.
547
589
 
548
590
  **Rule definition V1:** `schema_version` defaults to `1`. Conditions are ANDed;
@@ -1025,7 +1067,10 @@ metadata are never returned by the public API.
1025
1067
  | Comment create response | `outcome.mentions.transport` | Asynchronous Google Chat dispatch state; `dispatch: "scheduled"` is not final delivery, `final` is null while any result is unknown, `mixed` means terminal recipient results differ, and `error` exposes safe lookup/scheduling failure details |
1026
1068
  | Comment create response | `outcome.mentions.skipped[]` | Mention targets that did not create notification rows; each entry includes `member_id` and `reason` |
1027
1069
  | Task | `recurrenceType` | `daily`, `weekly`, `biweekly`, `monthly`, `custom` |
1028
- | Weekly task | `recurrenceDays[]` | Unique `mon`, `tue`, `wed`, `thu`, `fri`, `sat`, `sun` values |
1070
+ | Scheduled task | `recurrenceMaterializationMode` | `completion` or `schedule` |
1071
+ | Scheduled task | `recurrenceTime` | Local `HH:MM` time used with `schedule` |
1072
+ | Scheduled task | `recurrenceTimezone` | IANA timezone used with `schedule` |
1073
+ | Scheduled weekly task | `recurrenceDays[]` | Unique `mon`, `tue`, `wed`, `thu`, `fri`, `sat`, `sun` values |
1029
1074
  | Goal | `status` | `active`, `achieved`, `missed`, `paused`, `cancelled` |
1030
1075
  | KPI | `unit` | `count`, `percentage`, `currency`, `duration`, `ratio`, `custom` |
1031
1076
  | KPI | `target_direction` | `increase`, `decrease`, `maintain` |
@@ -1038,7 +1083,7 @@ metadata are never returned by the public API.
1038
1083
  | Status update | `status` | `on_track`, `at_risk`, `off_track` |
1039
1084
  | Member | `role` | `owner`, `admin`, `member`, `guest` |
1040
1085
  | Project member | `accessLevel` | `view`, `edit`, `admin` |
1041
- | Automation | `trigger_event` | `issue.created`, `issue.status_changed`, `issue.assigned`, `issue.priority_changed`, `pr.merged`, `ci.run.completed` |
1086
+ | Automation | `trigger_event` | `issue.created`, `issue.status_changed`, `issue.assigned`, `issue.priority_changed`, `pr.merged`, `ci.run.completed`, `schedule.issue_time` |
1042
1087
  | 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` |
1043
1088
  | Heartbeat signal | `severity` | `info`, `warning`, `critical` |
1044
1089
  | Custom view | `display_mode` | `board`, `list` |
@@ -1113,9 +1158,10 @@ metadata-only Activity actions `external_reference.linked`,
1113
1158
  links, selection prefers an open PR, then the latest `updated_at`, then the
1114
1159
  highest PR number. Otherwise it
1115
1160
  contains `repository`, `pull_request`, nullable `review`, `workflows`,
1116
- `freshness`, nullable `strongest_blocker`, and `partial`. PR, review, and
1117
- workflow evidence includes nullable `observed_at`, `provider_updated_at`,
1118
- `provider_event_id`, and `source_url`. The PR includes the exact `head_sha`.
1161
+ `required_checks`, `freshness`, nullable `strongest_blocker`, and `partial`. PR,
1162
+ review, and workflow evidence includes nullable `observed_at`,
1163
+ `provider_updated_at`, `provider_event_id`, and `source_url`. The PR includes
1164
+ the exact `head_sha`.
1119
1165
  Review state is `pending`, `approved`, or `changes_requested`; workflow state is
1120
1166
  `pending`, `passed`, `failed`, or `cancelled`. Older-head evidence is not
1121
1167
  current. Workflow `required` is always `false` because configured workflow
@@ -1130,6 +1176,19 @@ The selected PR-link state is authoritative. If a same-head PR observation
1130
1176
  disagrees, its `observed_at`, `provider_updated_at`, and `provider_event_id` are
1131
1177
  null, `source_url` uses the link URL, the observation is excluded from
1132
1178
  `freshness`, and `partial` is true.
1179
+ `required_checks.state` is `disabled`, `complete`, `partial`, or `unavailable`;
1180
+ `required_checks.aggregate` is `none`, `pending`, `passed`, `failed`,
1181
+ `cancelled`, or `unknown`. Each item includes `context`, nullable
1182
+ `integration_id`, `policy_sources` (`classic`, `ruleset`, or both), normalized
1183
+ `state`, bounded nullable provider state/conclusion, a safe nullable GitHub
1184
+ `url`, and nullable `provider_updated_at`. The collection has at most 200
1185
+ items, plus nullable safe `error_code` and `observed_at`. The server-only
1186
+ `ATOLL_GITHUB_REQUIRED_CHECKS_READ_ENABLED=1` flag enables the read-only
1187
+ provider collection; disabled is the default. With reads disabled, state
1188
+ `disabled` and aggregate `none` do not set `partial`. When enabled, partial or
1189
+ unavailable collection, stale, ambiguous, or missing evidence remains `unknown`
1190
+ and sets `partial`.
1191
+
1133
1192
  Review aggregation keeps each reviewer's latest exact-head opinion, ignores
1134
1193
  comments, and removes dismissed opinions. Change requests win; `approved`
1135
1194
  means at least one effective approval and no effective change request. It does
@@ -58,6 +58,7 @@ atoll issue list --scope blocked --initiative initiative-uuid --order-by due_dat
58
58
  # View a task
59
59
  atoll issue get ATOLL-42
60
60
  atoll issue view ATOLL-42 # alias kept for humans
61
+ atoll issue delivery-context ATOLL-42
61
62
 
62
63
  # Discover compact issue Artifacts, then fetch one body explicitly
63
64
  atoll artifact list ATOLL-42
@@ -69,7 +70,7 @@ atoll artifact update <artifact-id> --issue ATOLL-42 --expected-revision-id <rev
69
70
  atoll issue create --title "Fix login bug" --status todo --priority 1
70
71
  atoll issue create --title "Plan rollout" --project project-slug --milestone "Launch"
71
72
  atoll issue create --title "Weekly status review" --due-date 2026-07-06 --recurrence weekly
72
- atoll issue create --title "MWF status review" --due-date 2026-07-06 --recurrence weekly --recurrence-days mon,wed,fri
73
+ atoll issue create --title "MWF status review" --due-date 2026-07-06 --recurrence weekly --recurrence-days mon,wed,fri --recurrence-mode schedule --recurrence-time 09:00 --recurrence-timezone Asia/Singapore
73
74
  atoll issue upsert --match-title --project <project-id> --title "Fix login bug" --status todo
74
75
  atoll issue bulk-create --file ./issues.json --continue-on-error
75
76
 
@@ -181,12 +182,12 @@ CLI JSON conventions:
181
182
  - Machine-readable JSON preserves API strings exactly; human terminal output removes ANSI/VT, control, and bidirectional formatting characters from API-supplied strings.
182
183
  - Interactive CLI update notices also go to stderr and are suppressed for JSON/non-TTY/CI/completion flows.
183
184
  - `atoll agent-context` returns a versioned command/flag manifest, available profile context, and structured `cli.update_available` metadata.
184
- - Weekly issue recurrence accepts unique selected weekdays with `--recurrence weekly --recurrence-days mon,wed,fri`. Read JSON exposes normalized `recurrence_days` and `recurrence_schedule`; unrelated updates preserve the schedule.
185
+ - Weekly issue recurrence accepts unique selected weekdays with `--recurrence weekly --recurrence-days mon,wed,fri --recurrence-mode schedule --recurrence-time 09:00 --recurrence-timezone Asia/Singapore`. Read JSON exposes normalized `recurrence_days` and `recurrence_schedule`; unrelated updates preserve the schedule. Scheduled recurrence intervals are limited to `10000`. Use `--recurrence-mode schedule` with `--recurrence-time HH:MM` and `--recurrence-timezone IANA/Zone` to create the next task from the maintenance sweep while the current task remains open; `completion` remains the default and can retain larger positive intervals.
185
186
  - `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.
186
187
  - Authorized humans can configure an agent's included heartbeat sections and generated-signal focus in the Atoll **Heartbeats** UI. The saved policy is applied by the API before CLI or MCP request-level narrowing; it never changes project access, and existing heartbeat commands require no new arguments.
187
188
  - GitHub `workflow_run` signals are accepted only when HMAC-signed and completed, then reread and matched exactly by repository, PR, workflow path, run attempt, and head SHA. Workflow verification is disabled by default and observe-only until an owner/admin enables it in **Settings > Integrations > GitHub**. `attention` mode can add one bounded `verification.completed` attention item through authorized REST or CLI heartbeat for exactly one eligible current agent assignee or, when there is no unambiguous assignee, an eligible configured delivery agent. The public MCP heartbeat excludes this private event type. Unresolved recipients and cancelled, obsolete, superseded, mismatched, or unreadable runs create no attention. Owners and admins can configure 1–10 workflow paths of at most 255 characters each; the bounded evidence list defaults to 25 items and accepts a maximum `limit` of 100. Signed pull-request writes and reconciliation bind PR links to the stable GitHub repository ID, so repository renames keep existing workflow evidence linked. Do not expect raw payloads, secrets, logs, or thread IDs in evidence; owner/admin reconciliation retries pending evidence after current GitHub and PR-link readback.
188
189
  - Release-added required GitHub hook events mark existing reconciled and already-pending connections pending. The bounded 15-minute service sweep verifies immutable repository identity and upgrades hooks automatically; transient failures remain pending for retry, and owners/admins can reconcile manually.
189
- - Issue delivery context selects an open PR first, then the latest updated link, then the highest PR number. `pending` review/workflow state with null provenance means no current-head observation and does not by itself set `partial`. Disabled GitHub verification stops new projections. Workflow conclusions map success/neutral to passed, cancelled/stale/skipped to cancelled, and other supported terminal conclusions to failed.
190
+ - Issue delivery context is read with `atoll issue delivery-context <identifier>`; `--json` preserves `{ deliveryContext }`, while TTY output includes the full head SHA, review, actual required checks, configured verification, freshness, blocker, and partial state. The endpoint selects an open PR first, then the latest updated link, then the highest PR number. Required checks union active rulesets and classic branch protection for the base branch and use exact-head check-run/status evidence. `pending` review/workflow state with null provenance means no current-head observation and does not by itself set `partial`. Required-check collection is disabled by default; with the reader disabled, state `disabled` and aggregate `none` do not set `partial`. The server-only `ATOLL_GITHUB_REQUIRED_CHECKS_READ_ENABLED=1` flag enables read-only provider GETs; when enabled, partial or unavailable collection or aggregate `unknown` sets `partial`. This result does not authorize merge, deployment, production testing, or human acceptance. Configured workflows report `required: false`.
190
191
  - Aggregate review state keeps each reviewer's latest exact-head opinion, ignores comments, and removes dismissed opinions. Change requests win. `approved` means at least one effective approval and no effective change request; it does not prove required-review counts or branch protection.
191
192
  - `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`.
192
193
 
@@ -216,6 +216,29 @@ Webhook creation returns a raw `whsec_...` secret once. Delivery requests includ
216
216
 
217
217
  Webhook administration is owner/admin only. Lists return an origin-only `destination_display`; paths, queries, and signing material are never returned. Payload schema version `2` is allowlisted and omits descriptions, comment bodies, and raw change values. Delivery rows expose safe `delivery_id`, `status`, `status_code`, `error_code`, and retry timing, but not payloads, receiver response bodies, or raw errors. 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.
218
218
 
219
+ ### GitHub delivery context
220
+
221
+ Use `atoll issue delivery-context <identifier>` or
222
+ `GET /api/orgs/{id}/issues/{issueId}/external-operational-signals` to inspect a
223
+ linked pull request's current delivery evidence. The response is authorized to
224
+ the issue and selects an open PR first, then the latest updated link, then the
225
+ highest PR number. All revision-sensitive evidence is bound to the exact
226
+ 40-character head SHA.
227
+
228
+ The `required_checks` projection unions active base-branch rulesets and classic
229
+ branch protection by check context and optional integration/app ID. It reads
230
+ check-runs and legacy commit statuses for that exact head. If both result types
231
+ share a required context, both must pass. Collection states are `disabled`,
232
+ `complete`, `partial`, and `unavailable`; an aggregate of `unknown` is
233
+ fail-closed when missing, stale, ambiguous, or inaccessible evidence could
234
+ change the result. With the reader disabled, state `disabled` and aggregate
235
+ `none` do not set context `partial`; when enabled, partial or unavailable
236
+ collection or aggregate `unknown` sets `partial`. The server-only
237
+ `ATOLL_GITHUB_REQUIRED_CHECKS_READ_ENABLED=1` flag enables provider GETs and is
238
+ off by default. This evidence does not grant merge, deployment, production
239
+ testing, or acceptance authority, and the endpoint does not change GitHub
240
+ state. Configured Atoll workflow paths remain `required: false`.
241
+
219
242
  ## Planning Artifacts
220
243
 
221
244
  Use the connected typed Artifact tools for PRDs and implementation plans. Read
@@ -123,11 +123,20 @@ resolvability. Reads require project visibility; writes require project
123
123
  For compact implementation evidence, the private REST endpoint
124
124
  `GET /api/orgs/{id}/issues/{issueId}/external-operational-signals` returns the
125
125
  selected PR, stable repository identity, exact current head SHA, current-head
126
- review and configured workflow states, bounded provenance, freshness, and a
127
- safe strongest blocker. Older-head evidence is historical. Configured
128
- workflows are not GitHub branch-protection required checks. This namespace is
129
- separate from heartbeat `signals[]` and never changes tasks or dispatches
130
- agents.
126
+ review, actual required checks, and configured workflow states, bounded
127
+ provenance, freshness, and a safe strongest blocker. Older-head evidence is
128
+ historical. Configured workflows are not GitHub branch-protection required
129
+ checks. Required checks union active base-branch rulesets and classic branch
130
+ protection, use the exact head SHA, and report `disabled`, `complete`,
131
+ `partial`, or `unavailable` collection states. Partial, unavailable, stale,
132
+ ambiguous, or missing evidence remains aggregate `unknown`. With provider reads
133
+ disabled, aggregate `none` does not set context `partial`; enabled partial or
134
+ unavailable collection and aggregate `unknown` set `partial`. Read-only
135
+ required-check provider collection is disabled by default and requires the
136
+ server-only
137
+ `ATOLL_GITHUB_REQUIRED_CHECKS_READ_ENABLED=1` flag. This namespace is separate
138
+ from heartbeat `signals[]`, never changes provider state, and never changes
139
+ tasks or dispatches agents.
131
140
  The selected PR-link state is authoritative. If a same-head PR observation
132
141
  disagrees, Atoll clears its observation/provider provenance, falls back to the
133
142
  link URL, excludes it from freshness, and sets `partial`.