jackherd 1.6.1 → 1.7.1
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/CHANGELOG.md +31 -0
- package/INSTALL.md +176 -0
- package/README.md +228 -312
- package/assets/branding/README.md +7 -3
- package/assets/branding/jackherd-logo-dark-1024.png +0 -0
- package/assets/branding/jackherd-logo-dark-512.png +0 -0
- package/assets/branding/jackherd-logo-dark.svg +1 -1
- package/assets/icons/bark-dark.svg +1 -0
- package/assets/icons/bark.svg +1 -0
- package/assets/icons/bowl-dark.svg +1 -0
- package/assets/icons/bowl.svg +1 -0
- package/assets/icons/decide-dark.svg +1 -0
- package/assets/icons/decide.svg +1 -0
- package/assets/icons/ear-dark.svg +1 -0
- package/assets/icons/ear.svg +1 -0
- package/assets/icons/lanes-dark.svg +1 -0
- package/assets/icons/lanes.svg +1 -0
- package/assets/icons/plan-dark.svg +1 -0
- package/assets/icons/plan.svg +1 -0
- package/assets/icons/space.svg +1 -0
- package/dist/{chunk-QJSXHHQ3.js → chunk-OBUWTQ6Z.js} +25 -0
- package/dist/config.d.ts +14 -3
- package/dist/config.js +111 -10
- package/dist/plan-format.d.ts +180 -77
- package/dist/plan-format.js +292 -93
- package/docs/lanes-dark.svg +50 -0
- package/docs/lanes.svg +50 -1
- package/docs/skills-dark.svg +65 -0
- package/docs/skills.svg +65 -1
- package/docs/workflow-dark.svg +138 -0
- package/docs/workflow.svg +135 -169
- package/herdr-plugin/herdr-plugin.toml +6 -6
- package/herdr-plugin/open-plans.ts +1 -1
- package/herdr-plugin/restore-plans.ts +7 -7
- package/install.sh +1 -1
- package/kit/hooks/hooks/approval-gate/decision.ts +61 -0
- package/kit/hooks/hooks/approval-gate/herdr-panes.ts +24 -0
- package/kit/hooks/hooks/approval-gate/index.ts +69 -0
- package/kit/hooks/hooks/approval-gate/lane.ts +14 -0
- package/kit/hooks/hooks/approval-gate/request.ts +111 -0
- package/kit/hooks/hooks/approval-gate/run.ts +94 -0
- package/kit/hooks/hooks/approval-gate/settings.ts +26 -0
- package/kit/hooks/hooks/approval-gate/store.ts +70 -0
- package/kit/hooks/hooks/approval-gate/transcripts.ts +40 -0
- package/kit/hooks/hooks/merge-guard/approval.ts +11 -74
- package/kit/hooks/hooks/merge-guard/run.ts +2 -1
- package/kit/hooks/hooks/model-gate/agent-definition.ts +13 -0
- package/kit/hooks/hooks/model-gate/index.ts +58 -0
- package/kit/hooks/hooks/model-gate/run.ts +63 -0
- package/kit/hooks/hooks/model-log/index.ts +60 -0
- package/kit/hooks/hooks/model-log/run.ts +57 -0
- package/kit/hooks/hooks/model-log/store.ts +40 -0
- package/kit/hooks/hooks/model-log/transcript.ts +37 -0
- package/kit/hooks/hooks/shared/checkout.ts +22 -0
- package/kit/hooks/hooks/shared/command.ts +6 -0
- package/kit/hooks/hooks/shared/config.ts +21 -0
- package/kit/hooks/hooks/shared/dialog-answer.ts +5 -0
- package/kit/hooks/hooks/shared/dialog-answers.ts +74 -0
- package/kit/hooks/hooks/shared/files.ts +19 -0
- package/kit/hooks/hooks/shared/fresh.ts +4 -0
- package/kit/hooks/hooks/shared/json.ts +4 -0
- package/kit/hooks/hooks/shared/model-family.ts +48 -0
- package/kit/hooks/hooks/shared/plan-model-table.ts +41 -0
- package/kit/hooks/hooks/shared/private-directory.ts +29 -0
- package/kit/hooks/hooks/shared/repository-directory.ts +14 -0
- package/kit/hooks/hooks/shared/subagent-phase.ts +99 -0
- package/kit/hooks/hooks.json +25 -0
- package/kit/workflow/skills/follow/SKILL.md +4 -3
- package/kit/workflow/skills/implement/SKILL.md +6 -6
- package/kit/workflow/skills/orchestrate/SKILL.md +109 -27
- package/kit/workflow/skills/plan/SKILL.md +5 -5
- package/kit/workflow/skills/start/SKILL.md +2 -2
- package/package.json +4 -1
- package/schemas/jackherd.schema.json +43 -5
- package/src/check/command.ts +31 -4
- package/src/check/deferral-arrows.ts +1 -1
- package/src/check/parallel-report.ts +23 -0
- package/src/check/plan-structure-check.ts +120 -53
- package/src/cli.ts +8 -2
- package/src/config/legacy-names.ts +8 -0
- package/src/config/nested-quantifier.ts +73 -0
- package/src/config/repository-directory.ts +11 -0
- package/src/config/schema.ts +63 -8
- package/src/plan-format/board-prose.ts +36 -0
- package/src/plan-format/dependencies.ts +227 -0
- package/src/plan-format/documentation-gate.ts +16 -0
- package/src/plan-format/index.ts +23 -1
- package/src/plan-format/lanes.ts +35 -1
- package/src/plan-format/model-column.ts +52 -0
- package/src/plan-format/phases.ts +16 -1
- package/src/plan-format/plan-structure.ts +10 -28
- package/src/plan-format/progress.ts +7 -29
- package/src/plans/command.ts +3 -3
- package/src/plans/current-phase.ts +71 -0
- package/src/plans/ensure-panes.ts +2 -2
- package/src/plans/herd-command.ts +4 -0
- package/src/plans/lane-discovery.ts +14 -2
- package/src/plans/lane-tickets.ts +69 -0
- package/src/plans/layout.ts +182 -88
- package/src/plans/live.ts +5 -1
- package/src/plans/phase-models-read.ts +37 -0
- package/src/plans/phase-models.ts +70 -0
- package/src/plans/plan-panes.ts +8 -7
- package/src/plans/pull-requests.ts +78 -4
- package/src/plans/selection.ts +1 -40
- package/src/plans/settings.ts +9 -3
- package/src/plans/shown-with-more.ts +5 -0
- package/src/plans/snapshot.ts +82 -8
- package/src/plans/sprint-html.ts +2 -2
- package/src/plans/supervisor.ts +5 -4
- package/src/plans/symbols.ts +9 -6
- package/src/plans/texts.ts +30 -13
- package/src/plans/view.ts +1 -0
- package/src/sync/command.ts +16 -1
- package/src/sync/herdr-plugin.ts +1 -1
- package/src/sync/next-steps.ts +1 -1
- package/src/sync/render.ts +2 -1
- package/src/sync/setup-questions.ts +2 -2
- package/src/terminal/text.ts +4 -0
- package/src/terminal/types.ts +1 -1
- package/src/update/command.ts +4 -2
- package/src/update/update.ts +33 -9
- package/src/vocabulary/index.ts +39 -0
- package/src/watch/approvals.ts +96 -0
- package/src/watch/command.ts +154 -50
- package/src/watch/failed-tests.ts +52 -0
- package/src/watch/failure-read.ts +56 -0
- package/src/watch/failures.ts +107 -0
- package/src/watch/feedback-item.ts +21 -0
- package/src/watch/feedback-read.ts +2 -1
- package/src/watch/feedback.ts +37 -28
- package/src/watch/gh-process.ts +53 -0
- package/src/watch/gh.ts +10 -20
- package/src/watch/heartbeat-progress.ts +1 -1
- package/src/watch/lane-model.ts +54 -0
- package/src/watch/lane-parallel.ts +46 -0
- package/src/watch/lane-progress.ts +28 -4
- package/src/watch/lane-report.ts +62 -9
- package/src/watch/lane-sources.ts +1 -1
- package/src/watch/no-finding.ts +47 -0
- package/src/watch/plan-badges-read.ts +19 -7
- package/src/watch/plan-badges.ts +59 -7
- package/src/watch/plan-views.ts +5 -5
- package/src/watch/previews.ts +3 -9
- package/src/watch/pull-requests.ts +12 -2
- package/src/watch/recorded-reads.ts +25 -0
- package/src/watch/source-fields.ts +4 -0
- package/src/watch/source-tickets.ts +99 -0
- package/src/watch/sources.ts +62 -15
- package/src/watch/texts.ts +21 -1
- package/src/watch/watch-defaults.ts +8 -0
- package/src/watch/watch-events.ts +64 -4
- package/src/watch/watcher-lock.ts +1 -1
- package/src/watch/workflow-runs.ts +5 -7
- package/docs/lanes.mmd +0 -9
- package/docs/skills.mmd +0 -10
package/dist/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PLAN_LANGUAGE,
|
|
3
3
|
RESPONSE_ADDRESS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OBUWTQ6Z.js";
|
|
5
5
|
|
|
6
6
|
// src/config/json-schema.ts
|
|
7
7
|
import { z as z3 } from "zod";
|
|
@@ -157,8 +157,10 @@ var SOURCE_FIELD = {
|
|
|
157
157
|
title: "title",
|
|
158
158
|
url: "url",
|
|
159
159
|
body: "body",
|
|
160
|
-
author: "author"
|
|
160
|
+
author: "author",
|
|
161
|
+
status: "status"
|
|
161
162
|
};
|
|
163
|
+
var CONTENT_FIELDS = [SOURCE_FIELD.title, SOURCE_FIELD.author, SOURCE_FIELD.body, SOURCE_FIELD.url];
|
|
162
164
|
|
|
163
165
|
// src/watch/source-path.ts
|
|
164
166
|
var ROOT_PATH = ".";
|
|
@@ -176,6 +178,10 @@ var pathSteps = (path) => {
|
|
|
176
178
|
};
|
|
177
179
|
var isSourcePath = (path) => pathSteps(path) !== null;
|
|
178
180
|
|
|
181
|
+
// src/watch/watch-defaults.ts
|
|
182
|
+
var CLEAN_REVIEW_TEXT = "## Code review\n\nNo issues found. Checked for bugs and CLAUDE.md compliance.";
|
|
183
|
+
var BUN_FAILED_TEST_PATTERN = "^\\(fail\\) (.+?)(?: \\[[\\d.]+m?s\\])?$";
|
|
184
|
+
|
|
179
185
|
// src/config/link-kinds.ts
|
|
180
186
|
var DEFAULT_LINK_KINDS = [
|
|
181
187
|
{ pattern: "^https://github\\.com/[^/]+/[^/]+/(pull|issues)/\\d+", label: "GitHub", icon: "\u2442" },
|
|
@@ -191,6 +197,65 @@ var isRegularExpression = (source) => {
|
|
|
191
197
|
}
|
|
192
198
|
};
|
|
193
199
|
|
|
200
|
+
// src/config/nested-quantifier.ts
|
|
201
|
+
var GROUP_PREFIX = /^\?(?::|=|!|<=|<!|<[^>]+>)/;
|
|
202
|
+
var BRACES = /^\{(\d+)(?:(,)(\d*))?\}/;
|
|
203
|
+
var repeatingLengthAt = (pattern, index) => {
|
|
204
|
+
if (pattern[index] === "*" || pattern[index] === "+") return 1;
|
|
205
|
+
const braces = pattern.slice(index).match(BRACES);
|
|
206
|
+
const [text, , comma, max] = braces ?? [];
|
|
207
|
+
return text !== void 0 && comma && (max === "" || Number(max) > 1) ? text.length : 0;
|
|
208
|
+
};
|
|
209
|
+
var classEnd = (pattern, start) => {
|
|
210
|
+
let index = start + 1;
|
|
211
|
+
while (index < pattern.length && pattern[index] !== "]") index += pattern[index] === "\\" ? 2 : 1;
|
|
212
|
+
return index;
|
|
213
|
+
};
|
|
214
|
+
var overlapsAnother = (branches) => branches.some(
|
|
215
|
+
(branch, index) => branches.some((other, otherIndex) => index !== otherIndex && other.startsWith(branch))
|
|
216
|
+
);
|
|
217
|
+
var NESTED = -1;
|
|
218
|
+
var appendTo = (group, text) => {
|
|
219
|
+
group.branches[group.branches.length - 1] += text;
|
|
220
|
+
};
|
|
221
|
+
var prefixLengthAt = (pattern, index) => pattern.slice(index + 1).match(GROUP_PREFIX)?.[0].length ?? 0;
|
|
222
|
+
var closeGroup = (pattern, index, groups) => {
|
|
223
|
+
const closed = groups.pop();
|
|
224
|
+
const repeated = repeatingLengthAt(pattern, index + 1) > 0;
|
|
225
|
+
if (repeated && (closed.repeats || overlapsAnother(closed.branches))) return NESTED;
|
|
226
|
+
groups[groups.length - 1].repeats ||= closed.repeats;
|
|
227
|
+
return index + 1;
|
|
228
|
+
};
|
|
229
|
+
var stepAt = (pattern, index, groups) => {
|
|
230
|
+
const top = groups[groups.length - 1];
|
|
231
|
+
const char = pattern[index];
|
|
232
|
+
const literalEnd = char === "\\" ? index + 2 : classEnd(pattern, index) + 1;
|
|
233
|
+
const quantifierLength = repeatingLengthAt(pattern, index);
|
|
234
|
+
if (char === "\\" || char === "[") appendTo(top, pattern.slice(index, literalEnd));
|
|
235
|
+
else if (char === "(") groups.push({ repeats: false, branches: [""] });
|
|
236
|
+
else if (char === ")" && groups.length > 1) return closeGroup(pattern, index, groups);
|
|
237
|
+
else if (char === "|") top.branches.push("");
|
|
238
|
+
else if (quantifierLength > 0) top.repeats = true;
|
|
239
|
+
else appendTo(top, char);
|
|
240
|
+
if (char === "\\" || char === "[") return literalEnd;
|
|
241
|
+
if (char === "(") return index + 1 + prefixLengthAt(pattern, index);
|
|
242
|
+
return index + Math.max(quantifierLength, 1);
|
|
243
|
+
};
|
|
244
|
+
var hasNestedQuantifier = (pattern) => {
|
|
245
|
+
const groups = [{ repeats: false, branches: [""] }];
|
|
246
|
+
let index = 0;
|
|
247
|
+
while (index < pattern.length) {
|
|
248
|
+
index = stepAt(pattern, index, groups);
|
|
249
|
+
if (index === NESTED) return true;
|
|
250
|
+
}
|
|
251
|
+
return false;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// src/config/repository-directory.ts
|
|
255
|
+
import { isAbsolute } from "path";
|
|
256
|
+
var segmentsOf = (path) => path.split(/[\\/]/).filter((segment) => segment !== "" && segment !== ".");
|
|
257
|
+
var isRepositoryDirectory = (value) => !isAbsolute(value) && segmentsOf(value).length > 0 && !segmentsOf(value).includes("..");
|
|
258
|
+
|
|
194
259
|
// src/config/schema.ts
|
|
195
260
|
var TERMINAL_ADAPTER = { none: "none", herdr: "herdr" };
|
|
196
261
|
var MODEL_ROLE = {
|
|
@@ -228,7 +293,7 @@ var boardSchema = z2.strictObject({
|
|
|
228
293
|
pattern: boardPattern.default("board-*"),
|
|
229
294
|
/** The board document inside each of those directories. */
|
|
230
295
|
file: boardFile.default("board.md"),
|
|
231
|
-
/** What the project calls a board: the
|
|
296
|
+
/** What the project calls a board: the herd, its page and the watcher print it as written. */
|
|
232
297
|
term: z2.string().min(1).default("board")
|
|
233
298
|
});
|
|
234
299
|
var deploySchema = z2.strictObject({
|
|
@@ -239,7 +304,23 @@ var deploySchema = z2.strictObject({
|
|
|
239
304
|
});
|
|
240
305
|
var feedbackSchema = z2.strictObject({
|
|
241
306
|
/** GitHub logins whose feedback does not wake the coordinator, such as a status bot; case is ignored. */
|
|
242
|
-
ignore: z2.array(z2.string().min(1)).default([])
|
|
307
|
+
ignore: z2.array(z2.string().min(1)).default([]),
|
|
308
|
+
/**
|
|
309
|
+
* Texts of a bot's pull request comment that report no finding: such a comment (login ending `[bot]`, no inline
|
|
310
|
+
* comment by the same author within five minutes of it) is no feedback. Compared with whitespace collapsed; the
|
|
311
|
+
* default is the CI code review's comment for a clean run. An empty list counts every bot comment.
|
|
312
|
+
*/
|
|
313
|
+
noFindingTemplates: z2.array(z2.string().min(1)).default([CLEAN_REVIEW_TEXT])
|
|
314
|
+
});
|
|
315
|
+
var checksSchema = z2.strictObject({
|
|
316
|
+
/**
|
|
317
|
+
* Finds a failed test in a line of a red run's log (`gh run view --log-failed`) after its job, step and timestamp
|
|
318
|
+
* prefix: the first group is the name, else the match. The default is Bun's `(fail) <name> [<duration>]`. The
|
|
319
|
+
* watcher runs it on every line of a log it does not control, so a pattern that repeats a group which repeats inside
|
|
320
|
+
* itself (`(a+)+`, `(\w*)*`, and with alternation `(a|aa)+`) is refused: a best-effort scan of the source against
|
|
321
|
+
* catastrophic backtracking, not a proof.
|
|
322
|
+
*/
|
|
323
|
+
failedTestPattern: z2.string().min(1).refine(isRegularExpression, "not a valid regular expression").refine((pattern) => !hasNestedQuantifier(pattern), "a quantified group that holds a quantifier backtracks badly").default(BUN_FAILED_TEST_PATTERN)
|
|
243
324
|
});
|
|
244
325
|
var previewsSchema = z2.strictObject({
|
|
245
326
|
/** Reads the GitHub deployments of each head commit; a successful one outside production and `deploy.environments` names its `environment_url`. */
|
|
@@ -256,17 +337,23 @@ var sourcePath = z2.string().refine(isSourcePath, "not a source path: `.`, or `.
|
|
|
256
337
|
var SOURCE_FIELD_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
257
338
|
var sourceMapSchema = z2.object({
|
|
258
339
|
[SOURCE_FIELD.id]: sourcePath,
|
|
259
|
-
/**
|
|
260
|
-
|
|
340
|
+
/**
|
|
341
|
+
* Changes whenever the entry changes; compared as text, so any stable form of a time or version works. Needed
|
|
342
|
+
* only where no content field and no `reportOn` can tell a change.
|
|
343
|
+
*/
|
|
344
|
+
[SOURCE_FIELD.updatedAt]: sourcePath.optional(),
|
|
261
345
|
[SOURCE_FIELD.title]: sourcePath.optional(),
|
|
262
346
|
/** Shown only as an `https:` URL without user name or password. */
|
|
263
347
|
[SOURCE_FIELD.url]: sourcePath.optional(),
|
|
264
348
|
/** The first line with text is shown. */
|
|
265
349
|
[SOURCE_FIELD.body]: sourcePath.optional(),
|
|
266
|
-
[SOURCE_FIELD.author]: sourcePath.optional()
|
|
350
|
+
[SOURCE_FIELD.author]: sourcePath.optional(),
|
|
351
|
+
/** A ticket source's status, shown on its badge in the herd; also a field `reportOn` can name. */
|
|
352
|
+
[SOURCE_FIELD.status]: sourcePath.optional()
|
|
267
353
|
}).catchall(sourcePath).refine((map) => Object.keys(map).every((field) => SOURCE_FIELD_NAME.test(field)), {
|
|
268
354
|
message: "a map field is a letter, then letters, digits and `_`"
|
|
269
355
|
});
|
|
356
|
+
var canChange = ({ map, reportOn }) => map.updatedAt !== void 0 || CONTENT_FIELDS.some((field) => map[field] !== void 0) || reportOn !== void 0;
|
|
270
357
|
var sourceSchema = z2.strictObject({
|
|
271
358
|
/** Printed in every report of the source and the key of its saved state. */
|
|
272
359
|
name: z2.string().regex(/^[A-Za-z0-9][\w.-]*$/, "letters, digits, `_`, `.` and `-`"),
|
|
@@ -283,11 +370,19 @@ var sourceSchema = z2.strictObject({
|
|
|
283
370
|
reportLimit: z2.number().int().min(1).default(5),
|
|
284
371
|
/** The lane the source's reports name. */
|
|
285
372
|
lane: z2.string().min(1).optional(),
|
|
373
|
+
/**
|
|
374
|
+
* Marks the entries as tickets: the herd shows each as a badge beside the plan of the lane it belongs to,
|
|
375
|
+
* the lane above or the lane whose board row or plan names its id.
|
|
376
|
+
*/
|
|
377
|
+
ticket: z2.boolean().optional(),
|
|
286
378
|
/**
|
|
287
379
|
* The mapped fields whose change reports, with the old and the new value, in place of the content of `title`,
|
|
288
380
|
* `author`, `body` and `url`; without it a change of that content reports.
|
|
289
381
|
*/
|
|
290
382
|
reportOn: z2.array(z2.string().min(1)).min(1).max(10).optional()
|
|
383
|
+
}).refine(canChange, {
|
|
384
|
+
message: "map needs updatedAt, a content field (title, author, body, url) or reportOn",
|
|
385
|
+
path: ["map"]
|
|
291
386
|
}).refine((source) => source.ignoreAuthors.length === 0 || source.map.author !== void 0, {
|
|
292
387
|
message: "ignoreAuthors needs map.author",
|
|
293
388
|
path: ["ignoreAuthors"]
|
|
@@ -331,6 +426,10 @@ var guardSchema = z2.strictObject({
|
|
|
331
426
|
offer: z2.boolean().default(true),
|
|
332
427
|
/** How long an answer to that question lets `gh pr merge <number>` pass without asking, counted from the answer. */
|
|
333
428
|
approvalMinutes: z2.number().int().min(1).max(1440).default(180)
|
|
429
|
+
}).prefault({}),
|
|
430
|
+
approvals: z2.strictObject({
|
|
431
|
+
/** How long the approval gate hook holds a lane's call for the coordinator's dialog before it denies it; below the hook's 10 minutes. */
|
|
432
|
+
waitMinutes: z2.number().int().min(1).max(9).default(8)
|
|
334
433
|
}).prefault({})
|
|
335
434
|
});
|
|
336
435
|
var hintsSchema = z2.strictObject({
|
|
@@ -360,7 +459,7 @@ var jackherdConfigSchema = z2.strictObject({
|
|
|
360
459
|
board: boardSchema.prefault({}),
|
|
361
460
|
/** Replaced by `board.pattern` in 0.13.0; named here only so an old config is refused with that hint. */
|
|
362
461
|
sprintPattern: z2.never({ error: "sprintPattern was replaced by board.pattern (with board.file and board.term)" }).optional(),
|
|
363
|
-
worktreeDirectory: z2.string().min(1).default(claudePath(WORKTREES_DIRECTORY)),
|
|
462
|
+
worktreeDirectory: z2.string().min(1).refine(isRepositoryDirectory, "must lie below the repository root: relative, not `.`, without `..`").default(claudePath(WORKTREES_DIRECTORY)),
|
|
364
463
|
baseBranch: branchName.default(DEFAULT_BASE_BRANCH),
|
|
365
464
|
/**
|
|
366
465
|
* Put before every skill and agent name. `jh sync --global` refuses to run without one: a personal skill
|
|
@@ -388,7 +487,7 @@ var jackherdConfigSchema = z2.strictObject({
|
|
|
388
487
|
models: z2.record(z2.enum(Object.values(MODEL_ROLE)), modelId),
|
|
389
488
|
terminal: z2.strictObject({ adapter: z2.enum(Object.values(TERMINAL_ADAPTER)).default(TERMINAL_ADAPTER.none) }).prefault({}),
|
|
390
489
|
plans: z2.strictObject({
|
|
391
|
-
/** Minutes between background fetches of the base branch while `jh
|
|
490
|
+
/** Minutes between background fetches of the base branch while `jh herd` runs; 0 turns them off. */
|
|
392
491
|
fetchIntervalMinutes: z2.number().min(0).default(5),
|
|
393
492
|
/** Links in a plan that the sprint page shows as chips; the list replaces the built-in kinds. */
|
|
394
493
|
linkKinds: z2.array(
|
|
@@ -403,12 +502,14 @@ var jackherdConfigSchema = z2.strictObject({
|
|
|
403
502
|
/**
|
|
404
503
|
* Read by `jh watch`; without `deploy` it reports no deploy runs. `feedback` is on unless set to `false`:
|
|
405
504
|
* it reports new feedback on the lanes' pull requests except from the account the watcher runs as and `ignore`.
|
|
505
|
+
* `checks` reads the failed tests of a red lane pull request (`failedTestPattern`), also with `feedback` off.
|
|
406
506
|
* Without `previews` it reads no deploy preview; with it, one `preview` per new head commit. Each of `sources` is a
|
|
407
507
|
* command whose JSON output reports `source` for a new or changed entry.
|
|
408
508
|
*/
|
|
409
509
|
watch: z2.strictObject({
|
|
410
510
|
deploy: deploySchema.optional(),
|
|
411
|
-
feedback: z2.union([z2.literal(false), feedbackSchema]).
|
|
511
|
+
feedback: z2.union([z2.literal(false), feedbackSchema]).prefault({}),
|
|
512
|
+
checks: checksSchema.prefault({}),
|
|
412
513
|
previews: previewsSchema.optional(),
|
|
413
514
|
sources: z2.array(sourceSchema).refine(hasUniqueNames, "source names must be unique").default([])
|
|
414
515
|
}).prefault({}),
|
package/dist/plan-format.d.ts
CHANGED
|
@@ -22,6 +22,16 @@ declare const ADDRESS_FORM: Record<PlanLanguage, Record<ResponseAddress, string>
|
|
|
22
22
|
* a config value.
|
|
23
23
|
*/
|
|
24
24
|
declare const SELF_MERGE_LABEL: Record<PlanLanguage, string>;
|
|
25
|
+
/**
|
|
26
|
+
* The words of an approval: the two option labels of the coordinator's question about a lane's call, which the
|
|
27
|
+
* approval gate hook matches exactly, and what the hook tells the lane when it denies. Fixed per language, not config.
|
|
28
|
+
*/
|
|
29
|
+
declare const APPROVAL_TEXTS: Record<PlanLanguage, {
|
|
30
|
+
allow: string;
|
|
31
|
+
deny: string;
|
|
32
|
+
pending: string;
|
|
33
|
+
denied: string;
|
|
34
|
+
}>;
|
|
25
35
|
declare const isPlanLanguage: (value: string) => value is PlanLanguage;
|
|
26
36
|
declare const PLAN_STATUS: {
|
|
27
37
|
readonly done: "done";
|
|
@@ -68,8 +78,18 @@ type PlanVocabulary = {
|
|
|
68
78
|
laneClosed: string;
|
|
69
79
|
/** Words a starts-after cell begins with when the lane may start at once. */
|
|
70
80
|
startsNow: readonly string[];
|
|
81
|
+
/** Opens the parenthesis by which a board row's phases cell records a user's side order in prose. */
|
|
82
|
+
sideOrderMarker: string;
|
|
71
83
|
/** Words that may stand between two phases of one entry (`P1 Rule und P2 Monitor`). */
|
|
72
84
|
phaseConnectors: readonly string[];
|
|
85
|
+
/** Words that open a writes cell naming another phase's set instead of listing it (`wie 15`). */
|
|
86
|
+
writesLike: readonly string[];
|
|
87
|
+
/** Words that join several phases after a `writesLike` word (`wie 15 und 16`); a comma joins them in every language. */
|
|
88
|
+
writesLikeJoiners: readonly string[];
|
|
89
|
+
/** Words a `Depends on` cell says it depends on nothing with, besides a dash. */
|
|
90
|
+
noDependency: readonly string[];
|
|
91
|
+
/** The word that opens the serial marker of a phase that ships in a release (`Release 1.7.0`); the release files stay a judgement. */
|
|
92
|
+
releaseMarker: string;
|
|
73
93
|
statusWords: Record<PlanStatus, StatusWord>;
|
|
74
94
|
};
|
|
75
95
|
declare const PLAN_VOCABULARY: Record<PlanLanguage, PlanVocabulary>;
|
|
@@ -79,6 +99,139 @@ declare const classifyStatus: (language: PlanLanguage, statusText: string) => Pl
|
|
|
79
99
|
declare const phaseHeading: (language: PlanLanguage, id: string, title: string) => string;
|
|
80
100
|
declare const sectionHeading: (language: PlanLanguage, section: keyof PlanVocabulary["sections"]) => string;
|
|
81
101
|
|
|
102
|
+
/**
|
|
103
|
+
* The longest phases cell, in characters, that still reads as a phase and its state. Longer cells in the open
|
|
104
|
+
* lanes of the real boards carry prose, which belongs in the plan.
|
|
105
|
+
*/
|
|
106
|
+
declare const PHASE_CELL_LIMIT = 250;
|
|
107
|
+
declare const PROSE_REASON: {
|
|
108
|
+
readonly long: "long";
|
|
109
|
+
readonly sideOrder: "side-order";
|
|
110
|
+
};
|
|
111
|
+
type ProseReason = (typeof PROSE_REASON)[keyof typeof PROSE_REASON];
|
|
112
|
+
/** A changed row of an open lane (1-based line) whose phases cell is `length` characters and carries prose. */
|
|
113
|
+
type RowWithProse = {
|
|
114
|
+
line: number;
|
|
115
|
+
lane: string;
|
|
116
|
+
reason: ProseReason;
|
|
117
|
+
length: number;
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* The changed rows of open lanes whose phases cell is longer than `PHASE_CELL_LIMIT` or records a side order of the
|
|
121
|
+
* user in prose (`dazu (User …`): the board row names the phase, the side order is a task in the plan's phase.
|
|
122
|
+
* A cell that is both counts once, as a side order.
|
|
123
|
+
*/
|
|
124
|
+
declare const boardRowsWithProse: (markdown: string, language: PlanLanguage, previousLines: ReadonlySet<string>) => RowWithProse[];
|
|
125
|
+
|
|
126
|
+
/** A checkbox of a plan. `gate` is set on the ones listed under the phase's review gate, and only on those. */
|
|
127
|
+
type ChecklistItem = {
|
|
128
|
+
done: boolean;
|
|
129
|
+
text: string;
|
|
130
|
+
gate?: true;
|
|
131
|
+
};
|
|
132
|
+
/** An open checkbox that ends in `→ P<n>`: moved on purpose to phase `target`, its text without the marker. */
|
|
133
|
+
type DeferredItem = {
|
|
134
|
+
text: string;
|
|
135
|
+
target: string;
|
|
136
|
+
};
|
|
137
|
+
/** An open checkbox whose phase arrow is not at the end of its line (1-based), with the form the parser reads. */
|
|
138
|
+
type MisplacedDeferral = {
|
|
139
|
+
line: number;
|
|
140
|
+
target: string;
|
|
141
|
+
corrected: string;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* `touched` is set by the phase source when the worktree's ticks differ from the base branch's. `deferred` holds
|
|
145
|
+
* the checkboxes moved to another phase; they are not among `items`, so they count neither as open nor as done.
|
|
146
|
+
*/
|
|
147
|
+
type PlanPhase = {
|
|
148
|
+
id: string;
|
|
149
|
+
title: string;
|
|
150
|
+
items: ChecklistItem[];
|
|
151
|
+
deferred?: DeferredItem[];
|
|
152
|
+
touched?: true;
|
|
153
|
+
};
|
|
154
|
+
/** A phase heading with its 1-based line, the lower-case id and the title. */
|
|
155
|
+
type PhaseHeading = {
|
|
156
|
+
line: number;
|
|
157
|
+
id: string;
|
|
158
|
+
title: string;
|
|
159
|
+
};
|
|
160
|
+
/** The line that opens a phase's review gate: `**Review-Gate:**`, `**Review gate** (…)`. */
|
|
161
|
+
declare const isReviewGateLine: (line: string) => boolean;
|
|
162
|
+
/** A heading of level three or higher, which ends the section of a phase. */
|
|
163
|
+
declare const endsPhase: (line: string) => boolean;
|
|
164
|
+
declare const isCheckboxLine: (line: string) => boolean;
|
|
165
|
+
declare const isOpenCheckboxLine: (line: string) => boolean;
|
|
166
|
+
declare const phaseHeadingPattern: (language: PlanLanguage) => RegExp;
|
|
167
|
+
/**
|
|
168
|
+
* The phase an open checkbox line is moved to with `→ P<n>` at its end; null for any other line, a ticked box,
|
|
169
|
+
* a ✅/⬜ table row, and an arrow to the box's own phase `phaseId`. The one rule the parser and the tally share.
|
|
170
|
+
*/
|
|
171
|
+
declare const deferralTarget: (line: string, phaseId: string) => string | null;
|
|
172
|
+
/**
|
|
173
|
+
* Open checkboxes that carry `→ P<n>` somewhere other than at the end of the line. `deferralTarget` reads the arrow
|
|
174
|
+
* only there, so such a box counts as open in its own phase without a word; `jh check` refuses it. In an
|
|
175
|
+
* open checkbox the phase arrow stands only at the end, also where it would be meant as prose (`→ P2 prüfen`).
|
|
176
|
+
*/
|
|
177
|
+
declare const misplacedDeferrals: (markdown: string) => MisplacedDeferral[];
|
|
178
|
+
/** Every phase heading of a plan, `### Phase <id>` and `## P<id> — title` alike, with its 1-based line. */
|
|
179
|
+
declare const phaseHeadings: (markdown: string, language: PlanLanguage) => PhaseHeading[];
|
|
180
|
+
/**
|
|
181
|
+
* Every `### Phase <id>` section, and every `## <id> — title` section, with its checkboxes. A
|
|
182
|
+
* section runs to the next heading of level three or higher, so a review-gate list or a `####`
|
|
183
|
+
* sub-heading inside the phase still counts. A phase without checkboxes of its own that points at
|
|
184
|
+
* a section (``Siehe `## Dokumentation` ``) counts that section's items, so it is done when the
|
|
185
|
+
* section is. An open checkbox ending in `→ P<n>` is kept under `deferred` and listed in phase `<n>` as open.
|
|
186
|
+
*/
|
|
187
|
+
declare const parsePlanPhases: (markdown: string, language: PlanLanguage) => PlanPhase[];
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* A row of the dependency table. `after` holds the phases it waits for, `external` the entries that name no phase
|
|
191
|
+
* (`User: Zuruf`) or a range that cannot be expanded; `writes` are the paths of the writes cell (`''` is the whole
|
|
192
|
+
* repository), `writesLike` the phases whose sets the cell takes over (`wie 15 und 16`); `serialMarkers` are the
|
|
193
|
+
* entries of the marker cell that keep two phases apart.
|
|
194
|
+
*/
|
|
195
|
+
type PhaseDependency = {
|
|
196
|
+
id: string;
|
|
197
|
+
after: string[];
|
|
198
|
+
external: string[];
|
|
199
|
+
writes: string[];
|
|
200
|
+
writesLike: string[];
|
|
201
|
+
serialMarkers: string[];
|
|
202
|
+
};
|
|
203
|
+
/** A phase heading (1-based line) the dependency table has no row for. */
|
|
204
|
+
type PhaseWithoutRow = PhaseHeading;
|
|
205
|
+
/**
|
|
206
|
+
* The rows of the plan's dependency table (`### Abhängigkeiten und Parallelisierung`); null when the plan has no
|
|
207
|
+
* such table or the table lacks one of its three columns, so a plan that never had one is not asked for rows.
|
|
208
|
+
*/
|
|
209
|
+
declare const parseDependencyTable: (markdown: string, language: PlanLanguage) => PhaseDependency[] | null;
|
|
210
|
+
/** The phase headings of a plan with a dependency table that the table has no row for; null for a plan without one. */
|
|
211
|
+
declare const phasesWithoutDependencyRow: (markdown: string, language: PlanLanguage) => PhaseWithoutRow[] | null;
|
|
212
|
+
/**
|
|
213
|
+
* The phases that can run side by side, as groups in table order: the first group can start now, a later one holds
|
|
214
|
+
* the ready phases that collide with an earlier group's members. A phase is offered when it is not in `doneIds`,
|
|
215
|
+
* every phase in its `Depends on` cell is, and the cell names no external gate: nothing in the plan says such a gate
|
|
216
|
+
* holds, so the phase stays out and the caller asks. Two phases share a group only when no path of one lies at or
|
|
217
|
+
* below a path of the other (a root path lies below nothing and above everything) and they share no serial marker,
|
|
218
|
+
* compared without case (a release marker does not count). A `wie N` writes cell takes the set of phase N; a phase
|
|
219
|
+
* whose set is empty, whose `wie` target is unknown, or whose `wie` chain is a cycle, cannot be shown disjoint and
|
|
220
|
+
* stays out. Whether two phases collide in content, or in the release files, is not decided here.
|
|
221
|
+
*/
|
|
222
|
+
declare const parallelGroups: (rows: readonly PhaseDependency[], doneIds: ReadonlySet<string>) => string[][];
|
|
223
|
+
/** The phases as a report names them, side by side: `P19 ∥ P20`. */
|
|
224
|
+
declare const phasesText: (phases: readonly string[]) => string;
|
|
225
|
+
/** `parallelGroups` of the plan's own dependency table and ticks (a phase is done when every box is ticked); null for a plan without a table. */
|
|
226
|
+
declare const parallelGroupsOfPlan: (markdown: string, language: PlanLanguage) => string[][] | null;
|
|
227
|
+
|
|
228
|
+
/** The review-gate box `Dokumentation aktualisiert …` (`Documentation updated …`): a gate item starting with the documentation word. */
|
|
229
|
+
declare const isDocumentationGateItem: ({ gate, text }: ChecklistItem) => boolean;
|
|
230
|
+
/** The documentation gate box is the only unticked box of the phase: everything else is done. */
|
|
231
|
+
declare const onlyDocumentationOpen: ({ items }: {
|
|
232
|
+
items: readonly ChecklistItem[];
|
|
233
|
+
}) => boolean;
|
|
234
|
+
|
|
82
235
|
type DriftFinding = {
|
|
83
236
|
file: string;
|
|
84
237
|
reason: string;
|
|
@@ -121,6 +274,12 @@ type SprintLane = {
|
|
|
121
274
|
steps: PlanStep[];
|
|
122
275
|
closed: boolean;
|
|
123
276
|
};
|
|
277
|
+
/** A row of the lanes table (1-based line) of an open lane with the text of its phases cell. */
|
|
278
|
+
type OpenLaneRow = {
|
|
279
|
+
line: number;
|
|
280
|
+
lane: string;
|
|
281
|
+
phases: string;
|
|
282
|
+
};
|
|
124
283
|
/** Sprint tables name a phase `P4`; the sidebar title prints it the same way. */
|
|
125
284
|
declare const PHASE_ID_PREFIX = "P";
|
|
126
285
|
/** The phase ids a phases cell of the lanes table names, read as `parseSprintLanes` reads them. */
|
|
@@ -138,6 +297,22 @@ declare const sprintTitleOf: (markdown: string, fallback: string) => string;
|
|
|
138
297
|
/** The repository path of a plan link, relative to the sprint document's directory. */
|
|
139
298
|
declare const resolvePlanPath: (sprintDirectory: string, href: string) => string;
|
|
140
299
|
|
|
300
|
+
/**
|
|
301
|
+
* A model as a board's model column names it: its words (`Opus 5.5` names `opus`; `claude-sonnet-5-5` names
|
|
302
|
+
* `claude` and `sonnet`, one of which is the family) and its version (`['5', '5']`).
|
|
303
|
+
*/
|
|
304
|
+
type ColumnModel = {
|
|
305
|
+
names: string[];
|
|
306
|
+
version: string[];
|
|
307
|
+
};
|
|
308
|
+
/** The models a model column names, in its order; a note in brackets (`(Plan)`) and a dash name none. */
|
|
309
|
+
declare const columnModels: (column: string) => ColumnModel[];
|
|
310
|
+
/**
|
|
311
|
+
* Whether a running model's id fits none of the models the column names, by family and version (`Opus 5.5` fits
|
|
312
|
+
* `claude-opus-5-5`, also with a date or window suffix). Knows no vendor. A column that names no model never differs.
|
|
313
|
+
*/
|
|
314
|
+
declare const differsFromColumn: (column: string, modelId: string) => boolean;
|
|
315
|
+
|
|
141
316
|
/** Per heading that carries checkboxes or table status cells: how many are done and open. */
|
|
142
317
|
type PhaseTally = {
|
|
143
318
|
title: string;
|
|
@@ -153,73 +328,10 @@ type PhaseTally = {
|
|
|
153
328
|
*/
|
|
154
329
|
declare const tallyPhases: (markdown: string, language: PlanLanguage) => PhaseTally[];
|
|
155
330
|
|
|
156
|
-
/** A checkbox of a plan. `gate` is set on the ones listed under the phase's review gate, and only on those. */
|
|
157
|
-
type ChecklistItem = {
|
|
158
|
-
done: boolean;
|
|
159
|
-
text: string;
|
|
160
|
-
gate?: true;
|
|
161
|
-
};
|
|
162
|
-
/** An open checkbox that ends in `→ P<n>`: moved on purpose to phase `target`, its text without the marker. */
|
|
163
|
-
type DeferredItem = {
|
|
164
|
-
text: string;
|
|
165
|
-
target: string;
|
|
166
|
-
};
|
|
167
|
-
/** An open checkbox whose phase arrow is not at the end of its line (1-based), with the form the parser reads. */
|
|
168
|
-
type MisplacedDeferral = {
|
|
169
|
-
line: number;
|
|
170
|
-
target: string;
|
|
171
|
-
corrected: string;
|
|
172
|
-
};
|
|
173
|
-
/**
|
|
174
|
-
* `touched` is set by the phase source when the worktree's ticks differ from the base branch's. `deferred` holds
|
|
175
|
-
* the checkboxes moved to another phase; they are not among `items`, so they count neither as open nor as done.
|
|
176
|
-
*/
|
|
177
|
-
type PlanPhase = {
|
|
178
|
-
id: string;
|
|
179
|
-
title: string;
|
|
180
|
-
items: ChecklistItem[];
|
|
181
|
-
deferred?: DeferredItem[];
|
|
182
|
-
touched?: true;
|
|
183
|
-
};
|
|
184
|
-
/** The line that opens a phase's review gate: `**Review-Gate:**`, `**Review gate** (…)`. */
|
|
185
|
-
declare const isReviewGateLine: (line: string) => boolean;
|
|
186
|
-
/** A heading of level three or higher, which ends the section of a phase. */
|
|
187
|
-
declare const endsPhase: (line: string) => boolean;
|
|
188
|
-
declare const isCheckboxLine: (line: string) => boolean;
|
|
189
|
-
declare const isOpenCheckboxLine: (line: string) => boolean;
|
|
190
|
-
declare const phaseHeadingPattern: (language: PlanLanguage) => RegExp;
|
|
191
|
-
/**
|
|
192
|
-
* The phase an open checkbox line is moved to with `→ P<n>` at its end; null for any other line, a ticked box,
|
|
193
|
-
* a ✅/⬜ table row, and an arrow to the box's own phase `phaseId`. The one rule the parser and the tally share.
|
|
194
|
-
*/
|
|
195
|
-
declare const deferralTarget: (line: string, phaseId: string) => string | null;
|
|
196
|
-
/**
|
|
197
|
-
* Open checkboxes that carry `→ P<n>` somewhere other than at the end of the line. `deferralTarget` reads the arrow
|
|
198
|
-
* only there, so such a box counts as open in its own phase without a word; `jh check` refuses it. In an
|
|
199
|
-
* open checkbox the phase arrow stands only at the end, also where it would be meant as prose (`→ P2 prüfen`).
|
|
200
|
-
*/
|
|
201
|
-
declare const misplacedDeferrals: (markdown: string) => MisplacedDeferral[];
|
|
202
|
-
/**
|
|
203
|
-
* Every `### Phase <id>` section, and every `## <id> — title` section, with its checkboxes. A
|
|
204
|
-
* section runs to the next heading of level three or higher, so a review-gate list or a `####`
|
|
205
|
-
* sub-heading inside the phase still counts. A phase without checkboxes of its own that points at
|
|
206
|
-
* a section (``Siehe `## Dokumentation` ``) counts that section's items, so it is done when the
|
|
207
|
-
* section is. An open checkbox ending in `→ P<n>` is kept under `deferred` and listed in phase `<n>` as open.
|
|
208
|
-
*/
|
|
209
|
-
declare const parsePlanPhases: (markdown: string, language: PlanLanguage) => PlanPhase[];
|
|
210
|
-
|
|
211
331
|
/** A `### Phase` heading (1-based line) whose section has tasks and neither a review gate nor the line saying why not. */
|
|
212
|
-
type PhaseWithoutGate =
|
|
213
|
-
line: number;
|
|
214
|
-
id: string;
|
|
215
|
-
title: string;
|
|
216
|
-
};
|
|
332
|
+
type PhaseWithoutGate = PhaseHeading;
|
|
217
333
|
/** A row of the lanes table (1-based line) whose phases cell names no phase id. */
|
|
218
|
-
type RowWithoutPhase =
|
|
219
|
-
line: number;
|
|
220
|
-
lane: string;
|
|
221
|
-
phases: string;
|
|
222
|
-
};
|
|
334
|
+
type RowWithoutPhase = OpenLaneRow;
|
|
223
335
|
/**
|
|
224
336
|
* A `### Phase` heading (1-based line) whose tasks are all ticked on the base branch while its own section still
|
|
225
337
|
* has open checkboxes not moved on with `→ P<n>` (`openLines`, 1-based).
|
|
@@ -246,10 +358,8 @@ declare const hasLanesTable: (markdown: string, language: PlanLanguage) => boole
|
|
|
246
358
|
*/
|
|
247
359
|
declare const mergedPhasesWithOpenBoxes: (markdown: string, base: string, language: PlanLanguage) => MergedPhaseWithOpenBoxes[];
|
|
248
360
|
/**
|
|
249
|
-
* The rows of
|
|
250
|
-
*
|
|
251
|
-
* as `parseSprintLanes` reads it (its first table, a lane closed when any of its rows says so); rows of a closed
|
|
252
|
-
* lane are history and stay out.
|
|
361
|
+
* The changed rows of open lanes whose phases cell names no phase id (`P10c`), so neither the view nor the watcher
|
|
362
|
+
* can tie that step to a phase.
|
|
253
363
|
*/
|
|
254
364
|
declare const boardRowsWithoutPhase: (markdown: string, language: PlanLanguage, previousLines: ReadonlySet<string>) => RowWithoutPhase[];
|
|
255
365
|
|
|
@@ -286,13 +396,6 @@ declare const sumPhases: (phases: readonly PhaseProgress[]) => {
|
|
|
286
396
|
done: number;
|
|
287
397
|
total: number;
|
|
288
398
|
};
|
|
289
|
-
/**
|
|
290
|
-
* The ids of a step that show a phase of their own. An id the plan lacks (`5b`) falls back to its
|
|
291
|
-
* base phase (`5`); when the step already names that phase by its own id, or an earlier id fell
|
|
292
|
-
* back to it, the fallback would list the same tasks twice, so it is dropped. A lone fallback
|
|
293
|
-
* stays: the sprint line `P4a` finds phase 4 in the plans that have no `4a`.
|
|
294
|
-
*/
|
|
295
|
-
declare const keptPhaseIds: (phases: PlanPhase[], ids: readonly string[]) => string[];
|
|
296
399
|
/**
|
|
297
400
|
* A phase the lane ticked to the end in its worktree while the base branch does not carry those ticks yet: still
|
|
298
401
|
* the lane's work until it is merged, not a finished phase.
|
|
@@ -341,4 +444,4 @@ declare const readSprintDocument: (markdown: string, language: PlanLanguage) =>
|
|
|
341
444
|
*/
|
|
342
445
|
declare const readPhaseDependencies: (planMarkdown: string, language: PlanLanguage) => Record<string, string>;
|
|
343
446
|
|
|
344
|
-
export { ADDRESS_FORM, type ChecklistItem, type DeferredItem, type DriftFinding, LANGUAGE_NAME, type LaneProgress, type MergedPhaseWithOpenBoxes, type MisplacedDeferral, PHASE_ID_PREFIX, PLAN_LANGUAGE, PLAN_STATUS, PLAN_VOCABULARY, type PhaseProgress, type PhaseTally, type PhaseWithoutGate, type PlanHeader, type PlanLanguage, type PlanPhase, type PlanStatus, type PlanStep, type PlanVocabulary, type PlansByHref, RESPONSE_ADDRESS, type ResponseAddress, type RowWithoutPhase, SELF_MERGE_LABEL, type SprintDocument, type SprintLane, type SprintPlanRow, type SprintPlanTable, type StatusWord, type StepProgress, activeItem, boardRowsWithoutPhase, classifyStatus, countDecisions, currentPhase, currentPhaseOf, deferralTarget, endsPhase, findDrift, hasLanesTable, isCheckboxLine, isOpenCheckboxLine, isPlanLanguage, isReviewGateLine, isTickedUnmerged,
|
|
447
|
+
export { ADDRESS_FORM, APPROVAL_TEXTS, type ChecklistItem, type ColumnModel, type DeferredItem, type DriftFinding, LANGUAGE_NAME, type LaneProgress, type MergedPhaseWithOpenBoxes, type MisplacedDeferral, PHASE_CELL_LIMIT, PHASE_ID_PREFIX, PLAN_LANGUAGE, PLAN_STATUS, PLAN_VOCABULARY, PROSE_REASON, type PhaseDependency, type PhaseHeading, type PhaseProgress, type PhaseTally, type PhaseWithoutGate, type PhaseWithoutRow, type PlanHeader, type PlanLanguage, type PlanPhase, type PlanStatus, type PlanStep, type PlanVocabulary, type PlansByHref, type ProseReason, RESPONSE_ADDRESS, type ResponseAddress, type RowWithProse, type RowWithoutPhase, SELF_MERGE_LABEL, type SprintDocument, type SprintLane, type SprintPlanRow, type SprintPlanTable, type StatusWord, type StepProgress, activeItem, boardRowsWithProse, boardRowsWithoutPhase, classifyStatus, columnModels, countDecisions, currentPhase, currentPhaseOf, deferralTarget, differsFromColumn, endsPhase, findDrift, hasLanesTable, isCheckboxLine, isDocumentationGateItem, isOpenCheckboxLine, isPlanLanguage, isReviewGateLine, isTickedUnmerged, laneNameOf, laneProgress, mergedPhasesWithOpenBoxes, misplacedDeferrals, newPhasesWithoutReviewGate, onlyDocumentationOpen, parallelGroups, parallelGroupsOfPlan, parseDependencyTable, parsePlanPhases, parseSprintLanes, phaseHeading, phaseHeadingPattern, phaseHeadings, phaseIdsOfCell, phaseIdsOfPlan, phasesText, phasesWithoutDependencyRow, readPhaseDependencies, readPlanHeader, readSprintDocument, resolvePlanPath, sectionHeading, shortTitle, sprintTitleOf, sumPhases, tallyPhases, withoutRepeats };
|