@uchibeke/gallivant 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -16
- package/SECURITY.md +9 -0
- package/bin/gallivant.mjs +33 -10
- package/bin/promote-bitbucket.mjs +40 -0
- package/bin/task-pr.mjs +9 -0
- package/bin/task-review.mjs +15 -0
- package/docs/README.md +2 -0
- package/docs/architecture.md +11 -3
- package/docs/bitbucket-promotion.md +69 -0
- package/docs/bitbucket-review.md +330 -0
- package/docs/chains.md +30 -1
- package/docs/codex-cloud.md +7 -0
- package/docs/codex-review.md +50 -0
- package/docs/commands.md +65 -5
- package/docs/config.md +35 -10
- package/docs/first-party-review.md +266 -0
- package/docs/git-hosts.md +294 -0
- package/docs/guardrails.md +56 -0
- package/docs/install.md +18 -8
- package/docs/network-recovery.md +9 -0
- package/docs/openai-agents.md +2 -1
- package/docs/prd.md +23 -2
- package/docs/preparation.md +1 -1
- package/docs/release-qualification.md +1 -1
- package/docs/releasing.md +17 -2
- package/docs/task-delivery.md +4 -4
- package/docs/task-profiles.md +537 -0
- package/docs/tasks.md +59 -197
- package/lib/attribution.mjs +7 -3
- package/lib/block.mjs +10 -1
- package/lib/chains.mjs +101 -30
- package/lib/codex_cloud.mjs +2 -1
- package/lib/codex_cloud_input.mjs +15 -6
- package/lib/codex_cloud_result.mjs +1 -1
- package/lib/commands/doctor.mjs +22 -462
- package/lib/commands/init.mjs +72 -30
- package/lib/commands/register.mjs +25 -11
- package/lib/commands/resume.mjs +5 -1
- package/lib/commands/review.mjs +66 -0
- package/lib/commands/serve.mjs +8 -0
- package/lib/commands/start.mjs +30 -11
- package/lib/commands/status.mjs +18 -2
- package/lib/commands/task.mjs +9 -1
- package/lib/commands/up.mjs +19 -11
- package/lib/commands/why.mjs +7 -3
- package/lib/config.mjs +42 -9
- package/lib/context.mjs +23 -18
- package/lib/control.mjs +21 -6
- package/lib/credential.mjs +20 -14
- package/lib/deliverable.mjs +2 -0
- package/lib/events.mjs +96 -53
- package/lib/execution.mjs +48 -3
- package/lib/execution_preparation.mjs +16 -1
- package/lib/execution_result.mjs +26 -5
- package/lib/first_party_review.mjs +618 -0
- package/lib/gh.mjs +144 -56
- package/lib/git.mjs +133 -32
- package/lib/git_diff.mjs +121 -0
- package/lib/harness.mjs +14 -10
- package/lib/host_contract.mjs +71 -0
- package/lib/host_definitions.mjs +22 -0
- package/lib/hosts/bitbucket.mjs +553 -0
- package/lib/hosts/bitbucket_contract.mjs +57 -0
- package/lib/hosts/bitbucket_credential.mjs +62 -0
- package/lib/hosts/bitbucket_review.mjs +44 -0
- package/lib/hosts/bitbucket_review_producer.mjs +50 -0
- package/lib/hosts/github.mjs +57 -0
- package/lib/hosts/github_contract.mjs +27 -0
- package/lib/hosts/github_doctor.mjs +482 -0
- package/lib/hosts/github_review_summary.mjs +38 -0
- package/lib/hosts/transport_doctor.mjs +35 -0
- package/lib/hosts.mjs +130 -0
- package/lib/learning_qualification.mjs +1 -1
- package/lib/notify.mjs +1 -1
- package/lib/openai_agents_input.mjs +7 -2
- package/lib/openai_agents_sources.mjs +16 -8
- package/lib/plugin_package.mjs +13 -1
- package/lib/pr_operation.mjs +41 -0
- package/lib/prd.mjs +18 -3
- package/lib/preparation_codex.mjs +6 -1
- package/lib/probe.mjs +6 -4
- package/lib/process.mjs +24 -0
- package/lib/promotion.mjs +132 -0
- package/lib/promotion_git.mjs +63 -0
- package/lib/prompt.mjs +16 -13
- package/lib/provider_health.mjs +14 -3
- package/lib/repository.mjs +68 -0
- package/lib/repository_preflight.mjs +11 -0
- package/lib/review_evaluation.mjs +25 -0
- package/lib/review_evidence.mjs +500 -0
- package/lib/review_history.mjs +73 -0
- package/lib/review_image.mjs +145 -0
- package/lib/review_link.mjs +12 -0
- package/lib/review_policy.mjs +132 -0
- package/lib/review_policy_contract.mjs +18 -0
- package/lib/review_state.mjs +13 -0
- package/lib/review_visual.mjs +94 -0
- package/lib/runtime-environment.mjs +6 -0
- package/lib/runtime_node.mjs +3 -2
- package/lib/runtime_state.mjs +39 -5
- package/lib/sources/prd.mjs +6 -3
- package/lib/state.mjs +137 -24
- package/lib/task_completion.mjs +7 -3
- package/lib/task_contract.mjs +201 -27
- package/lib/task_delivery.mjs +9 -2
- package/lib/task_delivery_contract.mjs +13 -9
- package/lib/task_delivery_view.mjs +18 -2
- package/lib/task_environment.mjs +13 -1
- package/lib/task_limits.mjs +13 -0
- package/lib/task_model_config.mjs +99 -0
- package/lib/task_model_route.mjs +243 -0
- package/lib/task_prepare.mjs +21 -8
- package/lib/task_profile.mjs +1875 -0
- package/lib/task_repository_context.mjs +65 -0
- package/lib/tasks.mjs +252 -51
- package/lib/tick.mjs +353 -97
- package/lib/time.mjs +1 -0
- package/lib/tracker/pages.mjs +19 -5
- package/lib/tracker/review.mjs +21 -0
- package/lib/tracker_process.mjs +8 -1
- package/lib/verification_sandbox.mjs +2 -1
- package/lib/work_artifacts.mjs +79 -0
- package/npm-shrinkwrap.json +12 -3
- package/package.json +9 -3
- package/templates/plugin/task-delivery.SKILL.md +17 -10
- package/templates/plugin/task-intake-contract.json +18 -0
- package/templates/plugin/task-profile-requests.mjs +1448 -0
- package/templates/tracker/tracker.css +3 -0
- package/templates/tracker/tracker.js +38 -0
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
# Typed delivery profiles
|
|
2
|
+
|
|
3
|
+
New natural-language tasks take delivery permission from one typed profile
|
|
4
|
+
that the owner selects when the task is prepared. Request text, answers,
|
|
5
|
+
selected documents and model output can describe the implementation and can
|
|
6
|
+
raise clarification questions. None of them can add, widen or remove an
|
|
7
|
+
external action. This replaces the free-text publication grammar for new
|
|
8
|
+
tasks; saved tasks keep the contract they were created with (see
|
|
9
|
+
[historical tasks](#historical-tasks)).
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
gallivant task "Add CSV export for the widget table. Open one PR for review." \
|
|
13
|
+
--harness claude --delivery pull_request --completion-target delivery_ready --json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The profile is saved with the task as:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{"version":1,"action":"pull_request","target":{"kind":"github-pull-request","repository":"acme/widget","base":"main"},"completion":{"condition":"delivery_ready"}}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
| Field | Values | Meaning |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| `action` | `pull_request` | The only supported action: implement on a task branch and open exactly one pull request for human review. `merge` and `deploy` are recognised so a request for them fails closed with a remedy; they need an explicit supported control and authorization that this release does not have. |
|
|
25
|
+
| `target` | resolved repository and base | Bound from the checkout and the usual base precedence when the task is created. Never taken from text. |
|
|
26
|
+
| `completion.condition` | `delivery_ready`, `integrated` | The same milestone as `--completion-target`. `integrated` keeps watching until someone else merges; it grants no merge authority. |
|
|
27
|
+
|
|
28
|
+
Omitting `--delivery` selects `pull_request`. The profile is immutable for a
|
|
29
|
+
saved request identity; changed retry input returns `TASK_CONFLICT`. The
|
|
30
|
+
structured `prepare` operation accepts `delivery: { action, completion }` and
|
|
31
|
+
the MCP `task_prepare` schema carries the same field. Capability discovery lists
|
|
32
|
+
the supported actions, so clients render those instead of their own list.
|
|
33
|
+
|
|
34
|
+
## Clauses, mappings and the delivery screen
|
|
35
|
+
|
|
36
|
+
New tasks split request and answer text at sentence, semicolon and newline
|
|
37
|
+
boundaries outside paired quoted literals and code spans. Each material clause
|
|
38
|
+
has a stable identifier and its exact UTF-16 span in the immutable source text.
|
|
39
|
+
The task and review pin `fragmentVersion: 2`; saved tasks without that pin or
|
|
40
|
+
with version 1 retain their original line-based references, including later
|
|
41
|
+
answers. Unsupported versions remain inspectable and fail mutations closed with
|
|
42
|
+
a compatible-package or new-task recovery path. The planner must
|
|
43
|
+
map each fragment to generated criteria, to one explicit assumption listed in
|
|
44
|
+
the brief, or to a clarification question. Unmapped fragments trigger bounded
|
|
45
|
+
repair and can never validate or start.
|
|
46
|
+
|
|
47
|
+
When a clause asks for, forbids or conditions an external action, the planner
|
|
48
|
+
adds a literal reading as a typed `delivery` tag (`pull_request`, `merge`,
|
|
49
|
+
`deploy`, `release`, `publish`, `local_only`, `wait_for_approval`, or `restrict`
|
|
50
|
+
with the effects it forbids). The service compares that reading with the
|
|
51
|
+
profile:
|
|
52
|
+
|
|
53
|
+
- A covered reading (the profile already does exactly that, or the clause only
|
|
54
|
+
forbids effects the profile never performs) is recorded in the mapping. The
|
|
55
|
+
clause still keeps its implementation content in the criteria. A tag speaks
|
|
56
|
+
only for the terms it names, and only in the right sense: a requested action
|
|
57
|
+
speaks for terms outside a control word or under an affirmative one ("a
|
|
58
|
+
pull request is required"), a prohibition for terms under a negative one
|
|
59
|
+
("do not", "except", "is not required"); control words bind within a
|
|
60
|
+
statement, across additive conjunctions. Contrast words such as "but" and
|
|
61
|
+
"however" start a new control scope. Both senses are retained when an action
|
|
62
|
+
occurs more than once: "Do not deploy; deploy to production" cannot be covered
|
|
63
|
+
by a prohibition tag. So "do not open
|
|
64
|
+
a pull request" tagged as a `pull_request` action, "merge the PR" tagged with
|
|
65
|
+
a `merge` prohibition, an escalating term the tag leaves out ("open a PR and
|
|
66
|
+
deploy it") and an effect term it leaves out under a control word ("open a
|
|
67
|
+
PR; do not push to main") all keep the screen's own clarification.
|
|
68
|
+
- An uncovered reading becomes the deterministic question `q-delivery-<clause>`.
|
|
69
|
+
Preparation pauses with `needs-input`; no readiness decision or implementation
|
|
70
|
+
starts until the owner answers.
|
|
71
|
+
|
|
72
|
+
New delivery question IDs are at most 64 characters. Longer clause identifiers
|
|
73
|
+
use a stable portable digest suffix instead of embedding their full answer
|
|
74
|
+
ancestry. Exact source spans and saved question ownership retain that ancestry.
|
|
75
|
+
Saved IDs within the 128-character public answer limit remain unchanged. If an
|
|
76
|
+
older pending delivery question exceeds that limit, explicitly resume the task
|
|
77
|
+
at its current revision: intake creates a bounded replacement and a fresh draft
|
|
78
|
+
revision without inference or implementation, preserving the old history and
|
|
79
|
+
accepted answers. Answer the replacement ID from the resumed result; readiness
|
|
80
|
+
and execution authorization remain unset. Conflicting saved ownership refuses
|
|
81
|
+
recovery and requires inspection before retrying.
|
|
82
|
+
|
|
83
|
+
Explicit PR destinations are also compared with the selected repository and
|
|
84
|
+
case-sensitive base, even if the planner supplies only a `pull_request` tag.
|
|
85
|
+
Planner tags retain named destinations as `target: { repository, base }`, with
|
|
86
|
+
either field optional; malformed targets are rejected and mismatches clarify.
|
|
87
|
+
"Open a PR against staging" under a `main` profile, or a PR in another
|
|
88
|
+
repository, pauses with a question naming the selected target. Ambiguous
|
|
89
|
+
destinations require clarification. Text cannot change the saved target; the
|
|
90
|
+
owner must resolve the scope or prepare a new task with the intended selection.
|
|
91
|
+
Canonical `gh pr create` commands retain `--base`/`-B` and `--repo`/`-R`
|
|
92
|
+
arguments under the same comparison, including equals, attached short flags,
|
|
93
|
+
quoted values and repeated flags. Title/body values and later commands cannot
|
|
94
|
+
supply a target flag. Missing, dynamic or ambiguous target arguments clarify;
|
|
95
|
+
matching explicit targets retain the normal PR reading. These arguments never
|
|
96
|
+
select or expand the saved target.
|
|
97
|
+
Attached quoted title/body/description values (`titled`, `named`, `called`,
|
|
98
|
+
`with title`, `with body`) are consumed as data before checking later targets.
|
|
99
|
+
Only actual target spans are unmasked; title/body text cannot add delivery terms
|
|
100
|
+
or supply a destination. Incomplete or ambiguous descriptive values clarify.
|
|
101
|
+
Parsing still stops at independent actions instead of borrowing their targets.
|
|
102
|
+
Explicit `--head`/`-H` selectors also retain a target conflict, including fork
|
|
103
|
+
refs, attached/equal values, dynamic values and `HEAD`. The managed task branch
|
|
104
|
+
is allocated after approval, so preparation cannot prove an explicit head names
|
|
105
|
+
it. Omit the head override to keep managed task-branch delivery. Title/body data,
|
|
106
|
+
feature examples, terminators and independent later commands do not select a
|
|
107
|
+
head. No profile or planner field can grant a different head branch.
|
|
108
|
+
Quoted target values stay visible only when attached to a PR target qualifier,
|
|
109
|
+
including paired repository/base values and leading qualifiers. Matching quoted
|
|
110
|
+
values keep the ordinary PR reading; mismatches retain the exact named target.
|
|
111
|
+
Other quoted examples and unrelated prepositional phrases remain product text.
|
|
112
|
+
Draft and dry-run PR creation modes (`--draft`/`-d`, `--dry-run`) remain
|
|
113
|
+
`pull_request_mode` conflicts: this profile creates a regular review PR. Explicit false boolean flags, title/body argument values,
|
|
114
|
+
read-only help for registry commands, product features and literal examples
|
|
115
|
+
retain their own meaning. Natural-language requests to create a draft PR also
|
|
116
|
+
require clarification; no planner tag can select a different creation mode.
|
|
117
|
+
The profile opens exactly one PR. Requests for two or more PRs, separate PRs,
|
|
118
|
+
a PR per component, repeated PR creation commands or another PR retain a
|
|
119
|
+
`pull_request_count` conflict even if the planner supplies a `pull_request` tag.
|
|
120
|
+
Target qualifiers must be attached to the PR instruction, including leading
|
|
121
|
+
targets and adjacent repository/base pairs. Separate actions such as "run the
|
|
122
|
+
tests on Linux" or "document it in docs/README.md" do not select a PR target.
|
|
123
|
+
|
|
124
|
+
Independently of the planner, a deterministic screen looks for delivery
|
|
125
|
+
vocabulary in each clause (pull request, merge, deploy, release, publish, push,
|
|
126
|
+
commit, branch, approval, review, wait, local-only). Paired straight or curly
|
|
127
|
+
single/double quotes and code spans are masked as literal examples. Apostrophes
|
|
128
|
+
in contractions and possessives do not open quotes. Imperative command spans
|
|
129
|
+
such as ``Run `npm publish` `` remain visible, including linked command lists;
|
|
130
|
+
product wording such as ``Document how to run `npm publish` `` stays literal.
|
|
131
|
+
A span whose
|
|
132
|
+
statement carries a control phrase before or after it (`Please do not ever
|
|
133
|
+
"open a pull request"`, `"Open a pull request" is forbidden`) is read as
|
|
134
|
+
the control's target; a control word inside another example never counts. Restriction forms such
|
|
135
|
+
as "leave the changes uncommitted", "unstaged", "keep all edits in the working
|
|
136
|
+
tree" or "unpublished" count as local-only. Control words bind within a statement: sentence and clause
|
|
137
|
+
punctuation ends one, but additive conjunctions and an introductory colon after the
|
|
138
|
+
control ("Do not: open a pull request") do not.
|
|
139
|
+
|
|
140
|
+
Terminal directions such as "stop after committing the changes", "stop once
|
|
141
|
+
committed" and "once committed, stop" also count as local-only: they withhold
|
|
142
|
+
the push and PR required by the profile. They require clarification even when
|
|
143
|
+
the planner omits a tag. Feature infinitives and database transaction commits
|
|
144
|
+
retain their product interpretation.
|
|
145
|
+
|
|
146
|
+
Wrapped request and answer lines are screened in the complete source statements
|
|
147
|
+
that touch their immutable spans. Source IDs, text and offsets remain unchanged;
|
|
148
|
+
context never crosses between the original request and an answer or between
|
|
149
|
+
separate answers. Sentence punctuation, blank lines and list-item boundaries
|
|
150
|
+
separate controls; paired literal spans retain their context across wrapped
|
|
151
|
+
lines. Shared statement windows are cached within each source.
|
|
152
|
+
|
|
153
|
+
The screen grants nothing:
|
|
154
|
+
|
|
155
|
+
- Existing-PR branch updates (`gh pr update-branch`, including `--rebase`)
|
|
156
|
+
retain the lifecycle conflict, including repository selectors. They do not
|
|
157
|
+
authorize updating an unrelated PR head.
|
|
158
|
+
- Workflow dispatch, enable/disable and existing Actions run rerun/cancel/delete
|
|
159
|
+
are unsupported external mutations, including canonical CLI commands and
|
|
160
|
+
imperative workflow wording. Active/passive Actions-run mutation prose and
|
|
161
|
+
quoted run references follow the same rule. Read-only list/view/watch commands,
|
|
162
|
+
features and literal examples retain their implementation meaning. Command coverage follows
|
|
163
|
+
[workflow commands](https://cli.github.com/manual/gh_workflow) and
|
|
164
|
+
[run commands](https://cli.github.com/manual/gh_run).
|
|
165
|
+
- Issue creation, editing, commenting, closing and reopening are unsupported
|
|
166
|
+
external mutations, including passive instructions, quoted issue references,
|
|
167
|
+
GitHub issue URLs and canonical `gh issue` write commands. Related writes
|
|
168
|
+
(deleting, assigning, locking, pinning and transferring issues, or creating
|
|
169
|
+
linked development branches) follow the same rule. They require clarification
|
|
170
|
+
even with an omitted or `pull_request` planner tag; no new profile action or
|
|
171
|
+
prohibition tag is granted. Read-only issue commands, issue templates,
|
|
172
|
+
product features and literal examples retain their implementation meaning.
|
|
173
|
+
Command coverage follows the [GitHub CLI issue commands](https://cli.github.com/manual/gh_issue).
|
|
174
|
+
- Release actions retain their unsupported delivery effect; product nouns such
|
|
175
|
+
as release notes, versions and metadata do not request that effect. Actual
|
|
176
|
+
release/publish lifecycle instructions, release asset writes and canonical
|
|
177
|
+
`gh release` mutations still require clarification. The shared command reader
|
|
178
|
+
keeps read-only release commands, option values and templates as data.
|
|
179
|
+
Feature infinitives, local resource release, and release-named refs/flags
|
|
180
|
+
retain implementation scope; explicit release prohibitions remain traceable.
|
|
181
|
+
- GitHub Discussion creation, edits and comment/reply writes are unsupported
|
|
182
|
+
external content mutations. List/view, help and quoted content retain scope.
|
|
183
|
+
- Nested repository autolink create/new/delete commands retain a repository
|
|
184
|
+
mutation conflict; list/view and help remain read-only, including parent and
|
|
185
|
+
child option values.
|
|
186
|
+
- Repository delete, archive/unarchive, rename, settings, creation, fork and
|
|
187
|
+
sync commands are unsupported external mutations. The shared command reader
|
|
188
|
+
preserves read-only repository commands, help and option values; explicit
|
|
189
|
+
GitHub repository lifecycle prose requires clarification as well.
|
|
190
|
+
- GitHub account SSH/GPG key additions and deletions are unsupported external
|
|
191
|
+
effects. Canonical `gh ssh-key`/`gh gpg-key` writes and explicit account-key
|
|
192
|
+
mutations require clarification. Listings, help, title/type values, local key
|
|
193
|
+
generation and product features retain their implementation meaning.
|
|
194
|
+
- Codespace creation, deletion, stopping, rebuilding and editing are unsupported
|
|
195
|
+
external effects. Canonical `gh codespace`/`gh cs` writes and imperative
|
|
196
|
+
Codespace lifecycle prose require clarification under omitted or covered PR
|
|
197
|
+
tags. The shared command reader preserves option values, read-only
|
|
198
|
+
list/status/view/logs/help, features and literal examples. No Codespace
|
|
199
|
+
action or prohibition tag is granted.
|
|
200
|
+
- GitHub Project creation, editing, deletion, copying and closing/reopening,
|
|
201
|
+
field/item writes, repository/team linking and template marking are unsupported
|
|
202
|
+
external mutations. Canonical `gh project` writes and explicit GitHub Project
|
|
203
|
+
mutation prose require clarification with omitted or covered PR tags; no
|
|
204
|
+
project action/prohibition authority is granted. The shared command reader
|
|
205
|
+
keeps option values atomic and preserves list/view/field-list/item-list/help,
|
|
206
|
+
ordinary local project work, product features and literal examples.
|
|
207
|
+
- Gist creation, editing, deletion and file renaming are unsupported external
|
|
208
|
+
mutations, including `gh gist create`/`new`, `edit`, `delete` and `rename`.
|
|
209
|
+
Both secret and public gists write account-owned content and require
|
|
210
|
+
clarification with omitted or covered PR tags; no gist action/prohibition
|
|
211
|
+
authority is granted. The shared command reader preserves option values,
|
|
212
|
+
read-only list/view/help and local gist cloning. Product viewers, feature
|
|
213
|
+
requests and literal examples retain their ordinary meaning.
|
|
214
|
+
- Repository label creation, editing, deletion and cloning are unsupported
|
|
215
|
+
external mutations. Canonical `gh label` writes and explicit GitHub/repository
|
|
216
|
+
label instructions require clarification under omitted or covered PR tags.
|
|
217
|
+
The shared quote-aware command reader preserves repository selectors and
|
|
218
|
+
option values; list/help, product features and literal examples keep their
|
|
219
|
+
ordinary meaning. Cloning labels writes the destination repository too.
|
|
220
|
+
No label action or prohibition tag is granted.
|
|
221
|
+
- Package registry administration is also a publication restriction. Write
|
|
222
|
+
subcommands of `npm access` (set/grant/revoke and legacy access/MFA setters),
|
|
223
|
+
`npm owner` (add/remove), and `npm dist-tag` (add/remove) require clarification.
|
|
224
|
+
List/get forms and help remain read-only. The quote-aware command argument
|
|
225
|
+
reader keeps option values and later commands from supplying a write verb.
|
|
226
|
+
- Outbound messages (email, Slack, chat and webhook instructions) are unsupported
|
|
227
|
+
external communications. Mutating `curl` calls, including explicit methods,
|
|
228
|
+
data/form/JSON bodies and file uploads, require clarification. Read-only
|
|
229
|
+
GET/HEAD/OPTIONS/TRACE requests and GET query options retain their meaning;
|
|
230
|
+
explicit methods and `--next` transfer boundaries are respected. Configuration
|
|
231
|
+
files or unresolved methods cannot silently choose a write. Header/body option
|
|
232
|
+
values, read-only help, local logging, product features and literal examples
|
|
233
|
+
do not become separate communication instructions. These screens never send
|
|
234
|
+
a message or issue a network request. Authenticated `gh api` writes use the
|
|
235
|
+
same HTTP conflict: explicit mutating methods and implicit POST from
|
|
236
|
+
field/input flags cannot use PR authority. Explicit GET overrides retain query
|
|
237
|
+
semantics, including field values; method, header, payload and output option
|
|
238
|
+
values stay atomic. Unknown modes require clarification. See the
|
|
239
|
+
[GitHub CLI API reference](https://cli.github.com/manual/gh_api).
|
|
240
|
+
- Hosted registry names and host destinations use the same publication
|
|
241
|
+
restriction: GitHub Packages/GHCR, GitLab registries, cloud artifact registries
|
|
242
|
+
and explicit registry hosts, including schemes, ports and artifact paths.
|
|
243
|
+
Detection, escalation and registry-removal checks share one destination
|
|
244
|
+
vocabulary. Quoted destinations of mutation instructions remain visible;
|
|
245
|
+
read-only pulls/downloads, feature infinitives and literal examples retain
|
|
246
|
+
their implementation meaning. Host formats follow [GitHub Container registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry),
|
|
247
|
+
[Google Artifact Registry](https://docs.cloud.google.com/artifact-registry/docs/docker/names),
|
|
248
|
+
[Amazon ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html)
|
|
249
|
+
and [Azure Container Registry](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-get-started-portal).
|
|
250
|
+
- Removing, deprecating or yanking registry packages retains the existing
|
|
251
|
+
publication conflict. This includes npm unpublish/deprecate, Cargo/RubyGems
|
|
252
|
+
yank and prose such as "remove the package from npm". No registry mutation
|
|
253
|
+
is authorized by PR delivery. Local dependency removal, feature descriptions
|
|
254
|
+
and literal examples keep their implementation meaning. Command semantics
|
|
255
|
+
follow [npm unpublish](https://docs.npmjs.com/cli/v11/commands/npm-unpublish/),
|
|
256
|
+
[npm deprecate](https://docs.npmjs.com/cli/v11/commands/npm-deprecate/) and
|
|
257
|
+
[Cargo yank](https://doc.rust-lang.org/cargo/commands/cargo-yank.html).
|
|
258
|
+
- Conversational owner decisions such as "check with me", "ask me" and "get
|
|
259
|
+
my go-ahead" are approval gates, including quoted decision objects. A plain
|
|
260
|
+
"go ahead and open a PR" retains its affirmative reading. Confirmation
|
|
261
|
+
dialogs, product features and literal examples keep their product meaning.
|
|
262
|
+
- Object-storage uploads and remote copies using AWS S3 cp/sync or gsutil
|
|
263
|
+
cp/rsync require clarification, as do moves that delete a remote source.
|
|
264
|
+
Prose uploads to S3 and other named object stores use the same restriction.
|
|
265
|
+
Operand direction, quoted option values and separate command boundaries are
|
|
266
|
+
preserved; download-only transfers, listing and unambiguous simulations retain
|
|
267
|
+
their read-only reading. Dynamic operands or unresolved option arity cannot
|
|
268
|
+
prove a download or dry run. See [AWS S3 transfer commands](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html).
|
|
269
|
+
- Imperative infrastructure writes, including Terraform/OpenTofu apply/destroy,
|
|
270
|
+
Helm install/upgrade/rollback/uninstall, kubectl resource mutations and Pulumi
|
|
271
|
+
up/destroy/refresh/import/cancel, retain
|
|
272
|
+
the existing deployment conflict. Plan/template/get commands and unambiguous
|
|
273
|
+
simulation flags (including Pulumi refresh --preview-only) keep their read-only
|
|
274
|
+
reading. Pulumi preview/history/stack output do not request an update.
|
|
275
|
+
Simulation flags cannot be
|
|
276
|
+
borrowed from another command or override a later mutating mode; quoted or
|
|
277
|
+
ambiguous option values keep a clarification. See [Terraform CLI](https://developer.hashicorp.com/terraform/cli/commands),
|
|
278
|
+
[Helm upgrade](https://docs.helm.sh/docs/helm/helm_upgrade/) and
|
|
279
|
+
[kubectl apply](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_apply/)
|
|
280
|
+
and [Pulumi up](https://www.pulumi.com/docs/iac/cli/commands/pulumi_up/).
|
|
281
|
+
- Force-push requirements (`--force`, `--force-with-lease`, short `-f`,
|
|
282
|
+
and direct force-push wording) conflict with the fixed task-branch safety
|
|
283
|
+
rule, even when the destination is `HEAD`. Known push-option values and
|
|
284
|
+
literal/product examples stay data; a PR tag cannot cover a force mode.
|
|
285
|
+
- Pushing tags, Git notes, all/mirrored refs, deleting remote refs or naming
|
|
286
|
+
another destination ref is a `direct_push` conflict. A base named before
|
|
287
|
+
the remote ("push main to origin", "push the main branch to origin") has the
|
|
288
|
+
same restriction, including literal selected-base names and reversed named
|
|
289
|
+
branch wording. Descriptive task/feature branches retain their ordinary
|
|
290
|
+
reading. A task-branch push such
|
|
291
|
+
as `git push -u origin HEAD` keeps the profile's normal reading. Product
|
|
292
|
+
commands and literal examples retain their feature meaning.
|
|
293
|
+
- Closing, reopening, editing, locking or changing the state of an existing
|
|
294
|
+
PR is a `pull_request_lifecycle` conflict, including imperative CLI commands
|
|
295
|
+
and quoted PR objects. The profile creates one new review PR; a planner's
|
|
296
|
+
`pull_request` tag cannot cover an existing-PR mutation or grant it authority.
|
|
297
|
+
Prose reviews, comments, feedback and replies use the same conflict as their
|
|
298
|
+
CLI equivalents; asking to open a new PR "for review" stays creation scope.
|
|
299
|
+
- Escalating terms (merge, including landing a PR, patch or change; deploy
|
|
300
|
+
including shipping, rollout, go-live and
|
|
301
|
+
"to production" wording, release, wait, local-only, a write aimed
|
|
302
|
+
at the base branch or at skipping the pull request such as "push directly
|
|
303
|
+
to main", "push to <the selected base>" with the profile's actual base name
|
|
304
|
+
or any explicitly direct branch write such as "commit straight to staging",
|
|
305
|
+
publish whenever it appears as a bare verb such as "Publish this package to
|
|
306
|
+
npm", "and publish the package" or "could you publish it", or as a package
|
|
307
|
+
or build submission to a registry or store such as "submit the package to
|
|
308
|
+
npm", "upload the build to the App Store" or "run gem push", rather than as a
|
|
309
|
+
noun modifier such as "a publish button" or a feature infinitive such as
|
|
310
|
+
"a command to publish docs", and approval whenever the statement waits on
|
|
311
|
+
someone's decision such as "wait for my approval", "get sign-off", "once
|
|
312
|
+
approved", "get my consent" or "get my authorization" (also "authorisation"
|
|
313
|
+
and "permission"), rather than a product feature such as "an approval
|
|
314
|
+
workflow", "a consent banner", "authorization middleware", "the approval
|
|
315
|
+
status column" or "a button to approve comments") or a
|
|
316
|
+
control word such as "do not", "until", "unless", "out of scope",
|
|
317
|
+
"exclude", "except", "other than", "but not", "disallowed", "isn't
|
|
318
|
+
allowed", "not permitted", "stop before", "pause before" or an owner
|
|
319
|
+
reservation such
|
|
320
|
+
as "I will open the PR myself", "let me open the PR" or "leave the PR to me"
|
|
321
|
+
next to any delivery
|
|
322
|
+
term
|
|
323
|
+
raise the same `q-delivery-<clause>` question when the planner left the
|
|
324
|
+
clause untagged.
|
|
325
|
+
- Dots inside registry and repository names stay in the statement, so
|
|
326
|
+
"Upload the package to hex.pm" and "Submit the package to crates.io" keep
|
|
327
|
+
their publication meaning. Quoted examples and feature infinitives retain
|
|
328
|
+
their product interpretation.
|
|
329
|
+
- A review prohibited outright ("do not send this for review", "no code
|
|
330
|
+
review", "reviews are forbidden") conflicts with pull-request delivery, which
|
|
331
|
+
exists to request review, so it keeps its clarification whatever the planner
|
|
332
|
+
tags. A review named as a condition ("do not merge until reviewed") or as
|
|
333
|
+
optional ("a review is not required") does not.
|
|
334
|
+
- Ordinary vocabulary ("Add a PR status badge") becomes a visible assumption in
|
|
335
|
+
the brief and in the review: the clause is treated as product behaviour and
|
|
336
|
+
the profile is unchanged.
|
|
337
|
+
|
|
338
|
+
The owner's reply to a delivery question is screened like any other clause,
|
|
339
|
+
and it closes the original conflict only when every fragment of the reply
|
|
340
|
+
carries a typed reading the profile covers; an anaphoric reply such as "do it
|
|
341
|
+
anyway" gets its own question instead.
|
|
342
|
+
That reading must be grounded in the reply's own explicit action or prohibited
|
|
343
|
+
effects. Empty `restrict` tags and invented actions or prohibitions cannot close
|
|
344
|
+
a delivery question. Restate the intended action (for example, "Open a pull
|
|
345
|
+
request for review; do not merge") or explicitly name the prohibited effects.
|
|
346
|
+
A reply that the planner reads as asking for an uncovered action, or that
|
|
347
|
+
carries escalating vocabulary the planner leaves untagged, raises the same
|
|
348
|
+
question for the reply itself. A reply that restates a prohibition the profile
|
|
349
|
+
already honours ("no deployment by this task") maps to criteria once the planner
|
|
350
|
+
tags it as a covered `restrict` reading; insisting on an uncovered action
|
|
351
|
+
cannot expand the profile. Prepare a new task with a different typed profile
|
|
352
|
+
instead.
|
|
353
|
+
|
|
354
|
+
## The review
|
|
355
|
+
|
|
356
|
+
Every prepared revision returns one `review` object, pinned by `revision` and a
|
|
357
|
+
`digest` over the immutable request, fragments, answers, profile, harness,
|
|
358
|
+
route, draft hash, selected sources, repository snapshot and allowance:
|
|
359
|
+
|
|
360
|
+
- `request`: the original text, its hash and `immutable: true`.
|
|
361
|
+
- `requirementMap`: for each fragment, its source span, target (criteria,
|
|
362
|
+
assumption or question), any clarification, delivery tag, coverage, screen
|
|
363
|
+
result and conflict reason.
|
|
364
|
+
- `questions`, `assumptions` (planner assumptions plus screen assumptions) and
|
|
365
|
+
`draft` (path, hash, revision, text).
|
|
366
|
+
- `deliveryProfile`, `harness`, `allowance`, `modelRoute` and `cost`.
|
|
367
|
+
- `repositoryContext`, `readiness` and `approval`.
|
|
368
|
+
|
|
369
|
+
`task start --run` on the current revision records `approval` with that digest.
|
|
370
|
+
Answers clear readiness and approval, so a changed material input requires a
|
|
371
|
+
new review before the existing run path is callable. Preparation never authorizes
|
|
372
|
+
a new typed task, even if called with `run: true`.
|
|
373
|
+
An answered intake returns `ready` and needs its own `task start --run`. A saved
|
|
374
|
+
typed preparation flag without a review approval also requires that explicit
|
|
375
|
+
start. Tasks saved before typed profiles keep their documented
|
|
376
|
+
persisted authorization. A saved approval whose
|
|
377
|
+
digest no longer matches returns `TASK_CONFLICT` instead of dispatching. The
|
|
378
|
+
approved profile and approval travel into the implementation entry and are
|
|
379
|
+
checked again on reconciliation, so retries resume the same dispatch rather than
|
|
380
|
+
creating another.
|
|
381
|
+
|
|
382
|
+
The CLI prints the profile, planner route, cost status, repository snapshot
|
|
383
|
+
status and review summary; `--json` returns the complete object. The delivery
|
|
384
|
+
dispatcher and MCP views expose the same fields, and the bounded model summary
|
|
385
|
+
carries the profile action, completion, review revision and approval state.
|
|
386
|
+
|
|
387
|
+
## Planner routes
|
|
388
|
+
|
|
389
|
+
| Route | When | Boundary |
|
|
390
|
+
| --- | --- | --- |
|
|
391
|
+
| `harness` | The selected harness declares a preparation boundary (Claude, Codex, OpenAI Agents) | Existing dispatch, session controls and usage recording. Cost is provider-reported or labelled unknown, never zero. |
|
|
392
|
+
| `model` | `intake_model` is configured and its credential is exported | One bounded text request per planning turn against the configured endpoint, with no tools, shell, web or repository access. |
|
|
393
|
+
|
|
394
|
+
Without `--route`, a harness with a preparation boundary is used; otherwise the
|
|
395
|
+
model route when it is enabled; otherwise the existing
|
|
396
|
+
`TASK_PREPARATION_BOUNDARY` refusal. `--route model` on a disabled route returns
|
|
397
|
+
`TASK_MODEL_ROUTE` with the configuration remedy before any effect. The task's
|
|
398
|
+
`harness` still names the implementation adapter in the brief's frontmatter.
|
|
399
|
+
Unavailable implementation adapters are refused with `EXECUTION_UNAVAILABLE`
|
|
400
|
+
before a new task or planning call, independently of the planner route. An
|
|
401
|
+
available adapter without isolated preparation may still use the model route.
|
|
402
|
+
Saved results remain replayable; a known availability failure before a fresh
|
|
403
|
+
turn can be explicitly resumed after restoring its implementation transport,
|
|
404
|
+
without replacing the pinned route or retrying an unsettled call.
|
|
405
|
+
|
|
406
|
+
### Configuring the model route
|
|
407
|
+
|
|
408
|
+
```json
|
|
409
|
+
"intake_model": {
|
|
410
|
+
"adapter": "openai-chat",
|
|
411
|
+
"model": "gpt-5-mini",
|
|
412
|
+
"endpoint": "https://api.openai.com/v1/chat/completions",
|
|
413
|
+
"credential_env": "OPENAI_API_KEY",
|
|
414
|
+
"budget": { "max_calls": 12, "max_input_tokens": 100000, "max_output_tokens": 16000,
|
|
415
|
+
"allowance_usd": 10, "input_usd_per_million": 0.25, "output_usd_per_million": 2 },
|
|
416
|
+
"timeout_ms": 120000
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
`adapter` is `openai-chat` or `anthropic-messages`. The endpoint must be a
|
|
421
|
+
public HTTPS URL without credentials. The API key is read from the named
|
|
422
|
+
environment variable at call time and is never written to disk or returned by
|
|
423
|
+
any view. Ceilings are absolute: at most 12 calls per task, 100,000 input and
|
|
424
|
+
16,000 output tokens per call, and a $10 allowance. Configuration can lower
|
|
425
|
+
them and cannot raise them. The task's runtime allowance bounds each call too:
|
|
426
|
+
the deadline is capped to the remaining runtime, and less than one second
|
|
427
|
+
remaining refuses before the request. Before each call the route bounds input tokens at
|
|
428
|
+
one token per UTF-8 byte of the complete serialized request (system message,
|
|
429
|
+
prompt and framing fields, plus a fixed margin for protocol tokens), the
|
|
430
|
+
byte-level fallback worst case, so emoji and rare scripts cannot slip under the
|
|
431
|
+
ceiling. It prices that bound plus
|
|
432
|
+
the output limit at the configured list prices, and refuses to start the call
|
|
433
|
+
when the result does not fit the remaining allowance. Reported usage above
|
|
434
|
+
either ceiling rejects the draft after the call, and usage that is negative,
|
|
435
|
+
fractional or non-numeric is treated as a malformed response rather than a
|
|
436
|
+
spend record. The response body is read under the same deadline as the request
|
|
437
|
+
and cancelled at one megabyte, so a stalled or oversized provider reply cannot
|
|
438
|
+
hang the task lock or buffer without bound. Cancelling a body, including an
|
|
439
|
+
error response's body, is awaited only until that deadline.
|
|
440
|
+
|
|
441
|
+
A missing pinned credential blocks before any model attempt or reservation is
|
|
442
|
+
created. Restore the named environment variable and explicitly resume the saved
|
|
443
|
+
task; known credential preflight recovery preserves accepted answers, the
|
|
444
|
+
original validation feedback and repair count. Only this known model pre-call failure
|
|
445
|
+
can rearm: submitted, unsettled or failed provider calls retain their ownership
|
|
446
|
+
and spend evidence and cannot purchase a replacement call through resume. Older markerless pre-call failures recover only when all saved calls are successful, settled and consumed with matching text-only receipts.
|
|
447
|
+
|
|
448
|
+
A task pins the complete route selection (adapter, model, endpoint, budget,
|
|
449
|
+
timeout and the credential variable name) when it is created. Later turns,
|
|
450
|
+
including answers and repairs, run against that pinned selection and the
|
|
451
|
+
review digest covers it, so changing or removing `intake_model` affects new
|
|
452
|
+
tasks only. The credential itself is still read from the environment on every
|
|
453
|
+
call; if the named variable is missing the turn stops with the export remedy. Reported usage replaces and releases the reservation, so the
|
|
454
|
+
implementation allowance that follows subtracts the reported spend rather than
|
|
455
|
+
the ceiling held during the call; missing usage leaves the reservation as the
|
|
456
|
+
spend bound with `spend.status: "unknown"`. These are
|
|
457
|
+
estimates from list prices, not provider invoices. Truncated, over-limit,
|
|
458
|
+
malformed or empty responses are rejected with a bounded error and count as a
|
|
459
|
+
call.
|
|
460
|
+
|
|
461
|
+
## Repository context
|
|
462
|
+
|
|
463
|
+
Preparation collects a read-only snapshot of the selected checkout: the HEAD
|
|
464
|
+
revision and the path listing of that commit's tree, with ignored and private
|
|
465
|
+
paths removed (`.env`, credential, key and agent-configuration locations). The
|
|
466
|
+
checkout's in-tree `.gitignore` files decide ignores (local and global exclude
|
|
467
|
+
files do not), and they must match the recorded revision: an edited or
|
|
468
|
+
untracked `.gitignore` makes the snapshot unavailable with the files named,
|
|
469
|
+
instead of evaluating rules the recorded tree does not contain. A tree path the
|
|
470
|
+
index no longer holds (a staged deletion) is excluded as unverified and a
|
|
471
|
+
staged addition is never listed; the listing therefore always describes the
|
|
472
|
+
recorded revision. It is bounded to 400 paths and 16 KiB in the prompt; its
|
|
473
|
+
digest covers the complete approved listing at that revision. The revision,
|
|
474
|
+
the index and the ignore files are rechecked after the listings are read, so a concurrent
|
|
475
|
+
edit between the reads makes the snapshot unavailable instead of pairing the
|
|
476
|
+
recorded revision with another state. File contents reach the planner only through
|
|
477
|
+
explicitly selected `--context` documents, which are screened for credential
|
|
478
|
+
material. If the snapshot cannot be collected safely, the task records
|
|
479
|
+
`repositoryContext.status: "unavailable"` with the reason, and nothing is
|
|
480
|
+
guessed.
|
|
481
|
+
|
|
482
|
+
## Historical tasks
|
|
483
|
+
|
|
484
|
+
Tasks saved before typed profiles existed keep their original interpretation.
|
|
485
|
+
Those with a Coordinator delivery contract keep its versioned validation; those
|
|
486
|
+
without one keep the workflow default. Inspection labels them `legacy` and they
|
|
487
|
+
can still be validated, started, resumed and controlled. A saved profile with an
|
|
488
|
+
unsupported version, or whose target repository, base or completion does not
|
|
489
|
+
match the task it is saved on, is readable through `inspect` and `list` and can
|
|
490
|
+
be exported, but every mutation returns `TASK_PROFILE_UNSUPPORTED` with the
|
|
491
|
+
remedy "prepare a new task". A record created with a typed profile (it carries
|
|
492
|
+
a planner route, a repository snapshot or a pinned model route) whose profile
|
|
493
|
+
is missing is treated the same way, never as a historical task. Such a record does not pin an idle namespace, so runtime migration
|
|
494
|
+
proceeds. New tasks always use the current typed profile; there is no fallback
|
|
495
|
+
to the free-text contract.
|
|
496
|
+
|
|
497
|
+
## Agent Passport packaging
|
|
498
|
+
|
|
499
|
+
`lib/task_profile.mjs` and its portable host identity/declaration dependencies
|
|
500
|
+
are vendored together. They contain no Node transport or credential code. Its
|
|
501
|
+
completion conditions are checked against the coordinator schema by the focused
|
|
502
|
+
suite. `templates/plugin/task-intake-contract.json` pins the validator, every
|
|
503
|
+
transitive declaration file, the fixture corpus at
|
|
504
|
+
`templates/plugin/task-profile-requests.mjs` and the profile schema version.
|
|
505
|
+
All pinned files ship in the published package, so a consumer can run the exact
|
|
506
|
+
promised corpus. `npm run lint` fails when the pin is stale;
|
|
507
|
+
`npm run contract:intake -- --write` refreshes it after a reviewed change.
|
|
508
|
+
The plugin builder refuses to package when a pinned file differs and records
|
|
509
|
+
`intakeContract` in `runtime.json`. The
|
|
510
|
+
downstream `task-intake-vendor-sync` work in `aporthq/agent-passport` must pin
|
|
511
|
+
the published package, regenerate its bundled validator from these bytes and
|
|
512
|
+
run the same corpus before either repository's change is approved.
|
|
513
|
+
|
|
514
|
+
## Verification
|
|
515
|
+
|
|
516
|
+
```sh
|
|
517
|
+
npm test
|
|
518
|
+
npm run lint
|
|
519
|
+
npm run test:task-intake
|
|
520
|
+
git diff --check
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
The focused suite covers the request corpus (direct, indirect, quoted,
|
|
524
|
+
contradictory, adversarial and ordinary feature wording), per-clause
|
|
525
|
+
traceability, typed-profile authorization, review invalidation, retry and
|
|
526
|
+
idempotency, historical fixtures, model-route call, token and allowance
|
|
527
|
+
boundaries, repository snapshots and a bounded-input timing check. It makes no
|
|
528
|
+
provider calls. Maximum-size timing fixtures use the UTF-8 byte counts of their
|
|
529
|
+
complete repeated units and command prefixes/suffixes, with assertions that
|
|
530
|
+
inputs fill but never exceed the accepted request allowance. The 50 CPU ms
|
|
531
|
+
screening budget is unchanged. Repeated statements share checks only within one
|
|
532
|
+
screen; every target-conflict occurrence and whole-request PR count is retained.
|
|
533
|
+
Passive landing checks first require a matching subject before inspecting
|
|
534
|
+
feature context; maximum-size probes include unrelated words followed by a real
|
|
535
|
+
instruction or a feature phrase. Timing failures identify the exact fixture.
|
|
536
|
+
No live qualification of generated-PRD quality or actual cost is
|
|
537
|
+
recorded here.
|