@pmelab/gtd 27.9.0 → 28.0.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/.claude-plugin/plugin.json +1 -1
- package/README.md +50 -26
- package/claude/hooks/doors.ts +12 -0
- package/claude/hooks/register.tsx +2 -4
- package/claude/hooks/ship.ts +115 -20
- package/dist/chunks/{reserved-UdSuHDUJ.mjs → reserved-BIsngMGL.mjs} +168 -27
- package/dist/chunks/{tail-fj60rQ3y.mjs → tail-DHEaOHyp.mjs} +1 -1
- package/dist/gtd.bundle.mjs +43 -15
- package/dist/testkit.mjs +43 -15
- package/dist/workflows/cleanup.mjs +3 -4
- package/dist/workflows/feature.mjs +2 -2
- package/dist/workflows/fix.mjs +2 -2
- package/dist/workflows/review.mjs +2 -2
- package/dist/workflows/rollout.mjs +19 -4
- package/dist/workflows.mjs +186 -127
- package/package.json +1 -1
- package/skills/authoring/SKILL.md +4 -3
- package/src/cli/Cli.ts +4 -4
- package/src/install/ConfigScaffold.ts +4 -1
- package/src/install/Install.test.ts +10 -0
- package/src/install/Install.ts +5 -2
- package/src/workflow/load.test.ts +82 -5
- package/src/workflow/load.ts +40 -16
- package/src/workflows/cleanup/cleanup.feature +21 -0
- package/src/workflows/cleanup/cleanup.ts +1 -1
- package/src/workflows/index.ts +2 -1
- package/src/workflows/rollout/rollout.feature +282 -2
- package/src/workflows/rollout/rollout.test.ts +96 -2
- package/src/workflows/rollout/rollout.ts +41 -3
- package/src/workflows/shared/options.test.ts +25 -2
- package/src/workflows/shared/options.ts +7 -4
- package/src/workflows/shared/registry.test.ts +41 -1
- package/src/workflows/shared/registry.ts +26 -1
- package/src/workflows/shared/text.test.ts +252 -2
- package/src/workflows/shared/text.ts +44 -1
- package/src/workflows/shared/vars.ts +2 -0
- package/dist/chunks/registry-CP3YuV9j.mjs +0 -101
package/dist/gtd.bundle.mjs
CHANGED
|
@@ -21520,8 +21520,11 @@ hands off to \`gtd-build\`, which halts at the blocked gate and prints it,
|
|
|
21520
21520
|
rather than starting the review; \`gtd-door fix\` on a GREEN suite is a no-op
|
|
21521
21521
|
straight back to \`idle\` — the exec'd \`gtd-build\` exits immediately on it.
|
|
21522
21522
|
\`gtd doors\` lists the doors a repository offers (those of the workflows its
|
|
21523
|
-
config exports — the bundled \`fix\` and \`review [base]
|
|
21524
|
-
|
|
21523
|
+
config exports — the bundled \`fix\` and \`review [base]\`, plus the opt-in
|
|
21524
|
+
\`rollout <flag>\` (turn a release flag default-on) and \`cleanup <flag>\`
|
|
21525
|
+
(remove it), which a config adds by exporting \`rollout\` from
|
|
21526
|
+
\`@pmelab/gtd/workflows/rollout\` and \`cleanup\` from
|
|
21527
|
+
\`@pmelab/gtd/workflows/cleanup\` — plus any it declares). Refuses with
|
|
21525
21528
|
\`usage: gtd-door <name> [args...]\` on stderr and exit \`2\` when the name is
|
|
21526
21529
|
missing — nothing was even attempted. Default path: \`~/.local/bin/gtd-door\`.
|
|
21527
21530
|
|
|
@@ -21631,7 +21634,10 @@ const renderBriefing = () => HEADER() + BEAT_PROTOCOL + JSON_FIELD_REFERENCE + D
|
|
|
21631
21634
|
const CONFIG_SCAFFOLD = `// The workflows gtd runs here: gtd's shipped feature, review and fix.
|
|
21632
21635
|
// Every exported function is startable with \`gtd --workflow <name>\`; the
|
|
21633
21636
|
// default export is what a change in the tree starts. Each workflow brings
|
|
21634
|
-
// its own doors: \`gtd door review [base]\` and \`gtd door fix\`.
|
|
21637
|
+
// its own doors: \`gtd door review [base]\` and \`gtd door fix\`. Export \`rollout\`
|
|
21638
|
+
// from \`@pmelab/gtd/workflows/rollout\` and \`cleanup\` from
|
|
21639
|
+
// \`@pmelab/gtd/workflows/cleanup\` to add \`gtd door rollout <flag>\` and
|
|
21640
|
+
// \`gtd door cleanup <flag>\`.
|
|
21635
21641
|
export {
|
|
21636
21642
|
feature as default,
|
|
21637
21643
|
feature,
|
|
@@ -38993,10 +38999,10 @@ const doorsFrom = (exports) => {
|
|
|
38993
38999
|
};
|
|
38994
39000
|
/**
|
|
38995
39001
|
* Each exported workflow's own doors, onto the name it is exported under. The
|
|
38996
|
-
* `doors` export adds to them and
|
|
39002
|
+
* `doors` export adds to them and declares a name several workflows clash on.
|
|
38997
39003
|
*/
|
|
38998
39004
|
const derivedDoors = (catalogue, declared) => {
|
|
38999
|
-
const
|
|
39005
|
+
const builders = /* @__PURE__ */ new Map();
|
|
39000
39006
|
for (const [workflow, loaded] of catalogue) for (const [name, spec] of Object.entries(loaded.doors ?? {})) {
|
|
39001
39007
|
const door = {
|
|
39002
39008
|
...spec,
|
|
@@ -39004,12 +39010,22 @@ const derivedDoors = (catalogue, declared) => {
|
|
|
39004
39010
|
};
|
|
39005
39011
|
const problem = doorProblem(name, door);
|
|
39006
39012
|
if (problem !== void 0) throw new Error(`workflow "${workflow}" builds door "${name}", which ${problem}`);
|
|
39007
|
-
|
|
39008
|
-
|
|
39009
|
-
|
|
39013
|
+
builders.set(name, [...builders.get(name) ?? [], door]);
|
|
39014
|
+
}
|
|
39015
|
+
const doors = /* @__PURE__ */ new Map();
|
|
39016
|
+
const clashes = /* @__PURE__ */ new Map();
|
|
39017
|
+
for (const [name, built] of builders) {
|
|
39018
|
+
const owner = ownerOf(name, built);
|
|
39019
|
+
if (owner !== void 0) doors.set(name, owner);
|
|
39020
|
+
else if (!declared.has(name)) clashes.set(name, built.map((door) => door.workflow));
|
|
39010
39021
|
}
|
|
39011
|
-
return
|
|
39022
|
+
return {
|
|
39023
|
+
doors: new Map([...doors, ...declared]),
|
|
39024
|
+
clashes
|
|
39025
|
+
};
|
|
39012
39026
|
};
|
|
39027
|
+
/** The export named after the door owns it, else the sole builder; a clash of several builds no door. */
|
|
39028
|
+
const ownerOf = (name, built) => built.find((door) => door.workflow === name) ?? (built.length === 1 ? built[0] : void 0);
|
|
39013
39029
|
/** Sort the doors and check each names a startable workflow. */
|
|
39014
39030
|
const checkDoors = (declared, catalogue) => {
|
|
39015
39031
|
const doors = new Map([...declared].sort(([a], [b]) => a.localeCompare(b)));
|
|
@@ -39040,16 +39056,28 @@ const loadWorkflows = (module, shipped) => {
|
|
|
39040
39056
|
return workflow === void 0 ? [] : [[name, workflow]];
|
|
39041
39057
|
}));
|
|
39042
39058
|
const defaultWorkflow = built.get(value);
|
|
39059
|
+
const derived = rejections.length > 0 ? {
|
|
39060
|
+
doors: /* @__PURE__ */ new Map(),
|
|
39061
|
+
clashes: /* @__PURE__ */ new Map()
|
|
39062
|
+
} : derivedDoors(catalogue, doorsFrom(exports));
|
|
39043
39063
|
return {
|
|
39044
39064
|
file,
|
|
39045
39065
|
catalogue,
|
|
39046
|
-
doors:
|
|
39066
|
+
doors: checkDoors(derived.doors, catalogue),
|
|
39047
39067
|
default: defaultWorkflow && {
|
|
39048
39068
|
...defaultWorkflow,
|
|
39049
39069
|
name: defaultName
|
|
39050
39070
|
},
|
|
39051
39071
|
config: compileConfig(exports["config"], module.filepath),
|
|
39052
|
-
diagnostics: nameRejections(rejections)
|
|
39072
|
+
diagnostics: [...nameRejections(rejections), ...[...derived.clashes].map(([name, builders]) => {
|
|
39073
|
+
const names = [...builders].sort().map((b) => JSON.stringify(b));
|
|
39074
|
+
return {
|
|
39075
|
+
severity: "warning",
|
|
39076
|
+
message: `door "${name}" is built by workflows ${names.slice(0, -1).join(", ")} and ${names.at(-1)} and none is exported under that name — declare it in the "doors" export`,
|
|
39077
|
+
path: ["doors", name],
|
|
39078
|
+
origin: file.origin
|
|
39079
|
+
};
|
|
39080
|
+
})]
|
|
39053
39081
|
};
|
|
39054
39082
|
};
|
|
39055
39083
|
const evaluateFromDisk = (module, shipped) => {
|
|
@@ -42186,10 +42214,10 @@ const COMMAND_ROWS = [
|
|
|
42186
42214
|
"positional args to that workflow's process settings — the",
|
|
42187
42215
|
"same start `gtd --workflow` makes, printed the same way.",
|
|
42188
42216
|
"Each workflow the config exports brings its own doors (gtd's",
|
|
42189
|
-
"`fix
|
|
42190
|
-
"the config's `doors` export. An
|
|
42191
|
-
"too many args, is a usage error
|
|
42192
|
-
"the door's synopsis"
|
|
42217
|
+
"`fix`, `review [base]`, `rollout <flag>` and",
|
|
42218
|
+
"`cleanup <flag>`), plus the config's `doors` export. An",
|
|
42219
|
+
"unknown door, or too few or too many args, is a usage error",
|
|
42220
|
+
"(exit 2) naming the doors or the door's synopsis"
|
|
42193
42221
|
]
|
|
42194
42222
|
},
|
|
42195
42223
|
{
|
package/dist/testkit.mjs
CHANGED
|
@@ -6647,8 +6647,11 @@ hands off to \`gtd-build\`, which halts at the blocked gate and prints it,
|
|
|
6647
6647
|
rather than starting the review; \`gtd-door fix\` on a GREEN suite is a no-op
|
|
6648
6648
|
straight back to \`idle\` — the exec'd \`gtd-build\` exits immediately on it.
|
|
6649
6649
|
\`gtd doors\` lists the doors a repository offers (those of the workflows its
|
|
6650
|
-
config exports — the bundled \`fix\` and \`review [base]
|
|
6651
|
-
|
|
6650
|
+
config exports — the bundled \`fix\` and \`review [base]\`, plus the opt-in
|
|
6651
|
+
\`rollout <flag>\` (turn a release flag default-on) and \`cleanup <flag>\`
|
|
6652
|
+
(remove it), which a config adds by exporting \`rollout\` from
|
|
6653
|
+
\`@pmelab/gtd/workflows/rollout\` and \`cleanup\` from
|
|
6654
|
+
\`@pmelab/gtd/workflows/cleanup\` — plus any it declares). Refuses with
|
|
6652
6655
|
\`usage: gtd-door <name> [args...]\` on stderr and exit \`2\` when the name is
|
|
6653
6656
|
missing — nothing was even attempted. Default path: \`~/.local/bin/gtd-door\`.
|
|
6654
6657
|
|
|
@@ -6758,7 +6761,10 @@ const renderBriefing = () => HEADER() + BEAT_PROTOCOL + JSON_FIELD_REFERENCE + D
|
|
|
6758
6761
|
const CONFIG_SCAFFOLD = `// The workflows gtd runs here: gtd's shipped feature, review and fix.
|
|
6759
6762
|
// Every exported function is startable with \`gtd --workflow <name>\`; the
|
|
6760
6763
|
// default export is what a change in the tree starts. Each workflow brings
|
|
6761
|
-
// its own doors: \`gtd door review [base]\` and \`gtd door fix\`.
|
|
6764
|
+
// its own doors: \`gtd door review [base]\` and \`gtd door fix\`. Export \`rollout\`
|
|
6765
|
+
// from \`@pmelab/gtd/workflows/rollout\` and \`cleanup\` from
|
|
6766
|
+
// \`@pmelab/gtd/workflows/cleanup\` to add \`gtd door rollout <flag>\` and
|
|
6767
|
+
// \`gtd door cleanup <flag>\`.
|
|
6762
6768
|
export {
|
|
6763
6769
|
feature as default,
|
|
6764
6770
|
feature,
|
|
@@ -8104,10 +8110,10 @@ const doorsFrom = (exports) => {
|
|
|
8104
8110
|
};
|
|
8105
8111
|
/**
|
|
8106
8112
|
* Each exported workflow's own doors, onto the name it is exported under. The
|
|
8107
|
-
* `doors` export adds to them and
|
|
8113
|
+
* `doors` export adds to them and declares a name several workflows clash on.
|
|
8108
8114
|
*/
|
|
8109
8115
|
const derivedDoors = (catalogue, declared) => {
|
|
8110
|
-
const
|
|
8116
|
+
const builders = /* @__PURE__ */ new Map();
|
|
8111
8117
|
for (const [workflow, loaded] of catalogue) for (const [name, spec] of Object.entries(loaded.doors ?? {})) {
|
|
8112
8118
|
const door = {
|
|
8113
8119
|
...spec,
|
|
@@ -8115,12 +8121,22 @@ const derivedDoors = (catalogue, declared) => {
|
|
|
8115
8121
|
};
|
|
8116
8122
|
const problem = doorProblem(name, door);
|
|
8117
8123
|
if (problem !== void 0) throw new Error(`workflow "${workflow}" builds door "${name}", which ${problem}`);
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8124
|
+
builders.set(name, [...builders.get(name) ?? [], door]);
|
|
8125
|
+
}
|
|
8126
|
+
const doors = /* @__PURE__ */ new Map();
|
|
8127
|
+
const clashes = /* @__PURE__ */ new Map();
|
|
8128
|
+
for (const [name, built] of builders) {
|
|
8129
|
+
const owner = ownerOf(name, built);
|
|
8130
|
+
if (owner !== void 0) doors.set(name, owner);
|
|
8131
|
+
else if (!declared.has(name)) clashes.set(name, built.map((door) => door.workflow));
|
|
8121
8132
|
}
|
|
8122
|
-
return
|
|
8133
|
+
return {
|
|
8134
|
+
doors: new Map([...doors, ...declared]),
|
|
8135
|
+
clashes
|
|
8136
|
+
};
|
|
8123
8137
|
};
|
|
8138
|
+
/** The export named after the door owns it, else the sole builder; a clash of several builds no door. */
|
|
8139
|
+
const ownerOf = (name, built) => built.find((door) => door.workflow === name) ?? (built.length === 1 ? built[0] : void 0);
|
|
8124
8140
|
/** Sort the doors and check each names a startable workflow. */
|
|
8125
8141
|
const checkDoors = (declared, catalogue) => {
|
|
8126
8142
|
const doors = new Map([...declared].sort(([a], [b]) => a.localeCompare(b)));
|
|
@@ -8151,16 +8167,28 @@ const loadWorkflows = (module, shipped) => {
|
|
|
8151
8167
|
return workflow === void 0 ? [] : [[name, workflow]];
|
|
8152
8168
|
}));
|
|
8153
8169
|
const defaultWorkflow = built.get(value);
|
|
8170
|
+
const derived = rejections.length > 0 ? {
|
|
8171
|
+
doors: /* @__PURE__ */ new Map(),
|
|
8172
|
+
clashes: /* @__PURE__ */ new Map()
|
|
8173
|
+
} : derivedDoors(catalogue, doorsFrom(exports));
|
|
8154
8174
|
return {
|
|
8155
8175
|
file,
|
|
8156
8176
|
catalogue,
|
|
8157
|
-
doors:
|
|
8177
|
+
doors: checkDoors(derived.doors, catalogue),
|
|
8158
8178
|
default: defaultWorkflow && {
|
|
8159
8179
|
...defaultWorkflow,
|
|
8160
8180
|
name: defaultName
|
|
8161
8181
|
},
|
|
8162
8182
|
config: compileConfig(exports["config"], module.filepath),
|
|
8163
|
-
diagnostics: nameRejections(rejections)
|
|
8183
|
+
diagnostics: [...nameRejections(rejections), ...[...derived.clashes].map(([name, builders]) => {
|
|
8184
|
+
const names = [...builders].sort().map((b) => JSON.stringify(b));
|
|
8185
|
+
return {
|
|
8186
|
+
severity: "warning",
|
|
8187
|
+
message: `door "${name}" is built by workflows ${names.slice(0, -1).join(", ")} and ${names.at(-1)} and none is exported under that name — declare it in the "doors" export`,
|
|
8188
|
+
path: ["doors", name],
|
|
8189
|
+
origin: file.origin
|
|
8190
|
+
};
|
|
8191
|
+
})]
|
|
8164
8192
|
};
|
|
8165
8193
|
};
|
|
8166
8194
|
const evaluateFromDisk = (module, shipped) => {
|
|
@@ -11284,10 +11312,10 @@ const COMMAND_ROWS = [
|
|
|
11284
11312
|
"positional args to that workflow's process settings — the",
|
|
11285
11313
|
"same start `gtd --workflow` makes, printed the same way.",
|
|
11286
11314
|
"Each workflow the config exports brings its own doors (gtd's",
|
|
11287
|
-
"`fix
|
|
11288
|
-
"the config's `doors` export. An
|
|
11289
|
-
"too many args, is a usage error
|
|
11290
|
-
"the door's synopsis"
|
|
11315
|
+
"`fix`, `review [base]`, `rollout <flag>` and",
|
|
11316
|
+
"`cleanup <flag>`), plus the config's `doors` export. An",
|
|
11317
|
+
"unknown door, or too few or too many args, is a usage error",
|
|
11318
|
+
"(exit 2) naming the doors or the door's synopsis"
|
|
11291
11319
|
]
|
|
11292
11320
|
},
|
|
11293
11321
|
{
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { agent, changes, glob, read, refuse, scope, start, vars } from "../flows.mjs";
|
|
2
|
-
import { a as flagShipped,
|
|
3
|
-
import { i as refusePendingHandOff, r as handOffTail } from "../chunks/tail-
|
|
4
|
-
import { i as requireFlag, r as registryEntry, t as flagReferences } from "../chunks/registry-CP3YuV9j.mjs";
|
|
2
|
+
import { a as flagShipped, ct as defaults, dt as flagReferences, i as skills, lt as envDefaults, mt as requireFlag, n as summary, pt as registryEntry, r as access, t as steering, v as coder } from "../chunks/reserved-BIsngMGL.mjs";
|
|
3
|
+
import { i as refusePendingHandOff, r as handOffTail } from "../chunks/tail-DHEaOHyp.mjs";
|
|
5
4
|
//#region src/workflows/cleanup/cleanup.ts
|
|
6
5
|
const removingPrompt = (name, registry) => `Clean up the release flag "${name}", which is default-on: delete its entry in ${registry}, and remove every \`GTD_FLAG_${name.toUpperCase()}\` check from the shipped sources. Keep the flag-on path; delete code only the off path reached, including tests that pin the off path.`;
|
|
7
6
|
const cleanupFlow = async () => {
|
|
@@ -29,7 +28,7 @@ const cleanupFlow = async () => {
|
|
|
29
28
|
});
|
|
30
29
|
await handOffTail(false, start(), guard);
|
|
31
30
|
};
|
|
32
|
-
const cleanup = flagShipped(cleanupFlow);
|
|
31
|
+
const cleanup = flagShipped(cleanupFlow, "cleanup");
|
|
33
32
|
//#endregion
|
|
34
33
|
//#region src/workflows/cleanup/index.ts
|
|
35
34
|
var cleanup_default = cleanup;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { answered, changes, changesSince, glob, hasThreadFor, head, human, judge, judgeDiffShape, kept, mark, numeric, quote, read, refuse, removeScript, requireAnswers, requireProgress, requireReplies, requireRevert, requireThreadsClosed, restoreScript, revertScript, run, scope, seamGate, start, vars } from "../flows.mjs";
|
|
2
2
|
import { review as review$1 } from "../workflow-kit.mjs";
|
|
3
|
-
import { $ as
|
|
4
|
-
import { a as tail, i as refusePendingHandOff, n as closeReview } from "../chunks/tail-
|
|
3
|
+
import { $ as reviewEditsCapture, A as architectureGateAnswerMessage, B as designTriagePrompt, C as reviewMissing, D as architectSystem, E as agentWithSkills, F as buildReviewTriageMessage, G as implementBuildingPrompt, I as builderSystem, J as packagesItemBuildingPrompt, K as implementFixPrompt, L as deferNotesScript, M as buildReviewAwaitAfterDeferMessage, N as buildReviewCollectingPrompt, O as architectureAuthorPrompt, P as buildReviewFixNitsPrompt, Q as reviewEditNotesCapture, R as designGateAnswerMessage, S as planner, T as reviewing, W as idleMessage, X as refactorBuildingPrompt, Y as packagesItemFixSuitePrompt, Z as refactorFixPrompt, _ as awaitReview, at as startGateBlockedMessage, ct as defaults, d as healthy, f as ARCHITECTURE, g as REVIEW, h as REQUIREMENTS, i as skills, it as seamSteerMessage, j as buildReviewAnswerQuestionsPrompt, k as architectureDecomposePrompt, l as gate, lt as envDefaults, n as summary, nt as reviewerSystem, o as shipped, ot as unwindFailedMessage, p as FEEDBACK, q as naivePassPrompt, r as access, rt as seamByHandMessage, st as unwindFailure, t as steering, tt as reviewNotesCapture, v as coder, x as fixRisks, y as fixCheck, z as designSystem } from "../chunks/reserved-BIsngMGL.mjs";
|
|
4
|
+
import { a as tail, i as refusePendingHandOff, n as closeReview } from "../chunks/tail-DHEaOHyp.mjs";
|
|
5
5
|
//#region src/workflows/feature/tier.ts
|
|
6
6
|
/** GTD_FLAG_NAIVE_PASS, GTD_FLAG_RISK_TIER: both pinned at process start, so a mid-process flip never moves a process. */
|
|
7
7
|
const riskTierOn = () => vars.flag_naive_pass === "1" && vars.flag_risk_tier === "1";
|
package/dist/workflows/fix.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { read, refuse, removeScript, run, scope, start } from "../flows.mjs";
|
|
2
2
|
import { d as reviewNotes, f as reviewRisks } from "../chunks/steering-DVILanVf.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-
|
|
3
|
+
import { E as agentWithSkills, H as fixReviewNotesPrompt, V as finisherSystem, ct as defaults, g as REVIEW, i as skills, lt as envDefaults, n as summary, o as shipped, r as access, s as baseline, t as steering, v as coder } from "../chunks/reserved-BIsngMGL.mjs";
|
|
4
|
+
import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-DHEaOHyp.mjs";
|
|
5
5
|
//#region src/workflows/fix/fix.ts
|
|
6
6
|
/**
|
|
7
7
|
* Fix every note a human left in a handed-off `.gtd/REVIEW.md` and every
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { start } from "../flows.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { i as refusePendingHandOff, r as handOffTail } from "../chunks/tail-
|
|
2
|
+
import { ct as defaults, et as reviewGateBlockedMessage, i as skills, l as gate, lt as envDefaults, n as summary, o as shipped, r as access, t as steering } from "../chunks/reserved-BIsngMGL.mjs";
|
|
3
|
+
import { i as refusePendingHandOff, r as handOffTail } from "../chunks/tail-DHEaOHyp.mjs";
|
|
4
4
|
//#region src/workflows/review/review.ts
|
|
5
5
|
/**
|
|
6
6
|
* Pure review of everything since `reviewBase`: a green gate, the quality
|
|
@@ -1,9 +1,23 @@
|
|
|
1
|
-
import { agent, changesSince, head, read, refuse, scope, vars } from "../flows.mjs";
|
|
2
|
-
import { a as flagShipped,
|
|
3
|
-
import { i as requireFlag, n as flipProblems } from "../chunks/registry-CP3YuV9j.mjs";
|
|
1
|
+
import { agent, changesSince, glob, head, mark, read, refuse, removeScript, run, scope, vars } from "../flows.mjs";
|
|
2
|
+
import { a as flagShipped, ct as defaults, ft as flipProblems, i as skills, l as gate, lt as envDefaults, mt as requireFlag, n as summary, p as FEEDBACK, r as access, t as steering, ut as flagMentions, v as coder } from "../chunks/reserved-BIsngMGL.mjs";
|
|
4
3
|
//#region src/workflows/rollout/rollout.ts
|
|
5
4
|
const flippingPrompt = (name, registry) => `Roll out the release flag "${name}": in ${registry}, set \`defaultOn: true\` on its entry. Change nothing else — no other entry, no other field, no other file, no comments.`;
|
|
6
5
|
const suiteBlockedMessage = () => "The suite is red after the rollout. Fix it by hand — a rollout may only touch the flag's registry entry — then land.";
|
|
6
|
+
const MARKED_MENTIONS = 50;
|
|
7
|
+
const listMentions = async (registry, name, guard) => {
|
|
8
|
+
await run("mentions", removeScript([FEEDBACK]), { label: "Listing flag mentions" });
|
|
9
|
+
guard();
|
|
10
|
+
const mentions = flagMentions(glob("**").filter((path) => path !== registry && path !== ".gtd" && !path.startsWith(".gtd/")).sort().map((path) => ({
|
|
11
|
+
path,
|
|
12
|
+
text: read(path) ?? ""
|
|
13
|
+
})), name);
|
|
14
|
+
mark("flag-mentions", String(mentions.length));
|
|
15
|
+
for (const m of mentions.slice(0, MARKED_MENTIONS)) try {
|
|
16
|
+
mark("flag-mention", `${m.path}:${m.line}`);
|
|
17
|
+
} catch {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
7
21
|
const rolloutFlow = async () => {
|
|
8
22
|
const registry = vars.flagRegistry ?? "";
|
|
9
23
|
const name = vars.flag ?? "";
|
|
@@ -23,9 +37,10 @@ const rolloutFlow = async () => {
|
|
|
23
37
|
});
|
|
24
38
|
guard();
|
|
25
39
|
await gate("suite", suiteBlockedMessage(), guard);
|
|
40
|
+
await listMentions(registry, name, guard);
|
|
26
41
|
});
|
|
27
42
|
};
|
|
28
|
-
const rollout = flagShipped(rolloutFlow);
|
|
43
|
+
const rollout = flagShipped(rolloutFlow, "rollout");
|
|
29
44
|
//#endregion
|
|
30
45
|
//#region src/workflows/rollout/index.ts
|
|
31
46
|
var rollout_default = rollout;
|