@rasensio/aidlc-content 1.36.1 → 1.37.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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/recipes.d.ts +12 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/recipes.js +18 -0
- package/dist/recipes.js.map +1 -0
- package/package.json +1 -1
- package/resources/recipes/project-status.yml +220 -0
- package/skills/04-roadmap.md +2 -0
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { loadGlossary, getGlossaryTerm } from './glossary.js';
|
|
|
5
5
|
export { loadCapabilities, getCapabilityMap } from './capabilities.js';
|
|
6
6
|
export { loadPhases, getPhase } from './phases.js';
|
|
7
7
|
export { loadRules } from './rules.js';
|
|
8
|
+
export { loadBoardWorkflow, BOARD_WORKFLOW_PATH } from './recipes.js';
|
|
8
9
|
export { loadTutorials, getTutorial, getSeries, parseTutorialSource } from './tutorials.js';
|
|
9
10
|
export type { Skill, WorkflowTemplate, GuidanceLayer, GlossaryTerm, CapabilityMap, QuestionRendering, PhaseDefinition, Rule, CodeSample, ContentReference, TutorialStep, Tutorial, WidgetKind, WidgetReference } from './types.js';
|
|
10
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5F,YAAY,EAAE,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5F,YAAY,EAAE,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,5 +5,6 @@ export { loadGlossary, getGlossaryTerm } from './glossary.js';
|
|
|
5
5
|
export { loadCapabilities, getCapabilityMap } from './capabilities.js';
|
|
6
6
|
export { loadPhases, getPhase } from './phases.js';
|
|
7
7
|
export { loadRules } from './rules.js';
|
|
8
|
+
export { loadBoardWorkflow, BOARD_WORKFLOW_PATH } from './recipes.js';
|
|
8
9
|
export { loadTutorials, getTutorial, getSeries, parseTutorialSource } from './tutorials.js';
|
|
9
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Where the board workflow ships, inside the published package. */
|
|
2
|
+
export declare const BOARD_WORKFLOW_PATH: string;
|
|
3
|
+
/**
|
|
4
|
+
* The GitHub Actions workflow that drives a Project board's Status field from the
|
|
5
|
+
* `aidlc:<status>` labels `aidlc roadmap sync` writes (project-board-recipe).
|
|
6
|
+
*
|
|
7
|
+
* Shipped as a file and printed on demand, never installed: the user creates the
|
|
8
|
+
* `project: write` token and owns the CI. This repository runs the same file from
|
|
9
|
+
* `.github/workflows/`, and a test keeps the two identical.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadBoardWorkflow(): string;
|
|
12
|
+
//# sourceMappingURL=recipes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"AAMA,oEAAoE;AACpE,eAAO,MAAM,mBAAmB,QAAsE,CAAC;AAEvG;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
|
package/dist/recipes.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { resolve, dirname } from 'node:path';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
const CONTENT_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
5
|
+
/** Where the board workflow ships, inside the published package. */
|
|
6
|
+
export const BOARD_WORKFLOW_PATH = resolve(CONTENT_ROOT, 'resources', 'recipes', 'project-status.yml');
|
|
7
|
+
/**
|
|
8
|
+
* The GitHub Actions workflow that drives a Project board's Status field from the
|
|
9
|
+
* `aidlc:<status>` labels `aidlc roadmap sync` writes (project-board-recipe).
|
|
10
|
+
*
|
|
11
|
+
* Shipped as a file and printed on demand, never installed: the user creates the
|
|
12
|
+
* `project: write` token and owns the CI. This repository runs the same file from
|
|
13
|
+
* `.github/workflows/`, and a test keeps the two identical.
|
|
14
|
+
*/
|
|
15
|
+
export function loadBoardWorkflow() {
|
|
16
|
+
return readFileSync(BOARD_WORKFLOW_PATH, 'utf8');
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=recipes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipes.js","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAE5E,oEAAoE;AACpE,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAEvG;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,YAAY,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Drives a GitHub Project's Status field from the `aidlc:<status>` labels that
|
|
2
|
+
# `aidlc roadmap sync` maintains.
|
|
3
|
+
#
|
|
4
|
+
# Get this file with: aidlc roadmap board-workflow > .github/workflows/aidlc-project-status.yml
|
|
5
|
+
#
|
|
6
|
+
# The projection deliberately stops at issues and labels. Writing a Projects v2
|
|
7
|
+
# field needs a token with `project: write`, and the workflow-provided
|
|
8
|
+
# `GITHUB_TOKEN` cannot do it at any permission level — so the tool cannot move
|
|
9
|
+
# the board itself without every project first creating and storing a token.
|
|
10
|
+
# This workflow is the opt-in other half. The tool prints it and never installs
|
|
11
|
+
# it: the token is yours to create, and the CI is yours to own.
|
|
12
|
+
#
|
|
13
|
+
# The discovery label (`aidlc`) and the `aidlc:<status>` labels are a supported
|
|
14
|
+
# interface. Renaming or removing one is a breaking change in aidlc, announced as
|
|
15
|
+
# such, so binding automation to them is safe.
|
|
16
|
+
#
|
|
17
|
+
# Convergence over replay. A single roadmap move produces two events — the old
|
|
18
|
+
# status label removed, the new one added — and `aidlc roadmap sync` can relabel
|
|
19
|
+
# dozens of issues in one run. So this reads the issue's CURRENT labels at run
|
|
20
|
+
# time instead of trusting the event payload, and the concurrency group collapses
|
|
21
|
+
# a burst per issue to its last event. Ordering then cannot matter: whatever runs
|
|
22
|
+
# last reads the settled state. That is the same property the projection itself
|
|
23
|
+
# has, for the same reason.
|
|
24
|
+
#
|
|
25
|
+
# Not configured reads as inert; half-configured fails loudly. With no
|
|
26
|
+
# `AIDLC_PROJECT_NUMBER` variable the job is skipped entirely, so a fork or a
|
|
27
|
+
# clone never sees a red X for an integration it did not ask for. But if the
|
|
28
|
+
# number IS set and the token is missing, that is somebody's half-finished setup
|
|
29
|
+
# and it says so — the alternative is a workflow that runs green while writing
|
|
30
|
+
# nothing, which is how an automation comes to be believed.
|
|
31
|
+
#
|
|
32
|
+
# Setup:
|
|
33
|
+
# 1. Create the Status options in your Project, named to match STATUS_MAP below
|
|
34
|
+
# (or edit STATUS_MAP to match the columns you already have).
|
|
35
|
+
# 2. Create a token with `project: write` and store it as the repository secret
|
|
36
|
+
# AIDLC_PROJECT_TOKEN. A classic token needs the `project` scope; a
|
|
37
|
+
# fine-grained token can only reach projects owned by an organisation.
|
|
38
|
+
# 3. Set the repository variable AIDLC_PROJECT_NUMBER to the project's number
|
|
39
|
+
# (the digits in its URL). Optionally set AIDLC_PROJECT_OWNER if the project
|
|
40
|
+
# belongs to a different user or org than this repository, and
|
|
41
|
+
# AIDLC_DISCOVERY_LABEL if `roadmap.sync.label` renames the `aidlc` label.
|
|
42
|
+
#
|
|
43
|
+
# Needs gh 2.97.0 or later on the runner, for `gh project item-edit --url`. The
|
|
44
|
+
# workflow checks, and says so if the runner's is older.
|
|
45
|
+
|
|
46
|
+
name: Project status from AIDLC labels
|
|
47
|
+
|
|
48
|
+
on:
|
|
49
|
+
issues:
|
|
50
|
+
types: [opened, reopened, closed, labeled, unlabeled]
|
|
51
|
+
|
|
52
|
+
# Read the repository only. The Projects write travels on AIDLC_PROJECT_TOKEN,
|
|
53
|
+
# never on GITHUB_TOKEN, which cannot perform it regardless of what is granted.
|
|
54
|
+
permissions:
|
|
55
|
+
contents: read
|
|
56
|
+
issues: read
|
|
57
|
+
|
|
58
|
+
# One run per issue, latest wins. A sync that relabels thirty issues produces
|
|
59
|
+
# thirty independent groups, so they still proceed in parallel.
|
|
60
|
+
concurrency:
|
|
61
|
+
group: project-status-${{ github.event.issue.number }}
|
|
62
|
+
cancel-in-progress: true
|
|
63
|
+
|
|
64
|
+
jobs:
|
|
65
|
+
set-status:
|
|
66
|
+
# Unset variable = this repository has not opted in. Skip silently.
|
|
67
|
+
if: vars.AIDLC_PROJECT_NUMBER != ''
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
steps:
|
|
70
|
+
- name: Check the token is present
|
|
71
|
+
# Half-configured is an error, not a skip. See the header.
|
|
72
|
+
#
|
|
73
|
+
# The secret arrives through `env`, never interpolated into the script
|
|
74
|
+
# body: a `${{ secrets.* }}` inside `run:` is substituted before bash
|
|
75
|
+
# parses the line, so a token containing a quote or a backtick would
|
|
76
|
+
# either break the script or execute as part of it.
|
|
77
|
+
env:
|
|
78
|
+
TOKEN: ${{ secrets.AIDLC_PROJECT_TOKEN }}
|
|
79
|
+
run: |
|
|
80
|
+
if [ -z "${TOKEN:-}" ]; then
|
|
81
|
+
echo "::error::AIDLC_PROJECT_NUMBER is set but the AIDLC_PROJECT_TOKEN secret is missing." \
|
|
82
|
+
"Projects v2 writes need a token with 'project: write'; GITHUB_TOKEN cannot do it."
|
|
83
|
+
exit 1
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
- name: Read the issue's current labels
|
|
87
|
+
id: labels
|
|
88
|
+
env:
|
|
89
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
90
|
+
ISSUE: ${{ github.event.issue.number }}
|
|
91
|
+
REPO: ${{ github.repository }}
|
|
92
|
+
# Must match roadmap.sync.label. Without this a renamed label makes every
|
|
93
|
+
# run skip, green, having written nothing.
|
|
94
|
+
DISCOVERY: ${{ vars.AIDLC_DISCOVERY_LABEL || 'aidlc' }}
|
|
95
|
+
run: |
|
|
96
|
+
set -euo pipefail
|
|
97
|
+
# Read fresh rather than using github.event.issue.labels: a burst of
|
|
98
|
+
# relabels must converge on the settled state, not replay snapshots.
|
|
99
|
+
labels="$(gh issue view "$ISSUE" --repo "$REPO" --json labels --jq '.labels[].name')"
|
|
100
|
+
|
|
101
|
+
if ! grep -qxF "$DISCOVERY" <<<"$labels"; then
|
|
102
|
+
echo "Issue #$ISSUE does not carry the discovery label '$DISCOVERY' — not a projected item."
|
|
103
|
+
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
104
|
+
exit 0
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
status_labels="$(grep '^aidlc:' <<<"$labels" || true)"
|
|
108
|
+
count="$(grep -c . <<<"$status_labels" || true)"
|
|
109
|
+
|
|
110
|
+
if [ "$status_labels" = "" ]; then
|
|
111
|
+
# Reachable between the two events of a relabel. The run for the
|
|
112
|
+
# other event settles it; nothing to do here.
|
|
113
|
+
echo "Issue #$ISSUE carries no aidlc:<status> label yet — nothing to set."
|
|
114
|
+
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
115
|
+
exit 0
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
if [ "$count" -ne 1 ]; then
|
|
119
|
+
echo "::error::Issue #$ISSUE carries $count aidlc:<status> labels: $(tr '\n' ' ' <<<"$status_labels")." \
|
|
120
|
+
"The projection maintains exactly one. Fix the labels before the board can follow them."
|
|
121
|
+
exit 1
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
echo "Issue #$ISSUE is $status_labels"
|
|
125
|
+
echo "skip=false" >> "$GITHUB_OUTPUT"
|
|
126
|
+
echo "label=$status_labels" >> "$GITHUB_OUTPUT"
|
|
127
|
+
|
|
128
|
+
- name: Map the label to a Status option
|
|
129
|
+
id: map
|
|
130
|
+
if: steps.labels.outputs.skip == 'false'
|
|
131
|
+
env:
|
|
132
|
+
LABEL: ${{ steps.labels.outputs.label }}
|
|
133
|
+
# The one place the vocabularies are joined. Edit here if your columns
|
|
134
|
+
# are named differently.
|
|
135
|
+
STATUS_MAP: >-
|
|
136
|
+
{"aidlc:inbox":"Inbox",
|
|
137
|
+
"aidlc:backlog":"Backlog",
|
|
138
|
+
"aidlc:in-progress":"In Progress",
|
|
139
|
+
"aidlc:done":"Done",
|
|
140
|
+
"aidlc:hold":"On Hold"}
|
|
141
|
+
run: |
|
|
142
|
+
set -euo pipefail
|
|
143
|
+
value="$(jq -er --arg k "$LABEL" '.[$k]' <<<"$STATUS_MAP")" || {
|
|
144
|
+
echo "::error::No STATUS_MAP entry for $LABEL. Add one to this workflow." \
|
|
145
|
+
"A new roadmap status was added to aidlc and this map was not updated."
|
|
146
|
+
exit 1
|
|
147
|
+
}
|
|
148
|
+
echo "Target Status: $value"
|
|
149
|
+
echo "value=$value" >> "$GITHUB_OUTPUT"
|
|
150
|
+
|
|
151
|
+
- name: Check the runner's gh can edit an item by URL
|
|
152
|
+
if: steps.labels.outputs.skip == 'false'
|
|
153
|
+
run: |
|
|
154
|
+
# A feature probe, not a version compare: it tests the flag the write
|
|
155
|
+
# below uses. Without it an older runner image fails there with an
|
|
156
|
+
# unknown-flag error that names nothing useful.
|
|
157
|
+
if ! gh project item-edit --help 2>&1 | grep -q -- '--url'; then
|
|
158
|
+
echo "::error::gh $(gh --version | head -1 | awk '{print $3}') cannot edit a project item by URL." \
|
|
159
|
+
"This workflow needs gh 2.97.0 or later."
|
|
160
|
+
exit 1
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
- name: Check the Status option exists on the project
|
|
164
|
+
id: verify
|
|
165
|
+
if: steps.labels.outputs.skip == 'false'
|
|
166
|
+
env:
|
|
167
|
+
GH_TOKEN: ${{ secrets.AIDLC_PROJECT_TOKEN }}
|
|
168
|
+
NUMBER: ${{ vars.AIDLC_PROJECT_NUMBER }}
|
|
169
|
+
OWNER: ${{ vars.AIDLC_PROJECT_OWNER || github.repository_owner }}
|
|
170
|
+
WANT: ${{ steps.map.outputs.value }}
|
|
171
|
+
run: |
|
|
172
|
+
set -euo pipefail
|
|
173
|
+
# Checked before the write, so a missing column names itself and the
|
|
174
|
+
# available options instead of surfacing as an opaque gh failure.
|
|
175
|
+
fields="$(gh project field-list "$NUMBER" --owner "$OWNER" --format json --limit 100)"
|
|
176
|
+
options="$(jq -r '.fields[] | select(.name == "Status") | .options[].name' <<<"$fields")"
|
|
177
|
+
|
|
178
|
+
if [ "$options" = "" ]; then
|
|
179
|
+
echo "::error::Project $OWNER/$NUMBER has no single-select field named 'Status'." \
|
|
180
|
+
"Fields present: $(jq -r '[.fields[].name] | join(", ")' <<<"$fields")"
|
|
181
|
+
exit 1
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
if ! grep -qxF "$WANT" <<<"$options"; then
|
|
185
|
+
echo "::error::Project $OWNER/$NUMBER has no Status option named '$WANT'." \
|
|
186
|
+
"Options present: $(tr '\n' '|' <<<"$options" | sed 's/|$//; s/|/, /g')." \
|
|
187
|
+
"Create it, or change STATUS_MAP in this workflow to match your column names."
|
|
188
|
+
exit 1
|
|
189
|
+
fi
|
|
190
|
+
|
|
191
|
+
- name: Put the issue on the board
|
|
192
|
+
if: steps.labels.outputs.skip == 'false'
|
|
193
|
+
env:
|
|
194
|
+
GH_TOKEN: ${{ secrets.AIDLC_PROJECT_TOKEN }}
|
|
195
|
+
NUMBER: ${{ vars.AIDLC_PROJECT_NUMBER }}
|
|
196
|
+
OWNER: ${{ vars.AIDLC_PROJECT_OWNER || github.repository_owner }}
|
|
197
|
+
ISSUE_URL: ${{ github.event.issue.html_url }}
|
|
198
|
+
run: |
|
|
199
|
+
# Deliberately not fatal, and deliberately not silenced. An issue
|
|
200
|
+
# already on the board is the ordinary case and reports as a failure
|
|
201
|
+
# here; a genuinely broken token fails at the write below, where one
|
|
202
|
+
# loud failure is more use than two.
|
|
203
|
+
if ! out="$(gh project item-add "$NUMBER" --owner "$OWNER" --url "$ISSUE_URL" 2>&1)"; then
|
|
204
|
+
echo "item-add did not add the issue (already present, or the write below will fail):"
|
|
205
|
+
echo "$out"
|
|
206
|
+
fi
|
|
207
|
+
|
|
208
|
+
- name: Set the Status field
|
|
209
|
+
if: steps.labels.outputs.skip == 'false'
|
|
210
|
+
env:
|
|
211
|
+
GH_TOKEN: ${{ secrets.AIDLC_PROJECT_TOKEN }}
|
|
212
|
+
NUMBER: ${{ vars.AIDLC_PROJECT_NUMBER }}
|
|
213
|
+
OWNER: ${{ vars.AIDLC_PROJECT_OWNER || github.repository_owner }}
|
|
214
|
+
ISSUE_URL: ${{ github.event.issue.html_url }}
|
|
215
|
+
VALUE: ${{ steps.map.outputs.value }}
|
|
216
|
+
run: |
|
|
217
|
+
set -euo pipefail
|
|
218
|
+
gh project item-edit "$NUMBER" --owner "$OWNER" --url "$ISSUE_URL" \
|
|
219
|
+
--field Status --value "$VALUE"
|
|
220
|
+
echo "Set $ISSUE_URL to Status='$VALUE' on project $OWNER/$NUMBER."
|
package/skills/04-roadmap.md
CHANGED
|
@@ -189,4 +189,6 @@ Four things to know before you offer it:
|
|
|
189
189
|
|
|
190
190
|
Editing an item's body is therefore a publishing act on a repo with `roadmap.sync` configured. That is not a reason to hesitate, but it is a reason not to paste anything into an item you would not put on the tracker. Item prose is sanitized on the way out — HTML comments removed, `@name` and `#123` made inert — so no sync notifies anybody; secrets are not sanitized, and never were. If a user's braindump contains credentials, the existing hard rule applies: flag it and leave them out of the file.
|
|
191
191
|
|
|
192
|
+
**When the user's Project board does not move**, that is expected: the projection stops at issues and labels, because moving a board needs a `project: write` token that `GITHUB_TOKEN` cannot have. Offer `aidlc roadmap board-workflow > .github/workflows/aidlc-project-status.yml`, which prints a GitHub Actions workflow that sets each issue's Status column from its status label; its header lists the three setup steps (Status columns, the `AIDLC_PROJECT_TOKEN` secret, the `AIDLC_PROJECT_NUMBER` variable). Writing that file is the user's decision — show the command, do not run the redirect unasked. Do not offer to build board writes into `sync` instead.
|
|
193
|
+
|
|
192
194
|
`aidlc roadmap import <issue-url>` is the opposite direction, and it is one-shot: it writes one `inbox/` item with the issue linked and its executive summary left as `Not yet decided.`, which is then a normal triage. Nothing reconciles afterwards.
|