mandrel 1.72.0 → 1.74.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/.agents/README.md +9 -5
- package/.agents/docs/configuration.md +13 -0
- package/.agents/instructions.md +14 -6
- package/.agents/personas/devops-engineer.md +4 -2
- package/.agents/scripts/agents-bootstrap-github.js +42 -43
- package/.agents/scripts/bootstrap.js +79 -11
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +430 -0
- package/.agents/scripts/lib/bootstrap/manifest.js +13 -5
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +43 -4
- package/.agents/scripts/lib/bootstrap/prompt.js +1 -1
- package/.agents/scripts/lib/bootstrap/summary.js +0 -6
- package/.agents/scripts/lib/bootstrap/workflow-audit.js +25 -12
- package/.agents/scripts/lib/label-taxonomy.js +0 -37
- package/.agents/scripts/lib/onboard/init-tail.js +9 -10
- package/.agents/scripts/lib/orchestration/column-sync.js +22 -41
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +56 -2
- package/.agents/scripts/lib/orchestration/project-meta-resolver.js +129 -0
- package/.agents/scripts/lib/story-body/story-body.js +5 -2
- package/.agents/scripts/lib/story-plan.js +41 -4
- package/.agents/scripts/lint-issue-body.js +261 -0
- package/.agents/scripts/providers/github/project-board.js +5 -9
- package/.agents/scripts/providers/github/projects-v2-graphql.js +0 -166
- package/.agents/scripts/providers/github/tickets.js +10 -1
- package/.agents/scripts/providers/github.js +0 -1
- package/.agents/skills/core/documentation-and-adrs/SKILL.md +38 -2
- package/.agents/templates/docs/architecture.md +4 -1
- package/.agents/templates/docs/decisions/_template.md +35 -0
- package/.agents/templates/docs/decisions.index.md +49 -0
- package/.agents/templates/docs/decisions.md +11 -0
- package/.agents/workflows/helpers/plan-story.md +1 -1
- package/docs/CHANGELOG.md +22 -0
- package/package.json +1 -1
package/.agents/README.md
CHANGED
|
@@ -33,7 +33,7 @@ It then shows a **two-option prompt**:
|
|
|
33
33
|
|
|
34
34
|
1. **Configure now** — runs `node .agents/scripts/bootstrap.js`, forwarding any
|
|
35
35
|
passthrough flags unchanged, to wire the project and GitHub side (creates the
|
|
36
|
-
GitHub repo
|
|
36
|
+
GitHub repo; board decoration and Issue Forms are opt-in — see below).
|
|
37
37
|
2. **Just the files** — stops after materialization and prints a re-run hint
|
|
38
38
|
(`mandrel init`) so you can configure later.
|
|
39
39
|
|
|
@@ -100,9 +100,13 @@ The bootstrap pipeline, in order:
|
|
|
100
100
|
`.claude/commands/` tree so every `/<command>` loads), wires the system
|
|
101
101
|
prompt (see below), gitignores derived artefacts, and runs the
|
|
102
102
|
quality-gates installer.
|
|
103
|
-
4. **GitHub-side mutations.** Creates the label taxonomy,
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
4. **GitHub-side mutations.** Creates the label taxonomy, branch protection,
|
|
104
|
+
and merge-method settings. Skipped with `--skip-github`. Two additional
|
|
105
|
+
mutations are **opt-in** (prompted y/N, defaulting No, or passed as flags):
|
|
106
|
+
- `--with-project-board` — provision the Projects V2 Status field and
|
|
107
|
+
custom fields on an existing board.
|
|
108
|
+
- `--with-issue-forms` — generate `.github/ISSUE_TEMPLATE/story.yml` and
|
|
109
|
+
`epic.yml` from the ticket-body schema.
|
|
106
110
|
|
|
107
111
|
The bootstrap is idempotent — safe to re-run; an already-configured
|
|
108
112
|
clone produces zero file mutations.
|
|
@@ -184,7 +188,7 @@ Reverses a recorded install using the install ledger
|
|
|
184
188
|
(`.agents/.install-manifest.json`). Each ledger entry is a
|
|
185
189
|
mutation-manifest record; uninstall walks reversible entries and undoes
|
|
186
190
|
exactly what the install applied, without touching pre-existing operator
|
|
187
|
-
content. GitHub-side state (labels, branch protection,
|
|
191
|
+
content. GitHub-side state (labels, branch protection, project board fields)
|
|
188
192
|
requires manual reversal and is surfaced as a follow-up checklist.
|
|
189
193
|
|
|
190
194
|
```bash
|
|
@@ -358,6 +358,19 @@ Read with `getCommands(config)` — see
|
|
|
358
358
|
| ------------------ | -------- | ------- | -------------------------------------------------------------------------------------------------- |
|
|
359
359
|
| `docsContextFiles` | No | `[]` | Files the context-hydration engine includes when assembling agent prompts. Resolved against `paths.docsRoot`. |
|
|
360
360
|
|
|
361
|
+
> **Entries are plain filenames, not globs.** Each entry is resolved as a
|
|
362
|
+
> single file under `paths.docsRoot`; the loader does **not** expand glob
|
|
363
|
+
> patterns. This matters for the decisions log: when a project adopts the
|
|
364
|
+
> index + `decisions/` ADR-directory layout (see
|
|
365
|
+
> [`documentation-and-adrs`](../skills/core/documentation-and-adrs/SKILL.md)),
|
|
366
|
+
> the **index** `decisions.md` stays the mandatory-read and the per-ADR bodies
|
|
367
|
+
> under `decisions/` are link-followed on demand — **index-only by default**.
|
|
368
|
+
> Auto-loading every ADR body into each task's context would reintroduce the
|
|
369
|
+
> bloat the directory split exists to remove. A project that genuinely wants
|
|
370
|
+
> the full ADR set in mandatory context must opt in by listing the individual
|
|
371
|
+
> ADR files explicitly (one filename per entry); there is no built-in
|
|
372
|
+
> `decisions/*.md` glob.
|
|
373
|
+
|
|
361
374
|
---
|
|
362
375
|
|
|
363
376
|
## `github`
|
package/.agents/instructions.md
CHANGED
|
@@ -86,11 +86,13 @@ apply by checking the `.agents/rules/` directory (e.g.,
|
|
|
86
86
|
### G. Structured Configuration
|
|
87
87
|
|
|
88
88
|
Refer to `.agentrc.json` to understand your operational limits (e.g., allowed
|
|
89
|
-
auto-run permissions, default personas).
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
auto-run permissions, default personas). For the project's specific
|
|
90
|
+
technology choices (database, ORM, API framework, auth provider, validation
|
|
91
|
+
library, workspace paths), refer to the project's Tech Stack inventory: a
|
|
92
|
+
dedicated `docs/tech-stack.md` when present (the single-ownership convention),
|
|
93
|
+
otherwise the **Tech Stack** section of `docs/architecture.md` (a numbered or
|
|
94
|
+
decorated heading such as `## 1. Tech Stack` is fine). Project-specific
|
|
95
|
+
technology context is intentionally kept out of `.agentrc.json`.
|
|
94
96
|
|
|
95
97
|
### H. Observability & Friction Telemetry
|
|
96
98
|
|
|
@@ -240,7 +242,13 @@ stops.
|
|
|
240
242
|
data dictionary, decisions log, patterns, etc.) and replaces any
|
|
241
243
|
hardcoded filename list. Resolve each entry against
|
|
242
244
|
`project.paths.docsRoot` (default `docs/`) and skip silently
|
|
243
|
-
when an entry's file is absent.
|
|
245
|
+
when an entry's file is absent. The decisions log (`decisions.md`) may
|
|
246
|
+
be either a single-file dated-entry log or an **index** into a
|
|
247
|
+
`decisions/` ADR directory — both are first-class layouts (see
|
|
248
|
+
[`skills/core/documentation-and-adrs`](skills/core/documentation-and-adrs/SKILL.md)).
|
|
249
|
+
When it is an index, only the index is the mandatory-read; the
|
|
250
|
+
per-ADR bodies under `decisions/` are link-followed on demand
|
|
251
|
+
(index-only by default), not auto-loaded into every task's context.
|
|
244
252
|
- **Conditional Reads**: When the task touches UI copy, layout, or
|
|
245
253
|
routing and the corresponding file is present in the project, also
|
|
246
254
|
read `docs/style-guide.md` and `docs/web-routes.md`. Skip both when
|
|
@@ -14,8 +14,10 @@ express it through code or documented configuration files.
|
|
|
14
14
|
|
|
15
15
|
1. **Read Context:** Before making any infrastructure changes, analyze the
|
|
16
16
|
existing CI/CD, deployment, and security configurations.
|
|
17
|
-
2. **Follow Protocols:** Adhere strictly to the
|
|
18
|
-
`docs/
|
|
17
|
+
2. **Follow Protocols:** Adhere strictly to the project's Tech Stack
|
|
18
|
+
inventory — a dedicated `docs/tech-stack.md` when present, otherwise the
|
|
19
|
+
**Tech Stack** section of `docs/architecture.md` — and the `orchestration`
|
|
20
|
+
block of `.agentrc.json`.
|
|
19
21
|
3. **Validate Always:** For every task, determine how the change will be
|
|
20
22
|
monitored and validated (logs, health checks, or test gates).
|
|
21
23
|
|
|
@@ -43,7 +43,6 @@ import { Logger } from './lib/Logger.js';
|
|
|
43
43
|
import {
|
|
44
44
|
LABEL_TAXONOMY,
|
|
45
45
|
PROJECT_FIELD_DEFS,
|
|
46
|
-
PROJECT_VIEW_DEFS,
|
|
47
46
|
STATUS_FIELD_OPTIONS,
|
|
48
47
|
} from './lib/label-taxonomy.js';
|
|
49
48
|
import { createProvider } from './lib/provider-factory.js';
|
|
@@ -154,25 +153,6 @@ async function ensureStatusField(provider, log) {
|
|
|
154
153
|
}
|
|
155
154
|
}
|
|
156
155
|
|
|
157
|
-
async function ensureViews(provider, log) {
|
|
158
|
-
try {
|
|
159
|
-
const views = await provider.ensureProjectViews(PROJECT_VIEW_DEFS);
|
|
160
|
-
if (views.unavailable) {
|
|
161
|
-
log(
|
|
162
|
-
`[Bootstrap] Projects V2 Views unavailable — skipped ${views.skipped.join(', ')}.${views.error ? ` (${views.error})` : ''} ${PROJECTS_DOC_POINTER}`,
|
|
163
|
-
);
|
|
164
|
-
} else {
|
|
165
|
-
log(
|
|
166
|
-
`[Bootstrap] Views — created: ${views.created.length}, skipped: ${views.skipped.length}`,
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
return views;
|
|
170
|
-
} catch (err) {
|
|
171
|
-
log(`[Bootstrap] Views provisioning failed: ${err.message}`);
|
|
172
|
-
return { created: [], skipped: [], unavailable: false };
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
156
|
/**
|
|
177
157
|
* Audit the project's built-in workflows and, when explicitly opted-in
|
|
178
158
|
* via `--reap-conflicting-workflows`, delete the ones that race against
|
|
@@ -283,10 +263,15 @@ async function ensureProjectFields(provider, project, log) {
|
|
|
283
263
|
* github?: object,
|
|
284
264
|
* baseBranch?: string,
|
|
285
265
|
* githubAdminApproved?: boolean,
|
|
266
|
+
* withProjectBoard?: boolean,
|
|
286
267
|
* isTTY?: boolean,
|
|
287
268
|
* }} [opts] - `githubAdminApproved` MUST be `true` for any GitHub mutation to
|
|
288
269
|
* occur; any other value (absent / `false`) is treated as "not approved"
|
|
289
270
|
* and the run is a verified no-op.
|
|
271
|
+
* `withProjectBoard` (default `false`) — opt-in for Projects V2 board,
|
|
272
|
+
* Status field, custom fields, and workflow audit. When absent or `false`,
|
|
273
|
+
* the board decoration is skipped and only labels + branch protection +
|
|
274
|
+
* merge methods are provisioned.
|
|
290
275
|
*/
|
|
291
276
|
export async function runBootstrap(config, opts = {}) {
|
|
292
277
|
// Explicit opt-in gate (Story #3526). Default-deny: absent or non-`true`
|
|
@@ -316,36 +301,46 @@ export async function runBootstrap(config, opts = {}) {
|
|
|
316
301
|
log('[Bootstrap] API access verified.');
|
|
317
302
|
|
|
318
303
|
const labels = await ensureLabels(provider, log);
|
|
319
|
-
const project = await resolveProject(provider, providerConfig, log);
|
|
320
304
|
|
|
321
|
-
|
|
305
|
+
// Board decoration (Projects V2 board, Status field, custom fields, workflow
|
|
306
|
+
// audit) is opt-in and defaults OFF. Minimal install = labels only. Gate is
|
|
307
|
+
// `opts.withProjectBoard === true`; absent or false skips all board work.
|
|
308
|
+
// ColumnSync already soft-noops when projectNumber is unset (column-sync.js:19-23).
|
|
309
|
+
const projectBoard = opts.withProjectBoard === true;
|
|
310
|
+
let project = { projectNumber: null, created: false, skipped: true };
|
|
322
311
|
let statusField = { status: 'skipped', added: [] };
|
|
323
|
-
let views = { created: [], skipped: [], unavailable: false };
|
|
324
312
|
let fields = { created: [], skipped: [] };
|
|
313
|
+
let workflowAudit = {
|
|
314
|
+
skipped: true,
|
|
315
|
+
reason: 'board-decoration-not-opted-in',
|
|
316
|
+
};
|
|
325
317
|
|
|
326
|
-
if (
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
// read-only).
|
|
341
|
-
const workflowAudit = projectReady
|
|
342
|
-
? await auditAndOptionallyReapWorkflows(
|
|
318
|
+
if (projectBoard) {
|
|
319
|
+
project = await resolveProject(provider, providerConfig, log);
|
|
320
|
+
const projectReady = !project.skipped && project.projectNumber;
|
|
321
|
+
if (projectReady) {
|
|
322
|
+
statusField = await ensureStatusField(provider, log);
|
|
323
|
+
fields = await ensureProjectFields(provider, project, log);
|
|
324
|
+
// Story #2845 — audit project workflows for the ones that race against
|
|
325
|
+
// the orchestrator's ColumnSync writes (notably `Pull request merged`
|
|
326
|
+
// and `Pull request linked to issue`, which both rewrite Status as a
|
|
327
|
+
// side-effect of auto-merge). When `--reap-conflicting-workflows` is
|
|
328
|
+
// set, also delete the offenders via `deleteProjectV2Workflow` (the
|
|
329
|
+
// only programmatic action GraphQL exposes today — `enabled` is
|
|
330
|
+
// read-only).
|
|
331
|
+
workflowAudit = await auditAndOptionallyReapWorkflows(
|
|
343
332
|
provider,
|
|
344
333
|
project.projectNumber,
|
|
345
334
|
opts.reapConflictingWorkflows === true,
|
|
346
335
|
log,
|
|
347
|
-
)
|
|
348
|
-
|
|
336
|
+
);
|
|
337
|
+
} else {
|
|
338
|
+
log('[Bootstrap] No active project — skipping project-field setup.');
|
|
339
|
+
workflowAudit = { skipped: true, reason: 'no-project' };
|
|
340
|
+
}
|
|
341
|
+
} else {
|
|
342
|
+
log('[Bootstrap] Project board decoration skipped (opt-in not set).');
|
|
343
|
+
}
|
|
349
344
|
|
|
350
345
|
// Consumer-facing bootstrap promotes the framework's CI-gates-only
|
|
351
346
|
// stance: branch protection with enforce_admins + 0-approval-count and
|
|
@@ -405,7 +400,6 @@ export async function runBootstrap(config, opts = {}) {
|
|
|
405
400
|
fields,
|
|
406
401
|
project,
|
|
407
402
|
statusField,
|
|
408
|
-
views,
|
|
409
403
|
workflowAudit,
|
|
410
404
|
branchProtection,
|
|
411
405
|
mergeMethods,
|
|
@@ -490,6 +484,10 @@ async function main() {
|
|
|
490
484
|
// invocation never silently reconfigures branch protection or merge methods.
|
|
491
485
|
const githubAdminApproved =
|
|
492
486
|
assumeYes || process.argv.includes('--approve-github-admin');
|
|
487
|
+
// Story #4234 — Board decoration is opt-in (default off). Pass
|
|
488
|
+
// `--with-project-board` to also provision the Projects V2 board, Status
|
|
489
|
+
// field, and custom fields.
|
|
490
|
+
const withProjectBoard = process.argv.includes('--with-project-board');
|
|
493
491
|
|
|
494
492
|
try {
|
|
495
493
|
const result = await runBootstrap(config, {
|
|
@@ -499,6 +497,7 @@ async function main() {
|
|
|
499
497
|
assumeNo,
|
|
500
498
|
reapConflictingWorkflows,
|
|
501
499
|
githubAdminApproved,
|
|
500
|
+
withProjectBoard,
|
|
502
501
|
});
|
|
503
502
|
// A non-approved run returns the skip envelope (no full result shape);
|
|
504
503
|
// the skip line is already logged inside runBootstrap, so render the
|
|
@@ -37,8 +37,16 @@
|
|
|
37
37
|
* (labels, Projects V2, branch protection, merge
|
|
38
38
|
* methods) without accepting every other default.
|
|
39
39
|
* --skip-github Skip the GitHub-side bootstrap entirely
|
|
40
|
-
* --
|
|
40
|
+
* --with-quality Opt-in: install local quality gates (pre-commit
|
|
41
|
+
* hook + quality:preview/watch scripts). Off by
|
|
42
|
+
* default — prompted y/N.
|
|
41
43
|
* --dry-run Collect info and print the plan; change nothing
|
|
44
|
+
* --with-project-board Opt-in: provision the Projects V2 Status field
|
|
45
|
+
* and custom fields. Off by default — the project
|
|
46
|
+
* board object is still created when a project
|
|
47
|
+
* name is supplied, but decoration is skipped.
|
|
48
|
+
* --with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml
|
|
49
|
+
* and epic.yml. Off by default.
|
|
42
50
|
* --reap-conflicting-workflows Delete Projects V2 built-in workflows that
|
|
43
51
|
* race against the orchestrator (destructive)
|
|
44
52
|
* --help Print this help
|
|
@@ -97,8 +105,14 @@ Flags:
|
|
|
97
105
|
(labels, Projects V2, branch protection, merge
|
|
98
106
|
methods) without accepting every other default.
|
|
99
107
|
--skip-github Skip the GitHub-side bootstrap entirely
|
|
100
|
-
--
|
|
108
|
+
--with-quality Opt-in: install local quality gates (pre-commit
|
|
109
|
+
hook + quality:preview/watch scripts).
|
|
110
|
+
(default: off — prompted y/N).
|
|
101
111
|
--dry-run Collect info and print the plan; change nothing
|
|
112
|
+
--with-project-board Opt-in: provision the Projects V2 Status field
|
|
113
|
+
and custom fields (default: off — prompted y/N).
|
|
114
|
+
--with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml
|
|
115
|
+
and epic.yml (default: off — prompted y/N).
|
|
102
116
|
--reap-conflicting-workflows Delete Projects V2 built-in workflows that
|
|
103
117
|
race against the orchestrator (destructive)
|
|
104
118
|
--help Print this help
|
|
@@ -157,16 +171,24 @@ export function resolveOwnerForPicker(defaults, flags, env = process.env) {
|
|
|
157
171
|
return null;
|
|
158
172
|
}
|
|
159
173
|
|
|
160
|
-
/**
|
|
161
|
-
|
|
162
|
-
|
|
174
|
+
/**
|
|
175
|
+
* Ask a yes/no question. `defaultAnswer` controls the default when the
|
|
176
|
+
* operator presses Enter without typing (true = Y/n, false = y/N). In
|
|
177
|
+
* non-interactive mode the default is returned immediately.
|
|
178
|
+
*/
|
|
179
|
+
async function confirmYesNo(message, interactive, defaultAnswer = true) {
|
|
180
|
+
if (!interactive) return defaultAnswer;
|
|
163
181
|
const rl = readline.createInterface({
|
|
164
182
|
input: process.stdin,
|
|
165
183
|
output: process.stdout,
|
|
166
184
|
});
|
|
167
185
|
try {
|
|
168
|
-
const
|
|
169
|
-
|
|
186
|
+
const hint = defaultAnswer ? '[Y/n]' : '[y/N]';
|
|
187
|
+
const raw = (await rl.question(`${message} ${hint}: `))
|
|
188
|
+
.trim()
|
|
189
|
+
.toLowerCase();
|
|
190
|
+
if (raw === '') return defaultAnswer;
|
|
191
|
+
return raw === 'y' || raw === 'yes';
|
|
170
192
|
} finally {
|
|
171
193
|
rl.close();
|
|
172
194
|
}
|
|
@@ -688,6 +710,9 @@ async function runGithubBootstrap(answers, opts) {
|
|
|
688
710
|
// interactive operator confirmation, `--assume-yes`, or
|
|
689
711
|
// `--approve-github-admin`. Default-deny at the boundary gate when absent.
|
|
690
712
|
githubAdminApproved: opts.githubAdminApproved === true,
|
|
713
|
+
// Opt-in: provision Status field + custom fields on the project board.
|
|
714
|
+
// Default off — prompted y/N during collect/confirm or via --with-project-board.
|
|
715
|
+
withProjectBoard: opts.withProjectBoard === true,
|
|
691
716
|
// Opt-in: delete the Projects V2 built-in workflows that race against the
|
|
692
717
|
// orchestrator's ColumnSync (e.g. "Pull request merged"). Off by default.
|
|
693
718
|
reapConflictingWorkflows: Boolean(opts.reapConflictingWorkflows),
|
|
@@ -1011,7 +1036,48 @@ export async function collectAndConfirm(state) {
|
|
|
1011
1036
|
return { ok: false, exit: 1 };
|
|
1012
1037
|
}
|
|
1013
1038
|
}
|
|
1014
|
-
|
|
1039
|
+
|
|
1040
|
+
// Opt-in: board decoration (Status field, custom fields). Default off.
|
|
1041
|
+
// Dry-run halts immediately after this step — resolve without prompting.
|
|
1042
|
+
let withProjectBoard = Boolean(state.flags['with-project-board']);
|
|
1043
|
+
if (!state.flags['dry-run'] && !withProjectBoard) {
|
|
1044
|
+
withProjectBoard = await confirmYesNo(
|
|
1045
|
+
'Set up project board fields (Status, custom)?',
|
|
1046
|
+
state.interactive,
|
|
1047
|
+
false,
|
|
1048
|
+
);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
// Opt-in: GitHub Issue Form templates. Default off.
|
|
1052
|
+
let withIssueForms = Boolean(state.flags['with-issue-forms']);
|
|
1053
|
+
if (!state.flags['dry-run'] && !withIssueForms) {
|
|
1054
|
+
withIssueForms = await confirmYesNo(
|
|
1055
|
+
'Generate GitHub Issue Form templates?',
|
|
1056
|
+
state.interactive,
|
|
1057
|
+
false,
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
// Opt-in: local quality gates. Default off.
|
|
1062
|
+
let withQuality = Boolean(state.flags['with-quality']);
|
|
1063
|
+
if (!state.flags['dry-run'] && !withQuality) {
|
|
1064
|
+
withQuality = await confirmYesNo(
|
|
1065
|
+
'Install local quality gates (pre-commit hook + quality:preview/watch scripts)?',
|
|
1066
|
+
state.interactive,
|
|
1067
|
+
false,
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
return {
|
|
1072
|
+
ok: true,
|
|
1073
|
+
payload: {
|
|
1074
|
+
answers,
|
|
1075
|
+
creation,
|
|
1076
|
+
withProjectBoard,
|
|
1077
|
+
withIssueForms,
|
|
1078
|
+
withQuality,
|
|
1079
|
+
},
|
|
1080
|
+
};
|
|
1015
1081
|
}
|
|
1016
1082
|
}
|
|
1017
1083
|
|
|
@@ -1157,7 +1223,8 @@ export async function executeBootstrap(state) {
|
|
|
1157
1223
|
agentRoot: state.agentRoot,
|
|
1158
1224
|
answers: state.answers,
|
|
1159
1225
|
approvedGroups,
|
|
1160
|
-
|
|
1226
|
+
withQuality: state.withQuality === true,
|
|
1227
|
+
withIssueForms: state.withIssueForms === true,
|
|
1161
1228
|
});
|
|
1162
1229
|
return { ok: true, payload: { report, approvedGroups } };
|
|
1163
1230
|
}
|
|
@@ -1210,6 +1277,7 @@ export async function executeGithubBootstrap(state) {
|
|
|
1210
1277
|
state.report.github = await runGithubBootstrap(state.answers, {
|
|
1211
1278
|
assumeYes: state.assumeYes,
|
|
1212
1279
|
githubAdminApproved: state.githubAdminApproved === true,
|
|
1280
|
+
withProjectBoard: state.withProjectBoard === true,
|
|
1213
1281
|
reapConflictingWorkflows: Boolean(
|
|
1214
1282
|
state.flags['reap-conflicting-workflows'],
|
|
1215
1283
|
),
|
|
@@ -1232,7 +1300,7 @@ export function recordLedger(state) {
|
|
|
1232
1300
|
const manifestCtx = {
|
|
1233
1301
|
answers: state.answers,
|
|
1234
1302
|
skipGithub: Boolean(state.flags['skip-github']),
|
|
1235
|
-
|
|
1303
|
+
withQuality: state.withQuality === true,
|
|
1236
1304
|
};
|
|
1237
1305
|
const entries = buildMutationManifest(manifestCtx).filter((e) =>
|
|
1238
1306
|
appliedGroups.has(e.phaseGroup),
|
|
@@ -1384,7 +1452,7 @@ export async function main(argv = process.argv.slice(2), deps = {}) {
|
|
|
1384
1452
|
`\n[Bootstrap] GitHub bootstrap failed: ${githubError}. ` +
|
|
1385
1453
|
'Project-side setup (labels are GitHub-side; the local .agentrc.json / ' +
|
|
1386
1454
|
'quality-gate / workflow files that were applied are recorded in the ' +
|
|
1387
|
-
'install ledger) completed, but the GitHub label/board/
|
|
1455
|
+
'install ledger) completed, but the GitHub label/board/protection ' +
|
|
1388
1456
|
'setup did not. Resolve the cause above (commonly `gh auth login` or a ' +
|
|
1389
1457
|
'missing repo/project scope) and re-run `mandrel bootstrap` — the run is ' +
|
|
1390
1458
|
'idempotent and will skip what already succeeded.',
|