@windyroad/itil 3.4.0-preview.1368 → 3.4.0-preview.1370
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 +1 -1
- package/skills/outcome-led-planning/SKILL.md +2 -2
- package/skills/outcome-led-planning/references/github-coordination.md +113 -62
- package/skills/outcome-led-planning/references/github-project-checkpoint.md +70 -6
- package/skills/outcome-led-planning/scripts/github-project-checkpoint.mjs +74 -8
- package/skills-codex/outcome-led-planning/SKILL.md +2 -2
- package/skills-codex/outcome-led-planning/references/github-coordination.md +113 -62
- package/skills-codex/outcome-led-planning/references/github-project-checkpoint.md +70 -6
- package/skills-codex/outcome-led-planning/scripts/github-project-checkpoint.mjs +74 -8
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@ Read the relevant current evidence, project instructions, decisions, jobs, risk
|
|
|
16
16
|
|
|
17
17
|
Use SMART to make the objective specific, measurable through observable completion evidence, achievable against known constraints, relevant to the user's job, and time-bound using the user's stated deadline or timeframe. Qualitative evidence can establish success. Surface feasibility uncertainty instead of weakening the objective or promising certainty. Never invent numerical targets or dates. Preserve stated timing and prefer relative wording. Any added date must match verified context and its weekday. Never turn a guessed date into a new timing interview. If neither a time bound nor an explicit decision to omit one is established, ask one timing question and wait. If the user declines a time bound, record the exception honestly rather than claiming full SMART compliance.
|
|
18
18
|
|
|
19
|
-
If
|
|
19
|
+
If outcome information is unclear or missing, interview the user: **ask one focused question, then stop and wait for their answer before asking the next**. Select the next question from their actual answer and remaining uncertainty. Do not bundle questions, answer on their behalf, invent their intent, or resolve ambiguity by selecting a solution. Bounded read-only investigation can establish facts within existing authority.
|
|
20
20
|
|
|
21
21
|
One question requests **one missing fact**. Do not combine multiple information needs, such as who benefits and what is wrong, into a multipart question. Sharing a topic or using one question mark does not make it one question.
|
|
22
22
|
|
|
@@ -104,6 +104,6 @@ Finish when the objective's completion evidence is satisfied. Record the verifie
|
|
|
104
104
|
|
|
105
105
|
Recording verified completion is a terminal status update, not another executable plan. Any newly proposed work still needs its own assessed plan.
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
Before handing back a blocker, finish useful authorized work, including running checks. Preserve work, distinguish completed increments from unfinished outcomes, and report the precise missing result, capability, authority or irreducible user action. Resume from fresh evidence when the blocker clears; do not restart completed effects.
|
|
108
108
|
|
|
109
109
|
Communicate the objective, consequential plan changes, decisions requiring input, exact blockers, and verified outcomes concisely. Avoid narrating routine commands or every review and wait.
|
|
@@ -128,21 +128,62 @@ Give the existing planning critic the saved outcome and affected increment recor
|
|
|
128
128
|
|
|
129
129
|
**Horizon belongs only to increments**: each planned or active increment has exactly one of Now, Next or Later. Remove completed or superseded increments from active horizons while preserving their prior position in history. **Status** separately describes execution, such as ready, in progress, blocked or done. A blocked Now increment does not automatically become Next; a completed task does not become a completed outcome. Outcomes and tasks do not inherit Horizon. Map these meanings to existing repository labels or Project fields. Replace the previous horizon when replanning rather than accumulating contradictory values.
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
Maintain parent/child and prerequisite relationships in this order:
|
|
132
|
+
|
|
133
|
+
1. Inspect the actual relationship and the precise result that unlocks a start,
|
|
134
|
+
stage or completion. Read current native sub-issue and blocked-by state when
|
|
135
|
+
supported. A native write denial proves neither presence nor absence:
|
|
136
|
+
preserve known links and keep unreadable native state unknown.
|
|
137
|
+
2. Keep completion dependencies acyclic. A prerequisite cannot require its
|
|
138
|
+
dependent's result to close. Propose changed task boundaries and acceptance
|
|
139
|
+
in the increment thread; the increment owner records agreement with affected
|
|
140
|
+
task owners before applying them. Obtain the five independent reviews before
|
|
141
|
+
materially revised execution. Give each task an independently verifiable
|
|
142
|
+
result and retain the combined results in increment acceptance.
|
|
143
|
+
3. After any required agreement and reviews, use native links when supported;
|
|
144
|
+
create a missing required link or update a changed one when authorized.
|
|
145
|
+
Verify saved native state and both relationship directions. If operations are
|
|
146
|
+
unavailable, record their exact limitation plus reciprocal parent/child or
|
|
147
|
+
prerequisite/dependent text links on both affected issues; text is not proof
|
|
148
|
+
of native state. Request capable help through an authorized channel when
|
|
149
|
+
useful, without inventing a helper or widening access.
|
|
150
|
+
4. Reassess actual useful work and status under the claim table below. A Ready
|
|
151
|
+
or In progress task may prepare while a real prerequisite remains open;
|
|
152
|
+
preserve its precise unlock condition and required evidence. Independently
|
|
153
|
+
verify the prerequisite result before clearing that condition and proceeding
|
|
154
|
+
with the dependent stage. Administrative issue closure is not another
|
|
155
|
+
prerequisite unless recorded acceptance or a project rule requires it.
|
|
156
|
+
|
|
157
|
+
Optional Project membership and fields mirror issue state; do not create them
|
|
158
|
+
merely because this protocol mentions them.
|
|
134
159
|
|
|
135
160
|
Replan task boundaries at any stage when evidence changes what work is needed. Coordinate narrowed, split, replaced or dropped scope with the increment owner and affected task owners. Close redundant or superseded issues as **not planned**, with the reason and successor links; never mark undelivered work Done merely to retire it. Before removing a dependency, move still-required acceptance evidence to the appropriate task and retain it in increment acceptance. Remove only genuinely obsolete native dependencies and verify the saved result; preserve prerequisites that still constrain the revised work. Keep task briefs, links, ownership and any selected Project fields current. Routine task reconciliation within the assessed outcome and authority needs no new user approval; materially revised executable work still requires the five independent plan reviews.
|
|
136
161
|
|
|
137
|
-
|
|
162
|
+
### Status and contribution-claim decision
|
|
163
|
+
|
|
164
|
+
Use this table whenever work starts, blocks, finishes or is handed over. Inspect
|
|
165
|
+
scope, inputs and actual useful authorized in-task steps first: a stored Blocked
|
|
166
|
+
status alone does not establish exhaustion. Genuine assigned watcher duties
|
|
167
|
+
count as useful work; waiting for an unverified response or routine discussion
|
|
168
|
+
reads alone do not retain an exhausted implementation reservation.
|
|
138
169
|
|
|
139
|
-
| Actual state of the claimed task | Status |
|
|
170
|
+
| Actual state of the claimed task | Status | Assignment and saved result |
|
|
140
171
|
| --- | --- | --- |
|
|
141
|
-
| Recorded acceptance is verified with evidence | Done |
|
|
172
|
+
| Recorded acceptance is verified with evidence | Done | Post acceptance evidence, finish and preserve attribution history. |
|
|
142
173
|
| Useful authorized in-task work remains | In progress | Retain the single claim and do that work. |
|
|
143
|
-
| A required input is unavailable and no useful authorized in-task step remains | Blocked |
|
|
174
|
+
| A required input is unavailable and no useful authorized in-task step remains | Blocked | Save the blocker, evidence, unlock condition and handover; remove your assignment and read back its removal. Preserve historical attribution. |
|
|
144
175
|
|
|
145
|
-
|
|
176
|
+
One contribution claim is a ceiling, not a retention requirement. A blocked
|
|
177
|
+
assignment still counts until release is verified. Apply the table before
|
|
178
|
+
claiming another task; never reserve queued tasks. Outcome/increment ownership
|
|
179
|
+
does not reserve contributions. Agents sharing an account remain distinct by
|
|
180
|
+
their recorded agent/session. Keep actionable unclaimed work Ready/Unclaimed;
|
|
181
|
+
a blocked task does not block every contribution. Never invent busywork.
|
|
182
|
+
|
|
183
|
+
If assignment mutation or verification is unavailable, record the exact pending
|
|
184
|
+
release and known claim state, use an authorized owner/channel when available,
|
|
185
|
+
and do not claim release or take another task while still assigned. Reassess
|
|
186
|
+
when evidence changes.
|
|
146
187
|
|
|
147
188
|
## Join, claim and contribute
|
|
148
189
|
|
|
@@ -151,71 +192,81 @@ Use this contribution lifecycle:
|
|
|
151
192
|
1. Read the outcome, current Now revision, discussion, dependencies and claims. Reconcile stale scope before dependent work.
|
|
152
193
|
2. Choose a bounded useful result and announce its acceptance and file/operation boundary in the increment thread. Resolve overlap, shared operations or authority questions with affected owners. A non-overlapping task within the assessed Now needs no allocator approval.
|
|
153
194
|
3. Reuse a matching unclaimed task, or create your own just before work. Apply the established task-kind marker (`kind:task` by default). Assign it to the **actual authenticated account** and record the **specific agent/session** and native links; read back kind, assignment, claim and links and recheck competing work. For a selected or required Project, explicitly add the task and read back its membership and applicable fields so it matches the saved view.
|
|
154
|
-
4. Execute within the assessed plan and authority
|
|
195
|
+
4. Execute within the assessed plan and authority; apply the status and contribution-claim decision above, including saved release when exhausted.
|
|
155
196
|
5. Choose and document the next useful contribution from the remaining outcome gap, then repeat these checks before claiming it.
|
|
156
197
|
|
|
157
198
|
A starting battle plan exposes likely work, dependencies and parallel opportunities without precreating, assigning or reserving every future task. The increment owner keeps acceptance, sequence and integration clear and resolves overlap/dependencies. Explicit assignments and handoffs remain valid. Two agents sharing an account are distinct contributors. Checklists suffice for routine steps; do not create a task for every command. Task creation within assessed scope requires no fresh human approval.
|
|
158
199
|
|
|
159
|
-
**Each agent holds only one contribution task at a time**, including a blocked assignment. Finish, explicitly hand over or release the current assignment before claiming another. Do not reserve queued tasks. Outcome or increment coordination ownership does not reserve contribution tasks. Agents sharing an account remain distinct through their recorded agent/session identities.
|
|
160
|
-
|
|
161
200
|
Before declaring a contribution ready to start, complete this claim receipt: **no other contribution assignment held; parent increment; current assessed plan revision; non-overlapping scope; dependencies (or explicitly none); actual account; distinct agent/session; saved claim and reciprocal-link readback; competing-claim recheck.** Record all fields on the task, even when some are already known in conversation. Assignment does not increase authority. When explaining a proposed claim, make these required fields and the before/after overlap checks explicit.
|
|
162
201
|
|
|
163
202
|
Record scope boundaries and dependencies, then read back the claim, links and any competing claims. Issue claims are cooperative, not atomic locks: another agent may have claimed overlapping work since your first read. Reconcile that race before dependent implementation. If another contributor has claimed the same work, agree a split or handoff in the increment thread before overlapping implementation. An inactive or old claim is not permission to take over silently. If assignment is unavailable, record the intended owner and unassigned state, request the owner’s help through the agreed coordination channel when authorized, and continue only work whose ownership is clear. Never claim an assignment or board update succeeded without reading it back.
|
|
164
203
|
|
|
165
204
|
## Reconcile tracking at work checkpoints
|
|
166
205
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
cadence
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
are both
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
206
|
+
During an active work window, follow this coordination sequence while coding
|
|
207
|
+
or waiting:
|
|
208
|
+
|
|
209
|
+
1. Use the agreed, saved discussion-reading cadence. If none exists, propose a
|
|
210
|
+
bounded cadence through the authorized increment thread, obtain agreement
|
|
211
|
+
and verify its saved record. While agreement is pending, continue regular
|
|
212
|
+
bounded reads; a proposal is not agreement.
|
|
213
|
+
2. Also read new increment comments on joining/resuming and at the event
|
|
214
|
+
checkpoints below, including before dependent actions, pushes, scope or
|
|
215
|
+
ownership changes and handovers. Regular reads and event reads are both
|
|
216
|
+
required; neither replaces the other.
|
|
217
|
+
3. Answer relevant questions and handle handoffs through the authorized channel
|
|
218
|
+
and handoff rules below: actual recipient
|
|
219
|
+
acknowledgement and linked task, independent verification of returned
|
|
220
|
+
evidence, and updates to your task's evidence, dependency and next action.
|
|
221
|
+
A posted message is not the recipient's acknowledgement.
|
|
222
|
+
4. If the result materially changes the executable plan, reconcile that revision
|
|
223
|
+
and obtain the five independent reviews before dependent execution. Otherwise
|
|
224
|
+
continue within the assessed plan. Apply the claim table when work is
|
|
225
|
+
exhausted rather than retaining it for discussion reads.
|
|
226
|
+
|
|
227
|
+
These are bounded checks during active work, not a standing poller or a promise
|
|
228
|
+
to wake an idle agent. Use only already-authorized communication channels.
|
|
188
229
|
|
|
189
230
|
At each work checkpoint, reconcile tracking in this order:
|
|
190
231
|
|
|
191
|
-
|
|
192
|
-
the [
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
232
|
+
When the affected records include an outcome, current Now, provisional Next and
|
|
233
|
+
a task, and `gh` works, MUST first use the [read-only hierarchy inspector](github-project-checkpoint.md#inspect-the-hierarchy).
|
|
234
|
+
Construct its request from those actual records and consume its findings before
|
|
235
|
+
claiming completeness; identical draft/remote text is not that comparison.
|
|
236
|
+
Do not manufacture a Next issue for this route. Its configuration report is one
|
|
237
|
+
source for the selection decision below, not proof of capability or acceptance.
|
|
238
|
+
|
|
239
|
+
1. **Establish selection before checking Project capability.** Reuse the
|
|
240
|
+
established backend. From configuration, project requirements or explicit
|
|
241
|
+
direction, choose the applicable branch:
|
|
242
|
+
- **Selected/required:** verify the repository, Project and account, then
|
|
243
|
+
inspect its saved setup and applicable operations. For join/resume of an
|
|
244
|
+
active open task with working `gh`, MUST use the [executable Project checkpoint](github-project-checkpoint.md).
|
|
245
|
+
Read its inspection and handle current discussion before applying it;
|
|
246
|
+
do not manually publish synchronization-success text on that route.
|
|
247
|
+
If an applicable operation is unavailable, retain its exact pending state
|
|
248
|
+
under the recovery rules below. An unavailable API or bootstrap default
|
|
249
|
+
does not prove a missing view, field or membership.
|
|
250
|
+
- **Established none:** continue issue-side reconciliation without Project
|
|
251
|
+
setup, fields or synchronization.
|
|
252
|
+
- **Unresolved:** inspect available configuration, requirements, direction and
|
|
253
|
+
issue records. Record the selection gap and keep Project work conditional;
|
|
254
|
+
there is no established mirror operation to report pending or unsynchronized.
|
|
255
|
+
Omitted information and API availability establish neither selection nor
|
|
256
|
+
an explicit choice to use no Project.
|
|
257
|
+
2. **Inspect each affected record before classifying it.** Compare every
|
|
258
|
+
outcome, increment and task with the minimum-information table. Preserve its
|
|
259
|
+
own recorded owner/account, applicable agent/session, revision and acceptance,
|
|
260
|
+
including provisional and completed records. Mark a required value unresolved
|
|
261
|
+
only when inspection cannot establish it; omission from a scenario or summary
|
|
262
|
+
does not establish that saved information is missing. Completion evidence
|
|
263
|
+
does not replace the task's own revision or acceptance. Provisional ownership,
|
|
264
|
+
revision and tentative acceptance imply neither an executable plan nor
|
|
265
|
+
critic approval or completion evidence.
|
|
266
|
+
Record actual scope, status, increment-only Horizon, dependencies/blocker,
|
|
267
|
+
next action and state-appropriate evidence. For a selected/required Project,
|
|
268
|
+
each item's Agent remains its verified owner/session, never an identity
|
|
269
|
+
copied from its parent or child; Status reflects that item's actual work.
|
|
219
270
|
3. **Update and verify.** Make only necessary authorized changes to existing
|
|
220
271
|
records. Read back every changed issue's fields and links, checking both
|
|
221
272
|
directions of parent/dependency relationships. For a selected or required
|
|
@@ -235,7 +286,7 @@ system.
|
|
|
235
286
|
| Join, resume or start implementation | Read current records and discussion; correct stale status, scope and ownership before dependent implementation. Set the active task and increment In progress when useful work starts. Complete missing selected Project setup or record its precise unavailable operation. |
|
|
236
287
|
| Material milestone or failed verification | Record the actual result and evidence before the next dependent action. Keep In progress while useful repair remains; a failed check alone does not mean Blocked. |
|
|
237
288
|
| Scope, dependency, plan or horizon change | Update affected briefs, native relationships and increment horizons; remove superseded active horizons. Obtain the required reviews before materially revised execution. |
|
|
238
|
-
| Block, hand off, finish or yield the active work window |
|
|
289
|
+
| Block, hand off, finish or yield the active work window | Apply the claim table, saving the gap, next action/owner or acceptance evidence and verifying any required release. Reconcile the increment as well as the task; do not leave stale status or next action. |
|
|
239
290
|
|
|
240
291
|
For a selected or required Project, when an operation is unavailable, record
|
|
241
292
|
the affected view/field/item,
|
|
@@ -271,7 +322,7 @@ When an authorized owner must complete a pending Project operation, request it t
|
|
|
271
322
|
|
|
272
323
|
## Verify, learn and replan as the outcome owner
|
|
273
324
|
|
|
274
|
-
Post acceptance evidence before completing a task. Preserve its actual recorded acceptance: do not invent a later release check as a repair-task completion condition, or remove an established condition to finish early. At handoff,
|
|
325
|
+
Post acceptance evidence before completing a task. Preserve its actual recorded acceptance: do not invent a later release check as a repair-task completion condition, or remove an established condition to finish early. At handoff, apply the claim table; an explicit ownership transfer additionally needs the identified recipient's acknowledgement. Do not report both releasing and retaining the same claim. The increment owner verifies the whole increment against its criteria before closing it; task completion alone does not establish delivery. Publication, installed behavior and production/customer verification remain separate evidence stages where applicable.
|
|
275
326
|
|
|
276
327
|
After a verified increment, or earlier when evidence invalidates the plan, the outcome owner:
|
|
277
328
|
|
|
@@ -1,6 +1,72 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Inspect and reconcile GitHub records
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Resolve `scripts/github-project-checkpoint.mjs` relative to this installed
|
|
4
|
+
planning skill, including when called from `contribute`. Use the existing
|
|
5
|
+
authenticated `gh` account and saved project configuration. The default is
|
|
6
|
+
`.agents/planning.json`; an existing project-declared configuration path may be
|
|
7
|
+
supplied last. These operations require no new grants, account changes or tokens.
|
|
8
|
+
Local tracking keeps its existing path.
|
|
9
|
+
|
|
10
|
+
## Inspect the hierarchy
|
|
11
|
+
|
|
12
|
+
When reconciling an outcome, current Now, an affected provisional Next and a
|
|
13
|
+
task together with working `gh`, planning and `contribute` MUST first use the
|
|
14
|
+
read-only hierarchy inspector. Supply those actual distinct issue numbers;
|
|
15
|
+
do not invent a Next issue to satisfy the command. Other record sets retain
|
|
16
|
+
their existing coordination path.
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"outcome": 1,
|
|
21
|
+
"increment": {"issue": 2},
|
|
22
|
+
"next": {"issue": 3},
|
|
23
|
+
"task": {"issue": 4}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Run `node <installed-planning-skill>/scripts/github-project-checkpoint.mjs inspect-hierarchy request.json`.
|
|
28
|
+
This reads the four actual issues and their returned comments. It writes
|
|
29
|
+
nothing and makes no Project or native-link request. Read the raw records and
|
|
30
|
+
consume `findings` before claiming that the records are correct:
|
|
31
|
+
|
|
32
|
+
- `projectSelection` reports configuration facts. `not-recorded` means selection
|
|
33
|
+
is unresolved from that configuration, not an explicit choice to use no
|
|
34
|
+
Project. `recorded` does not prove capability; consider actual project
|
|
35
|
+
requirements and explicit direction too. Preserve invalid configuration.
|
|
36
|
+
- Each record's `inspection` reports literal owner, revision, acceptance and
|
|
37
|
+
Parent candidates with raw line evidence. `candidate` is text, not verified
|
|
38
|
+
ownership or passed acceptance. `explicitly-unresolved` preserves a recorded
|
|
39
|
+
unknown. Empty/missing literals, unsupported syntax and multiple candidates
|
|
40
|
+
remain unestablished by this inspector; they do not prove semantic information
|
|
41
|
+
is absent or that the issue is invalid. Inspect the actual prose/history
|
|
42
|
+
rather than forcing a new format or choosing a historical value.
|
|
43
|
+
- `textLinks` compares the three requested textual relationships. A mention is
|
|
44
|
+
observed text, not proof of a current native relationship. Inspect both sides
|
|
45
|
+
and repair known reciprocal gaps under the existing coordination rules.
|
|
46
|
+
- `capabilities` are `not-probed`; do not turn that into an outage or native-link
|
|
47
|
+
absence. `inspection-unavailable` means the read/report operation failed,
|
|
48
|
+
not that a Project mirror is pending.
|
|
49
|
+
|
|
50
|
+
A successful command produces a diagnostic report, never a correctness or
|
|
51
|
+
synchronization verdict. Identical drafts and saved bodies do not establish
|
|
52
|
+
completeness. Before claiming completeness, account for every finding through
|
|
53
|
+
actual semantic review, authorized repair with saved readback where needed, or
|
|
54
|
+
honest unresolved recording in the existing plan or record. Follow the selection
|
|
55
|
+
finding's conditional next action, which targets the existing outcome issue
|
|
56
|
+
for saving and reading back a still-unresolved gap. Reuse an already saved gap
|
|
57
|
+
without an unchanged write. Configuration alone may leave the choice unresolved
|
|
58
|
+
while requirements or explicit direction establish it. Unsupported
|
|
59
|
+
syntax does not force normalization or another artifact.
|
|
60
|
+
Apply the existing per-record rules to known gaps, marking missing
|
|
61
|
+
required information unresolved rather than inventing it; preserve completed
|
|
62
|
+
acceptance and attribution. Read back authorized changes and compare reciprocal
|
|
63
|
+
links before reporting reconciliation. Unsupported syntax needs actual review,
|
|
64
|
+
not automatic normalization. Semantic acceptance remains with the caller and
|
|
65
|
+
required independent review.
|
|
66
|
+
|
|
67
|
+
## Synchronize selected Project fields
|
|
68
|
+
|
|
69
|
+
For a join/resume checkpoint on an active open task with a selected GitHub Project and working `gh`,
|
|
4
70
|
planning and `contribute` MUST use the bundled
|
|
5
71
|
`scripts/github-project-checkpoint.mjs` operation. Do not manually publish a
|
|
6
72
|
Project synchronization-success claim on this route. The operation reads the
|
|
@@ -8,10 +74,8 @@ records/discussion, updates the two items, verifies their saved fields and only
|
|
|
8
74
|
then generates the task's synchronization result. It does not allocate owners,
|
|
9
75
|
approve a plan, acknowledge another person or complete the increment.
|
|
10
76
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
project configuration; no new grants, account changes or tokens are required by
|
|
14
|
-
the operation. Local and GitHub Issues-only tracking keep their existing paths.
|
|
77
|
+
This mutation route applies to its open outcome, increment and active task.
|
|
78
|
+
GitHub Issues-only tracking uses no Project field mutations.
|
|
15
79
|
|
|
16
80
|
## Inspect, decide, apply
|
|
17
81
|
|
|
@@ -26,10 +26,14 @@ function json(args, input) {
|
|
|
26
26
|
if (value.errors?.length) throw new Error(value.errors.map(error => error.message).join('; '));
|
|
27
27
|
return value;
|
|
28
28
|
}
|
|
29
|
-
function
|
|
30
|
-
requireValue(config
|
|
29
|
+
function repositoryFor(config) {
|
|
30
|
+
requireValue(config?.version === 1 && config.backend === 'github', 'This operation requires the saved GitHub backend.');
|
|
31
31
|
const repository = config.github?.repository;
|
|
32
|
-
requireValue(typeof repository === 'string' && /^[
|
|
32
|
+
requireValue(typeof repository === 'string' && /^[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\/[\w.-]+$/.test(repository) && !['.', '..'].includes(repository.split('/')[1]), 'Invalid configured GitHub repository.');
|
|
33
|
+
return repository;
|
|
34
|
+
}
|
|
35
|
+
function scope(request, config) {
|
|
36
|
+
const repository = repositoryFor(config);
|
|
33
37
|
const url = new URL(config.github?.projectUrl);
|
|
34
38
|
const match = url.pathname.match(/^\/(?:users|orgs)\/([\w.-]+)\/projects\/([1-9]\d*)(?:\/views\/[1-9]\d*)?\/?$/);
|
|
35
39
|
requireValue(url.protocol === 'https:' && url.hostname === 'github.com' && match && !url.username && !url.password, 'A selected GitHub Project URL is required.');
|
|
@@ -44,6 +48,66 @@ function scope(request, config) {
|
|
|
44
48
|
function issue(number, bound) {
|
|
45
49
|
return json(['issue', 'view', String(number), '--repo', bound.repository, '--json', 'number,url,body,state,assignees,labels,comments']);
|
|
46
50
|
}
|
|
51
|
+
function briefField(body, pattern, cue) {
|
|
52
|
+
// shortcut: observed literal brief fields only; extend when an actual brief needs another syntax.
|
|
53
|
+
const lines = body.split(/\r?\n/).map((text, index) => ({ line: index + 1, text }));
|
|
54
|
+
const matches = lines.flatMap(line => {
|
|
55
|
+
const match = line.text.match(pattern);
|
|
56
|
+
return match ? [{ ...line, value: match[1].trim() }] : [];
|
|
57
|
+
});
|
|
58
|
+
const literalEvidence = matches.map(({ line, text }) => ({ line, text }));
|
|
59
|
+
if (matches.length > 1) return { state: 'multiple-candidates', evidence: literalEvidence };
|
|
60
|
+
if (matches.length === 1) {
|
|
61
|
+
const { value } = matches[0];
|
|
62
|
+
return { state: !value ? 'empty' : /^(?:unresolved|unknown|tbd|unclaimed)(?:\b|$)/i.test(value) ? 'explicitly-unresolved' : 'candidate', value, evidence: literalEvidence };
|
|
63
|
+
}
|
|
64
|
+
const evidence = lines.filter(line => cue.test(line.text));
|
|
65
|
+
return { state: evidence.length ? 'unsupported-format' : 'literal-field-missing', evidence };
|
|
66
|
+
}
|
|
67
|
+
function textReference(body, number, repository) {
|
|
68
|
+
const escaped = repository.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
69
|
+
const reference = new RegExp(`(?:(?<![\\w./#:-])#${number}\\b|https://github\\.com/${escaped}/issues/${number}(?![\\w/]))`, 'i');
|
|
70
|
+
const evidence = body.split(/\r?\n/).flatMap((text, index) => reference.test(text) ? [{ line: index + 1, text }] : []);
|
|
71
|
+
return { observed: evidence.length > 0, evidence };
|
|
72
|
+
}
|
|
73
|
+
function inspectHierarchy(request, config) {
|
|
74
|
+
const repository = repositoryFor(config);
|
|
75
|
+
const roles = { outcome: request?.outcome, increment: request?.increment?.issue, next: request?.next?.issue, task: request?.task?.issue };
|
|
76
|
+
requireValue(Object.values(roles).every(n => Number.isSafeInteger(n) && n > 0) && new Set(Object.values(roles)).size === 4, 'Four distinct outcome, increment, next and task issue numbers are required.');
|
|
77
|
+
const projectSelection = { state: 'not-recorded', source: 'configuration' };
|
|
78
|
+
if (Object.hasOwn(config.github, 'projectUrl')) {
|
|
79
|
+
try {
|
|
80
|
+
const url = new URL(config.github.projectUrl);
|
|
81
|
+
requireValue(url.protocol === 'https:' && url.hostname === 'github.com' && !url.username && !url.password && !url.search && !url.hash && /^\/(?:users|orgs)\/[\w.-]+\/projects\/[1-9]\d*(?:\/views\/[1-9]\d*)?\/?$/.test(url.pathname), 'Invalid recorded Project URL.');
|
|
82
|
+
Object.assign(projectSelection, { state: 'recorded', url: `https://github.com${url.pathname.split('/views/')[0].replace(/\/$/, '')}` });
|
|
83
|
+
} catch { projectSelection.state = 'invalid'; }
|
|
84
|
+
}
|
|
85
|
+
const records = {};
|
|
86
|
+
const findings = projectSelection.state === 'recorded' ? [] : [{ issue: roles.outcome, field: 'projectSelection', state: projectSelection.state, nextAction: `Establish selection from applicable project requirements and explicit direction. If it remains unresolved, save that selection gap and conditional Project work on outcome #${roles.outcome} and read back its saved body before claiming reconciliation complete. Reuse an already saved gap without an unchanged write.` }];
|
|
87
|
+
for (const [role, number] of Object.entries(roles)) {
|
|
88
|
+
const record = issue(number, { repository });
|
|
89
|
+
requireValue(record.number === number && record.url?.toLowerCase() === `https://github.com/${repository}/issues/${number}`.toLowerCase() && typeof record.body === 'string', 'Returned issue does not match its requested repository/number or brief.');
|
|
90
|
+
const inspection = {
|
|
91
|
+
owner: briefField(record.body, /^\s*(?:(?:Outcome|Increment|Task) )?Owner:\s*(.*)$/i, /\bowner\b/i),
|
|
92
|
+
revision: briefField(record.body, /^\s*Revision:\s*(.*)$/i, /\brevision\b/i),
|
|
93
|
+
acceptance: briefField(record.body, /^\s*(?:Tentative )?Acceptance(?: criteria| evidence)?:\s*(.*)$/i, /\bacceptance\b/i),
|
|
94
|
+
parent: briefField(record.body, /^\s*Parent(?: outcome| increment)?:\s*(.*)$/i, /\bparent\b/i)
|
|
95
|
+
};
|
|
96
|
+
records[role] = { ...record, inspection };
|
|
97
|
+
for (const field of ['owner', 'revision', 'acceptance']) {
|
|
98
|
+
if (!['candidate', 'explicitly-unresolved'].includes(inspection[field].state)) findings.push({ issue: number, field, state: inspection[field].state });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const textLinks = [[records.outcome, records.increment], [records.outcome, records.next], [records.increment, records.task]].map(([parent, child]) => {
|
|
102
|
+
const parentMentionsChild = textReference(parent.body, child.number, repository);
|
|
103
|
+
const field = child.inspection.parent;
|
|
104
|
+
const referencesExpected = 'value' in field ? textReference(field.value, parent.number, repository).observed : null;
|
|
105
|
+
if (!parentMentionsChild.observed) findings.push({ issue: parent.number, field: 'child-text-reference', state: 'not-established', child: child.number });
|
|
106
|
+
if (referencesExpected !== true) findings.push({ issue: child.number, field: 'parent-text-reference', state: 'not-established', parent: parent.number });
|
|
107
|
+
return { parent: parent.number, child: child.number, parentMentionsChild, childParent: { ...field, referencesExpected } };
|
|
108
|
+
});
|
|
109
|
+
return { repository, projectSelection, capabilities: { project: 'not-probed', nativeLinks: 'not-probed' }, records, textLinks, findings };
|
|
110
|
+
}
|
|
47
111
|
function items(request, bound, projectId) {
|
|
48
112
|
const response = json(['api', 'graphql', '--input', '-'], JSON.stringify({ query: itemQuery, variables: { ids: [request.increment.itemId, request.task.itemId], agentFieldId: request.agentFieldId } }));
|
|
49
113
|
requireValue(response.data.agentField?.dataType === 'TEXT', 'The Agent field must be a text field.');
|
|
@@ -125,18 +189,20 @@ function apply(request, inspection, config) {
|
|
|
125
189
|
}
|
|
126
190
|
|
|
127
191
|
if (process.argv[2] === '--help') {
|
|
128
|
-
console.log('
|
|
192
|
+
console.log('Hierarchy: node github-project-checkpoint.mjs inspect-hierarchy REQUEST.json [CONFIG.json]\nInspect: node github-project-checkpoint.mjs inspect REQUEST.json [CONFIG.json]\nApply: node github-project-checkpoint.mjs apply REQUEST.json INSPECTION.json [CONFIG.json]');
|
|
129
193
|
} else {
|
|
130
194
|
try {
|
|
131
195
|
const [mode, requestPath, third, fourth] = process.argv.slice(2);
|
|
132
|
-
requireValue(
|
|
196
|
+
requireValue(['inspect', 'apply', 'inspect-hierarchy'].includes(mode), 'Expected inspect-hierarchy, inspect or apply; use --help for usage.');
|
|
133
197
|
const request = load(requestPath);
|
|
134
|
-
const config = load((mode === '
|
|
135
|
-
const result = mode === 'inspect' ? inspect(request, config) : apply(request, load(third), config);
|
|
198
|
+
const config = load((mode === 'apply' ? fourth : third) || '.agents/planning.json');
|
|
199
|
+
const result = mode === 'inspect-hierarchy' ? inspectHierarchy(request, config) : mode === 'inspect' ? inspect(request, config) : apply(request, load(third), config);
|
|
136
200
|
console.log(JSON.stringify(result));
|
|
137
201
|
if (result.status && result.status !== 'synchronized') process.exitCode = 1;
|
|
138
202
|
} catch (error) {
|
|
139
|
-
console.log(JSON.stringify(
|
|
203
|
+
console.log(JSON.stringify(process.argv[2] === 'inspect-hierarchy'
|
|
204
|
+
? { status: 'inspection-unavailable', reason: error.message, nextAction: 'Read the affected configuration or record before claiming a completed inspection.' }
|
|
205
|
+
: { status: 'pending', reason: error.message, nextAction: 'Inspect the affected record and resolve this operation before claiming synchronization.' }));
|
|
140
206
|
process.exitCode = 1;
|
|
141
207
|
}
|
|
142
208
|
}
|
|
@@ -25,7 +25,7 @@ Read the relevant current evidence, project instructions, decisions, jobs, risk
|
|
|
25
25
|
|
|
26
26
|
Use SMART to make the objective specific, measurable through observable completion evidence, achievable against known constraints, relevant to the user's job, and time-bound using the user's stated deadline or timeframe. Qualitative evidence can establish success. Surface feasibility uncertainty instead of weakening the objective or promising certainty. Never invent numerical targets or dates. Preserve stated timing and prefer relative wording. Any added date must match verified context and its weekday. Never turn a guessed date into a new timing interview. If neither a time bound nor an explicit decision to omit one is established, ask one timing question and wait. If the user declines a time bound, record the exception honestly rather than claiming full SMART compliance.
|
|
27
27
|
|
|
28
|
-
If
|
|
28
|
+
If outcome information is unclear or missing, interview the user: **ask one focused question, then stop and wait for their answer before asking the next**. Select the next question from their actual answer and remaining uncertainty. Do not bundle questions, answer on their behalf, invent their intent, or resolve ambiguity by selecting a solution. Bounded read-only investigation can establish facts within existing authority.
|
|
29
29
|
|
|
30
30
|
One question requests **one missing fact**. Do not combine multiple information needs, such as who benefits and what is wrong, into a multipart question. Sharing a topic or using one question mark does not make it one question.
|
|
31
31
|
|
|
@@ -113,6 +113,6 @@ Finish when the objective's completion evidence is satisfied. Record the verifie
|
|
|
113
113
|
|
|
114
114
|
Recording verified completion is a terminal status update, not another executable plan. Any newly proposed work still needs its own assessed plan.
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
Before handing back a blocker, finish useful authorized work, including running checks. Preserve work, distinguish completed increments from unfinished outcomes, and report the precise missing result, capability, authority or irreducible user action. Resume from fresh evidence when the blocker clears; do not restart completed effects.
|
|
117
117
|
|
|
118
118
|
Communicate the objective, consequential plan changes, decisions requiring input, exact blockers, and verified outcomes concisely. Avoid narrating routine commands or every review and wait.
|
|
@@ -128,21 +128,62 @@ Give the existing planning critic the saved outcome and affected increment recor
|
|
|
128
128
|
|
|
129
129
|
**Horizon belongs only to increments**: each planned or active increment has exactly one of Now, Next or Later. Remove completed or superseded increments from active horizons while preserving their prior position in history. **Status** separately describes execution, such as ready, in progress, blocked or done. A blocked Now increment does not automatically become Next; a completed task does not become a completed outcome. Outcomes and tasks do not inherit Horizon. Map these meanings to existing repository labels or Project fields. Replace the previous horizon when replanning rather than accumulating contradictory values.
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
Maintain parent/child and prerequisite relationships in this order:
|
|
132
|
+
|
|
133
|
+
1. Inspect the actual relationship and the precise result that unlocks a start,
|
|
134
|
+
stage or completion. Read current native sub-issue and blocked-by state when
|
|
135
|
+
supported. A native write denial proves neither presence nor absence:
|
|
136
|
+
preserve known links and keep unreadable native state unknown.
|
|
137
|
+
2. Keep completion dependencies acyclic. A prerequisite cannot require its
|
|
138
|
+
dependent's result to close. Propose changed task boundaries and acceptance
|
|
139
|
+
in the increment thread; the increment owner records agreement with affected
|
|
140
|
+
task owners before applying them. Obtain the five independent reviews before
|
|
141
|
+
materially revised execution. Give each task an independently verifiable
|
|
142
|
+
result and retain the combined results in increment acceptance.
|
|
143
|
+
3. After any required agreement and reviews, use native links when supported;
|
|
144
|
+
create a missing required link or update a changed one when authorized.
|
|
145
|
+
Verify saved native state and both relationship directions. If operations are
|
|
146
|
+
unavailable, record their exact limitation plus reciprocal parent/child or
|
|
147
|
+
prerequisite/dependent text links on both affected issues; text is not proof
|
|
148
|
+
of native state. Request capable help through an authorized channel when
|
|
149
|
+
useful, without inventing a helper or widening access.
|
|
150
|
+
4. Reassess actual useful work and status under the claim table below. A Ready
|
|
151
|
+
or In progress task may prepare while a real prerequisite remains open;
|
|
152
|
+
preserve its precise unlock condition and required evidence. Independently
|
|
153
|
+
verify the prerequisite result before clearing that condition and proceeding
|
|
154
|
+
with the dependent stage. Administrative issue closure is not another
|
|
155
|
+
prerequisite unless recorded acceptance or a project rule requires it.
|
|
156
|
+
|
|
157
|
+
Optional Project membership and fields mirror issue state; do not create them
|
|
158
|
+
merely because this protocol mentions them.
|
|
134
159
|
|
|
135
160
|
Replan task boundaries at any stage when evidence changes what work is needed. Coordinate narrowed, split, replaced or dropped scope with the increment owner and affected task owners. Close redundant or superseded issues as **not planned**, with the reason and successor links; never mark undelivered work Done merely to retire it. Before removing a dependency, move still-required acceptance evidence to the appropriate task and retain it in increment acceptance. Remove only genuinely obsolete native dependencies and verify the saved result; preserve prerequisites that still constrain the revised work. Keep task briefs, links, ownership and any selected Project fields current. Routine task reconciliation within the assessed outcome and authority needs no new user approval; materially revised executable work still requires the five independent plan reviews.
|
|
136
161
|
|
|
137
|
-
|
|
162
|
+
### Status and contribution-claim decision
|
|
163
|
+
|
|
164
|
+
Use this table whenever work starts, blocks, finishes or is handed over. Inspect
|
|
165
|
+
scope, inputs and actual useful authorized in-task steps first: a stored Blocked
|
|
166
|
+
status alone does not establish exhaustion. Genuine assigned watcher duties
|
|
167
|
+
count as useful work; waiting for an unverified response or routine discussion
|
|
168
|
+
reads alone do not retain an exhausted implementation reservation.
|
|
138
169
|
|
|
139
|
-
| Actual state of the claimed task | Status |
|
|
170
|
+
| Actual state of the claimed task | Status | Assignment and saved result |
|
|
140
171
|
| --- | --- | --- |
|
|
141
|
-
| Recorded acceptance is verified with evidence | Done |
|
|
172
|
+
| Recorded acceptance is verified with evidence | Done | Post acceptance evidence, finish and preserve attribution history. |
|
|
142
173
|
| Useful authorized in-task work remains | In progress | Retain the single claim and do that work. |
|
|
143
|
-
| A required input is unavailable and no useful authorized in-task step remains | Blocked |
|
|
174
|
+
| A required input is unavailable and no useful authorized in-task step remains | Blocked | Save the blocker, evidence, unlock condition and handover; remove your assignment and read back its removal. Preserve historical attribution. |
|
|
144
175
|
|
|
145
|
-
|
|
176
|
+
One contribution claim is a ceiling, not a retention requirement. A blocked
|
|
177
|
+
assignment still counts until release is verified. Apply the table before
|
|
178
|
+
claiming another task; never reserve queued tasks. Outcome/increment ownership
|
|
179
|
+
does not reserve contributions. Agents sharing an account remain distinct by
|
|
180
|
+
their recorded agent/session. Keep actionable unclaimed work Ready/Unclaimed;
|
|
181
|
+
a blocked task does not block every contribution. Never invent busywork.
|
|
182
|
+
|
|
183
|
+
If assignment mutation or verification is unavailable, record the exact pending
|
|
184
|
+
release and known claim state, use an authorized owner/channel when available,
|
|
185
|
+
and do not claim release or take another task while still assigned. Reassess
|
|
186
|
+
when evidence changes.
|
|
146
187
|
|
|
147
188
|
## Join, claim and contribute
|
|
148
189
|
|
|
@@ -151,71 +192,81 @@ Use this contribution lifecycle:
|
|
|
151
192
|
1. Read the outcome, current Now revision, discussion, dependencies and claims. Reconcile stale scope before dependent work.
|
|
152
193
|
2. Choose a bounded useful result and announce its acceptance and file/operation boundary in the increment thread. Resolve overlap, shared operations or authority questions with affected owners. A non-overlapping task within the assessed Now needs no allocator approval.
|
|
153
194
|
3. Reuse a matching unclaimed task, or create your own just before work. Apply the established task-kind marker (`kind:task` by default). Assign it to the **actual authenticated account** and record the **specific agent/session** and native links; read back kind, assignment, claim and links and recheck competing work. For a selected or required Project, explicitly add the task and read back its membership and applicable fields so it matches the saved view.
|
|
154
|
-
4. Execute within the assessed plan and authority
|
|
195
|
+
4. Execute within the assessed plan and authority; apply the status and contribution-claim decision above, including saved release when exhausted.
|
|
155
196
|
5. Choose and document the next useful contribution from the remaining outcome gap, then repeat these checks before claiming it.
|
|
156
197
|
|
|
157
198
|
A starting battle plan exposes likely work, dependencies and parallel opportunities without precreating, assigning or reserving every future task. The increment owner keeps acceptance, sequence and integration clear and resolves overlap/dependencies. Explicit assignments and handoffs remain valid. Two agents sharing an account are distinct contributors. Checklists suffice for routine steps; do not create a task for every command. Task creation within assessed scope requires no fresh human approval.
|
|
158
199
|
|
|
159
|
-
**Each agent holds only one contribution task at a time**, including a blocked assignment. Finish, explicitly hand over or release the current assignment before claiming another. Do not reserve queued tasks. Outcome or increment coordination ownership does not reserve contribution tasks. Agents sharing an account remain distinct through their recorded agent/session identities.
|
|
160
|
-
|
|
161
200
|
Before declaring a contribution ready to start, complete this claim receipt: **no other contribution assignment held; parent increment; current assessed plan revision; non-overlapping scope; dependencies (or explicitly none); actual account; distinct agent/session; saved claim and reciprocal-link readback; competing-claim recheck.** Record all fields on the task, even when some are already known in conversation. Assignment does not increase authority. When explaining a proposed claim, make these required fields and the before/after overlap checks explicit.
|
|
162
201
|
|
|
163
202
|
Record scope boundaries and dependencies, then read back the claim, links and any competing claims. Issue claims are cooperative, not atomic locks: another agent may have claimed overlapping work since your first read. Reconcile that race before dependent implementation. If another contributor has claimed the same work, agree a split or handoff in the increment thread before overlapping implementation. An inactive or old claim is not permission to take over silently. If assignment is unavailable, record the intended owner and unassigned state, request the owner’s help through the agreed coordination channel when authorized, and continue only work whose ownership is clear. Never claim an assignment or board update succeeded without reading it back.
|
|
164
203
|
|
|
165
204
|
## Reconcile tracking at work checkpoints
|
|
166
205
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
cadence
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
are both
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
206
|
+
During an active work window, follow this coordination sequence while coding
|
|
207
|
+
or waiting:
|
|
208
|
+
|
|
209
|
+
1. Use the agreed, saved discussion-reading cadence. If none exists, propose a
|
|
210
|
+
bounded cadence through the authorized increment thread, obtain agreement
|
|
211
|
+
and verify its saved record. While agreement is pending, continue regular
|
|
212
|
+
bounded reads; a proposal is not agreement.
|
|
213
|
+
2. Also read new increment comments on joining/resuming and at the event
|
|
214
|
+
checkpoints below, including before dependent actions, pushes, scope or
|
|
215
|
+
ownership changes and handovers. Regular reads and event reads are both
|
|
216
|
+
required; neither replaces the other.
|
|
217
|
+
3. Answer relevant questions and handle handoffs through the authorized channel
|
|
218
|
+
and handoff rules below: actual recipient
|
|
219
|
+
acknowledgement and linked task, independent verification of returned
|
|
220
|
+
evidence, and updates to your task's evidence, dependency and next action.
|
|
221
|
+
A posted message is not the recipient's acknowledgement.
|
|
222
|
+
4. If the result materially changes the executable plan, reconcile that revision
|
|
223
|
+
and obtain the five independent reviews before dependent execution. Otherwise
|
|
224
|
+
continue within the assessed plan. Apply the claim table when work is
|
|
225
|
+
exhausted rather than retaining it for discussion reads.
|
|
226
|
+
|
|
227
|
+
These are bounded checks during active work, not a standing poller or a promise
|
|
228
|
+
to wake an idle agent. Use only already-authorized communication channels.
|
|
188
229
|
|
|
189
230
|
At each work checkpoint, reconcile tracking in this order:
|
|
190
231
|
|
|
191
|
-
|
|
192
|
-
the [
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
232
|
+
When the affected records include an outcome, current Now, provisional Next and
|
|
233
|
+
a task, and `gh` works, MUST first use the [read-only hierarchy inspector](github-project-checkpoint.md#inspect-the-hierarchy).
|
|
234
|
+
Construct its request from those actual records and consume its findings before
|
|
235
|
+
claiming completeness; identical draft/remote text is not that comparison.
|
|
236
|
+
Do not manufacture a Next issue for this route. Its configuration report is one
|
|
237
|
+
source for the selection decision below, not proof of capability or acceptance.
|
|
238
|
+
|
|
239
|
+
1. **Establish selection before checking Project capability.** Reuse the
|
|
240
|
+
established backend. From configuration, project requirements or explicit
|
|
241
|
+
direction, choose the applicable branch:
|
|
242
|
+
- **Selected/required:** verify the repository, Project and account, then
|
|
243
|
+
inspect its saved setup and applicable operations. For join/resume of an
|
|
244
|
+
active open task with working `gh`, MUST use the [executable Project checkpoint](github-project-checkpoint.md).
|
|
245
|
+
Read its inspection and handle current discussion before applying it;
|
|
246
|
+
do not manually publish synchronization-success text on that route.
|
|
247
|
+
If an applicable operation is unavailable, retain its exact pending state
|
|
248
|
+
under the recovery rules below. An unavailable API or bootstrap default
|
|
249
|
+
does not prove a missing view, field or membership.
|
|
250
|
+
- **Established none:** continue issue-side reconciliation without Project
|
|
251
|
+
setup, fields or synchronization.
|
|
252
|
+
- **Unresolved:** inspect available configuration, requirements, direction and
|
|
253
|
+
issue records. Record the selection gap and keep Project work conditional;
|
|
254
|
+
there is no established mirror operation to report pending or unsynchronized.
|
|
255
|
+
Omitted information and API availability establish neither selection nor
|
|
256
|
+
an explicit choice to use no Project.
|
|
257
|
+
2. **Inspect each affected record before classifying it.** Compare every
|
|
258
|
+
outcome, increment and task with the minimum-information table. Preserve its
|
|
259
|
+
own recorded owner/account, applicable agent/session, revision and acceptance,
|
|
260
|
+
including provisional and completed records. Mark a required value unresolved
|
|
261
|
+
only when inspection cannot establish it; omission from a scenario or summary
|
|
262
|
+
does not establish that saved information is missing. Completion evidence
|
|
263
|
+
does not replace the task's own revision or acceptance. Provisional ownership,
|
|
264
|
+
revision and tentative acceptance imply neither an executable plan nor
|
|
265
|
+
critic approval or completion evidence.
|
|
266
|
+
Record actual scope, status, increment-only Horizon, dependencies/blocker,
|
|
267
|
+
next action and state-appropriate evidence. For a selected/required Project,
|
|
268
|
+
each item's Agent remains its verified owner/session, never an identity
|
|
269
|
+
copied from its parent or child; Status reflects that item's actual work.
|
|
219
270
|
3. **Update and verify.** Make only necessary authorized changes to existing
|
|
220
271
|
records. Read back every changed issue's fields and links, checking both
|
|
221
272
|
directions of parent/dependency relationships. For a selected or required
|
|
@@ -235,7 +286,7 @@ system.
|
|
|
235
286
|
| Join, resume or start implementation | Read current records and discussion; correct stale status, scope and ownership before dependent implementation. Set the active task and increment In progress when useful work starts. Complete missing selected Project setup or record its precise unavailable operation. |
|
|
236
287
|
| Material milestone or failed verification | Record the actual result and evidence before the next dependent action. Keep In progress while useful repair remains; a failed check alone does not mean Blocked. |
|
|
237
288
|
| Scope, dependency, plan or horizon change | Update affected briefs, native relationships and increment horizons; remove superseded active horizons. Obtain the required reviews before materially revised execution. |
|
|
238
|
-
| Block, hand off, finish or yield the active work window |
|
|
289
|
+
| Block, hand off, finish or yield the active work window | Apply the claim table, saving the gap, next action/owner or acceptance evidence and verifying any required release. Reconcile the increment as well as the task; do not leave stale status or next action. |
|
|
239
290
|
|
|
240
291
|
For a selected or required Project, when an operation is unavailable, record
|
|
241
292
|
the affected view/field/item,
|
|
@@ -271,7 +322,7 @@ When an authorized owner must complete a pending Project operation, request it t
|
|
|
271
322
|
|
|
272
323
|
## Verify, learn and replan as the outcome owner
|
|
273
324
|
|
|
274
|
-
Post acceptance evidence before completing a task. Preserve its actual recorded acceptance: do not invent a later release check as a repair-task completion condition, or remove an established condition to finish early. At handoff,
|
|
325
|
+
Post acceptance evidence before completing a task. Preserve its actual recorded acceptance: do not invent a later release check as a repair-task completion condition, or remove an established condition to finish early. At handoff, apply the claim table; an explicit ownership transfer additionally needs the identified recipient's acknowledgement. Do not report both releasing and retaining the same claim. The increment owner verifies the whole increment against its criteria before closing it; task completion alone does not establish delivery. Publication, installed behavior and production/customer verification remain separate evidence stages where applicable.
|
|
275
326
|
|
|
276
327
|
After a verified increment, or earlier when evidence invalidates the plan, the outcome owner:
|
|
277
328
|
|
|
@@ -1,6 +1,72 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Inspect and reconcile GitHub records
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Resolve `scripts/github-project-checkpoint.mjs` relative to this installed
|
|
4
|
+
planning skill, including when called from `contribute`. Use the existing
|
|
5
|
+
authenticated `gh` account and saved project configuration. The default is
|
|
6
|
+
`.agents/planning.json`; an existing project-declared configuration path may be
|
|
7
|
+
supplied last. These operations require no new grants, account changes or tokens.
|
|
8
|
+
Local tracking keeps its existing path.
|
|
9
|
+
|
|
10
|
+
## Inspect the hierarchy
|
|
11
|
+
|
|
12
|
+
When reconciling an outcome, current Now, an affected provisional Next and a
|
|
13
|
+
task together with working `gh`, planning and `contribute` MUST first use the
|
|
14
|
+
read-only hierarchy inspector. Supply those actual distinct issue numbers;
|
|
15
|
+
do not invent a Next issue to satisfy the command. Other record sets retain
|
|
16
|
+
their existing coordination path.
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"outcome": 1,
|
|
21
|
+
"increment": {"issue": 2},
|
|
22
|
+
"next": {"issue": 3},
|
|
23
|
+
"task": {"issue": 4}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Run `node <installed-planning-skill>/scripts/github-project-checkpoint.mjs inspect-hierarchy request.json`.
|
|
28
|
+
This reads the four actual issues and their returned comments. It writes
|
|
29
|
+
nothing and makes no Project or native-link request. Read the raw records and
|
|
30
|
+
consume `findings` before claiming that the records are correct:
|
|
31
|
+
|
|
32
|
+
- `projectSelection` reports configuration facts. `not-recorded` means selection
|
|
33
|
+
is unresolved from that configuration, not an explicit choice to use no
|
|
34
|
+
Project. `recorded` does not prove capability; consider actual project
|
|
35
|
+
requirements and explicit direction too. Preserve invalid configuration.
|
|
36
|
+
- Each record's `inspection` reports literal owner, revision, acceptance and
|
|
37
|
+
Parent candidates with raw line evidence. `candidate` is text, not verified
|
|
38
|
+
ownership or passed acceptance. `explicitly-unresolved` preserves a recorded
|
|
39
|
+
unknown. Empty/missing literals, unsupported syntax and multiple candidates
|
|
40
|
+
remain unestablished by this inspector; they do not prove semantic information
|
|
41
|
+
is absent or that the issue is invalid. Inspect the actual prose/history
|
|
42
|
+
rather than forcing a new format or choosing a historical value.
|
|
43
|
+
- `textLinks` compares the three requested textual relationships. A mention is
|
|
44
|
+
observed text, not proof of a current native relationship. Inspect both sides
|
|
45
|
+
and repair known reciprocal gaps under the existing coordination rules.
|
|
46
|
+
- `capabilities` are `not-probed`; do not turn that into an outage or native-link
|
|
47
|
+
absence. `inspection-unavailable` means the read/report operation failed,
|
|
48
|
+
not that a Project mirror is pending.
|
|
49
|
+
|
|
50
|
+
A successful command produces a diagnostic report, never a correctness or
|
|
51
|
+
synchronization verdict. Identical drafts and saved bodies do not establish
|
|
52
|
+
completeness. Before claiming completeness, account for every finding through
|
|
53
|
+
actual semantic review, authorized repair with saved readback where needed, or
|
|
54
|
+
honest unresolved recording in the existing plan or record. Follow the selection
|
|
55
|
+
finding's conditional next action, which targets the existing outcome issue
|
|
56
|
+
for saving and reading back a still-unresolved gap. Reuse an already saved gap
|
|
57
|
+
without an unchanged write. Configuration alone may leave the choice unresolved
|
|
58
|
+
while requirements or explicit direction establish it. Unsupported
|
|
59
|
+
syntax does not force normalization or another artifact.
|
|
60
|
+
Apply the existing per-record rules to known gaps, marking missing
|
|
61
|
+
required information unresolved rather than inventing it; preserve completed
|
|
62
|
+
acceptance and attribution. Read back authorized changes and compare reciprocal
|
|
63
|
+
links before reporting reconciliation. Unsupported syntax needs actual review,
|
|
64
|
+
not automatic normalization. Semantic acceptance remains with the caller and
|
|
65
|
+
required independent review.
|
|
66
|
+
|
|
67
|
+
## Synchronize selected Project fields
|
|
68
|
+
|
|
69
|
+
For a join/resume checkpoint on an active open task with a selected GitHub Project and working `gh`,
|
|
4
70
|
planning and `contribute` MUST use the bundled
|
|
5
71
|
`scripts/github-project-checkpoint.mjs` operation. Do not manually publish a
|
|
6
72
|
Project synchronization-success claim on this route. The operation reads the
|
|
@@ -8,10 +74,8 @@ records/discussion, updates the two items, verifies their saved fields and only
|
|
|
8
74
|
then generates the task's synchronization result. It does not allocate owners,
|
|
9
75
|
approve a plan, acknowledge another person or complete the increment.
|
|
10
76
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
project configuration; no new grants, account changes or tokens are required by
|
|
14
|
-
the operation. Local and GitHub Issues-only tracking keep their existing paths.
|
|
77
|
+
This mutation route applies to its open outcome, increment and active task.
|
|
78
|
+
GitHub Issues-only tracking uses no Project field mutations.
|
|
15
79
|
|
|
16
80
|
## Inspect, decide, apply
|
|
17
81
|
|
|
@@ -26,10 +26,14 @@ function json(args, input) {
|
|
|
26
26
|
if (value.errors?.length) throw new Error(value.errors.map(error => error.message).join('; '));
|
|
27
27
|
return value;
|
|
28
28
|
}
|
|
29
|
-
function
|
|
30
|
-
requireValue(config
|
|
29
|
+
function repositoryFor(config) {
|
|
30
|
+
requireValue(config?.version === 1 && config.backend === 'github', 'This operation requires the saved GitHub backend.');
|
|
31
31
|
const repository = config.github?.repository;
|
|
32
|
-
requireValue(typeof repository === 'string' && /^[
|
|
32
|
+
requireValue(typeof repository === 'string' && /^[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\/[\w.-]+$/.test(repository) && !['.', '..'].includes(repository.split('/')[1]), 'Invalid configured GitHub repository.');
|
|
33
|
+
return repository;
|
|
34
|
+
}
|
|
35
|
+
function scope(request, config) {
|
|
36
|
+
const repository = repositoryFor(config);
|
|
33
37
|
const url = new URL(config.github?.projectUrl);
|
|
34
38
|
const match = url.pathname.match(/^\/(?:users|orgs)\/([\w.-]+)\/projects\/([1-9]\d*)(?:\/views\/[1-9]\d*)?\/?$/);
|
|
35
39
|
requireValue(url.protocol === 'https:' && url.hostname === 'github.com' && match && !url.username && !url.password, 'A selected GitHub Project URL is required.');
|
|
@@ -44,6 +48,66 @@ function scope(request, config) {
|
|
|
44
48
|
function issue(number, bound) {
|
|
45
49
|
return json(['issue', 'view', String(number), '--repo', bound.repository, '--json', 'number,url,body,state,assignees,labels,comments']);
|
|
46
50
|
}
|
|
51
|
+
function briefField(body, pattern, cue) {
|
|
52
|
+
// shortcut: observed literal brief fields only; extend when an actual brief needs another syntax.
|
|
53
|
+
const lines = body.split(/\r?\n/).map((text, index) => ({ line: index + 1, text }));
|
|
54
|
+
const matches = lines.flatMap(line => {
|
|
55
|
+
const match = line.text.match(pattern);
|
|
56
|
+
return match ? [{ ...line, value: match[1].trim() }] : [];
|
|
57
|
+
});
|
|
58
|
+
const literalEvidence = matches.map(({ line, text }) => ({ line, text }));
|
|
59
|
+
if (matches.length > 1) return { state: 'multiple-candidates', evidence: literalEvidence };
|
|
60
|
+
if (matches.length === 1) {
|
|
61
|
+
const { value } = matches[0];
|
|
62
|
+
return { state: !value ? 'empty' : /^(?:unresolved|unknown|tbd|unclaimed)(?:\b|$)/i.test(value) ? 'explicitly-unresolved' : 'candidate', value, evidence: literalEvidence };
|
|
63
|
+
}
|
|
64
|
+
const evidence = lines.filter(line => cue.test(line.text));
|
|
65
|
+
return { state: evidence.length ? 'unsupported-format' : 'literal-field-missing', evidence };
|
|
66
|
+
}
|
|
67
|
+
function textReference(body, number, repository) {
|
|
68
|
+
const escaped = repository.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
69
|
+
const reference = new RegExp(`(?:(?<![\\w./#:-])#${number}\\b|https://github\\.com/${escaped}/issues/${number}(?![\\w/]))`, 'i');
|
|
70
|
+
const evidence = body.split(/\r?\n/).flatMap((text, index) => reference.test(text) ? [{ line: index + 1, text }] : []);
|
|
71
|
+
return { observed: evidence.length > 0, evidence };
|
|
72
|
+
}
|
|
73
|
+
function inspectHierarchy(request, config) {
|
|
74
|
+
const repository = repositoryFor(config);
|
|
75
|
+
const roles = { outcome: request?.outcome, increment: request?.increment?.issue, next: request?.next?.issue, task: request?.task?.issue };
|
|
76
|
+
requireValue(Object.values(roles).every(n => Number.isSafeInteger(n) && n > 0) && new Set(Object.values(roles)).size === 4, 'Four distinct outcome, increment, next and task issue numbers are required.');
|
|
77
|
+
const projectSelection = { state: 'not-recorded', source: 'configuration' };
|
|
78
|
+
if (Object.hasOwn(config.github, 'projectUrl')) {
|
|
79
|
+
try {
|
|
80
|
+
const url = new URL(config.github.projectUrl);
|
|
81
|
+
requireValue(url.protocol === 'https:' && url.hostname === 'github.com' && !url.username && !url.password && !url.search && !url.hash && /^\/(?:users|orgs)\/[\w.-]+\/projects\/[1-9]\d*(?:\/views\/[1-9]\d*)?\/?$/.test(url.pathname), 'Invalid recorded Project URL.');
|
|
82
|
+
Object.assign(projectSelection, { state: 'recorded', url: `https://github.com${url.pathname.split('/views/')[0].replace(/\/$/, '')}` });
|
|
83
|
+
} catch { projectSelection.state = 'invalid'; }
|
|
84
|
+
}
|
|
85
|
+
const records = {};
|
|
86
|
+
const findings = projectSelection.state === 'recorded' ? [] : [{ issue: roles.outcome, field: 'projectSelection', state: projectSelection.state, nextAction: `Establish selection from applicable project requirements and explicit direction. If it remains unresolved, save that selection gap and conditional Project work on outcome #${roles.outcome} and read back its saved body before claiming reconciliation complete. Reuse an already saved gap without an unchanged write.` }];
|
|
87
|
+
for (const [role, number] of Object.entries(roles)) {
|
|
88
|
+
const record = issue(number, { repository });
|
|
89
|
+
requireValue(record.number === number && record.url?.toLowerCase() === `https://github.com/${repository}/issues/${number}`.toLowerCase() && typeof record.body === 'string', 'Returned issue does not match its requested repository/number or brief.');
|
|
90
|
+
const inspection = {
|
|
91
|
+
owner: briefField(record.body, /^\s*(?:(?:Outcome|Increment|Task) )?Owner:\s*(.*)$/i, /\bowner\b/i),
|
|
92
|
+
revision: briefField(record.body, /^\s*Revision:\s*(.*)$/i, /\brevision\b/i),
|
|
93
|
+
acceptance: briefField(record.body, /^\s*(?:Tentative )?Acceptance(?: criteria| evidence)?:\s*(.*)$/i, /\bacceptance\b/i),
|
|
94
|
+
parent: briefField(record.body, /^\s*Parent(?: outcome| increment)?:\s*(.*)$/i, /\bparent\b/i)
|
|
95
|
+
};
|
|
96
|
+
records[role] = { ...record, inspection };
|
|
97
|
+
for (const field of ['owner', 'revision', 'acceptance']) {
|
|
98
|
+
if (!['candidate', 'explicitly-unresolved'].includes(inspection[field].state)) findings.push({ issue: number, field, state: inspection[field].state });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const textLinks = [[records.outcome, records.increment], [records.outcome, records.next], [records.increment, records.task]].map(([parent, child]) => {
|
|
102
|
+
const parentMentionsChild = textReference(parent.body, child.number, repository);
|
|
103
|
+
const field = child.inspection.parent;
|
|
104
|
+
const referencesExpected = 'value' in field ? textReference(field.value, parent.number, repository).observed : null;
|
|
105
|
+
if (!parentMentionsChild.observed) findings.push({ issue: parent.number, field: 'child-text-reference', state: 'not-established', child: child.number });
|
|
106
|
+
if (referencesExpected !== true) findings.push({ issue: child.number, field: 'parent-text-reference', state: 'not-established', parent: parent.number });
|
|
107
|
+
return { parent: parent.number, child: child.number, parentMentionsChild, childParent: { ...field, referencesExpected } };
|
|
108
|
+
});
|
|
109
|
+
return { repository, projectSelection, capabilities: { project: 'not-probed', nativeLinks: 'not-probed' }, records, textLinks, findings };
|
|
110
|
+
}
|
|
47
111
|
function items(request, bound, projectId) {
|
|
48
112
|
const response = json(['api', 'graphql', '--input', '-'], JSON.stringify({ query: itemQuery, variables: { ids: [request.increment.itemId, request.task.itemId], agentFieldId: request.agentFieldId } }));
|
|
49
113
|
requireValue(response.data.agentField?.dataType === 'TEXT', 'The Agent field must be a text field.');
|
|
@@ -125,18 +189,20 @@ function apply(request, inspection, config) {
|
|
|
125
189
|
}
|
|
126
190
|
|
|
127
191
|
if (process.argv[2] === '--help') {
|
|
128
|
-
console.log('
|
|
192
|
+
console.log('Hierarchy: node github-project-checkpoint.mjs inspect-hierarchy REQUEST.json [CONFIG.json]\nInspect: node github-project-checkpoint.mjs inspect REQUEST.json [CONFIG.json]\nApply: node github-project-checkpoint.mjs apply REQUEST.json INSPECTION.json [CONFIG.json]');
|
|
129
193
|
} else {
|
|
130
194
|
try {
|
|
131
195
|
const [mode, requestPath, third, fourth] = process.argv.slice(2);
|
|
132
|
-
requireValue(
|
|
196
|
+
requireValue(['inspect', 'apply', 'inspect-hierarchy'].includes(mode), 'Expected inspect-hierarchy, inspect or apply; use --help for usage.');
|
|
133
197
|
const request = load(requestPath);
|
|
134
|
-
const config = load((mode === '
|
|
135
|
-
const result = mode === 'inspect' ? inspect(request, config) : apply(request, load(third), config);
|
|
198
|
+
const config = load((mode === 'apply' ? fourth : third) || '.agents/planning.json');
|
|
199
|
+
const result = mode === 'inspect-hierarchy' ? inspectHierarchy(request, config) : mode === 'inspect' ? inspect(request, config) : apply(request, load(third), config);
|
|
136
200
|
console.log(JSON.stringify(result));
|
|
137
201
|
if (result.status && result.status !== 'synchronized') process.exitCode = 1;
|
|
138
202
|
} catch (error) {
|
|
139
|
-
console.log(JSON.stringify(
|
|
203
|
+
console.log(JSON.stringify(process.argv[2] === 'inspect-hierarchy'
|
|
204
|
+
? { status: 'inspection-unavailable', reason: error.message, nextAction: 'Read the affected configuration or record before claiming a completed inspection.' }
|
|
205
|
+
: { status: 'pending', reason: error.message, nextAction: 'Inspect the affected record and resolve this operation before claiming synchronization.' }));
|
|
140
206
|
process.exitCode = 1;
|
|
141
207
|
}
|
|
142
208
|
}
|