jackherd 1.18.2 → 1.19.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/CHANGELOG.md +19 -0
- package/INSTALL.md +1 -1
- package/README.md +30 -25
- package/assets/icons/model.svg +1 -0
- package/dist/{chunk-N5FAOQZL.js → chunk-JDO6O3UO.js} +52 -2
- package/dist/config.d.ts +15 -2
- package/dist/config.js +22 -3
- package/dist/plan-format.d.ts +84 -1
- package/dist/plan-format.js +85 -1
- package/docs/plan-contract.md +8 -2
- package/herdr-plugin/herdr-plugin.toml +1 -1
- package/install.sh +1 -1
- package/kit/hooks/hooks/approval-gate/decision.ts +10 -11
- package/kit/hooks/hooks/approval-gate/run.ts +23 -3
- package/kit/hooks/hooks/browser-guard/decision.ts +7 -0
- package/kit/hooks/hooks/browser-guard/index.ts +50 -0
- package/kit/hooks/hooks/plain-question/arguments.ts +14 -1
- package/kit/hooks/hooks/plain-question/card.ts +102 -0
- package/kit/hooks/hooks/plain-question/form.ts +25 -9
- package/kit/hooks/hooks/plain-question/index.ts +20 -25
- package/kit/hooks/hooks/plain-question/recommendation.ts +6 -6
- package/kit/hooks/hooks/return-brief/decision.ts +29 -0
- package/kit/hooks/hooks/return-brief/index.ts +37 -0
- package/kit/hooks/hooks/return-brief/settings.ts +11 -0
- package/kit/hooks/hooks/shared/coordinator-call.ts +25 -0
- package/kit/hooks/hooks/shared/transcript.ts +9 -0
- package/kit/hooks/hooks.json +18 -1
- package/kit/review/agents/security-audit.md +1 -1
- package/kit/workflow/agents/browser-check.md +29 -0
- package/kit/workflow/skills/implement/SKILL.md +5 -3
- package/kit/workflow/skills/orchestrate/SKILL.md +36 -14
- package/kit/workflow/skills/orchestrate/references/acceptance.md +10 -9
- package/kit/workflow/skills/orchestrate/references/coordinator-clear.md +45 -0
- package/kit/workflow/skills/orchestrate/references/coordinator-handover.md +15 -12
- package/kit/workflow/skills/plan/SKILL.md +2 -0
- package/kit/workflow/skills/plan/references/template-English.md +8 -0
- package/kit/workflow/skills/plan/references/template-German.md +8 -0
- package/package.json +1 -1
- package/schemas/jackherd.schema.json +16 -0
- package/src/brief/command.ts +45 -0
- package/src/brief/lane-brief.ts +51 -0
- package/src/brief/lane-facts.ts +64 -0
- package/src/check/skill-budget-defaults.ts +13 -2
- package/src/cli.ts +1 -0
- package/src/config/schema.ts +22 -0
- package/src/lane-prompt/texts.ts +2 -2
- package/src/plan-contract/command.ts +1 -0
- package/src/plan-contract/contract.ts +28 -5
- package/src/plan-format/index.ts +1 -0
- package/src/plan-format/plan-head.ts +131 -0
- package/src/plans/active-tasks.ts +8 -1
- package/src/plans/click-hint.ts +2 -1
- package/src/plans/focus-overlay.ts +5 -2
- package/src/plans/folded-detail.ts +47 -0
- package/src/plans/lane-line.ts +86 -0
- package/src/plans/lane-reason.ts +24 -4
- package/src/plans/layout-phase.ts +4 -20
- package/src/plans/layout-summary.ts +56 -45
- package/src/plans/layout.ts +178 -44
- package/src/plans/port-listening.ts +25 -0
- package/src/plans/selection.ts +11 -0
- package/src/plans/snapshot.ts +27 -9
- package/src/plans/task-checklist.ts +57 -0
- package/src/plans/texts.ts +34 -9
- package/src/resume/command.ts +40 -6
- package/src/resume/coordinator-read.ts +136 -0
- package/src/resume/state.ts +163 -0
- package/src/resume/texts.ts +6 -0
- package/src/sync/render.ts +5 -1
- package/src/vocabulary/index.ts +74 -0
- package/src/watch/clear-moment.ts +228 -0
- package/src/watch/command.ts +92 -8
- package/src/watch/lane-report.ts +5 -1
- package/src/watch/reference-paths.ts +8 -4
- package/src/watch/watch-events.ts +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
What changed for people who use jackherd, newest first.
|
|
4
4
|
|
|
5
|
+
## 1.19.0
|
|
6
|
+
|
|
7
|
+
- **The coordinator clears its context at quiet moments.** The watcher prints `coordinator clear <n>k` once your coordinator's context reaches `plans.context.coordinator.clearTokens` (250 000 by default), or `clearAfterMergeTokens` (150 000) after a merge with the board written afterwards, and only when no dialog is open, nothing unread waits, no lane is blocked or has a question not yet shown, no approval waits and no PR with self-merge is open. Without your own `clearTokens` a lower `warnTokens` moves it just below that; one you set at or above `warnTokens` is refused. `coordinator warn` now points to clearing, and the hand-over with a note stays for `coordinator alert`. Run `jh sync` to get the skill texts.
|
|
8
|
+
- **`jh resume --coordinator` lists what a cleared chat takes up.** Lanes with their status and open questions, orders without a report, open PRs, approvals, what waits on you, appointments and standing approvals, each with its place and a count, read from files, herdr and `gh`. `jh resume --clear-line` prints the first input of that chat. `jh resume` without arguments, the restart after a crash, is unchanged.
|
|
9
|
+
- **Browser checks run in a helper.** Every look in the browser now goes to the new `browser-check` agent, which looks without writing, saves its screenshots as files and returns findings and paths, so no screenshot stays in the coordinator's context. The new `browser-guard` hook refuses the Chrome extension in the coordinator's main context; subagents, lanes and sessions outside the herd pass. A look that needs page scripts goes to the lane. Run `jh sync` to get the agent and the hook.
|
|
10
|
+
- **An answer settles a retry too.** When a request older than 30 minutes made the approval gate open a new one for the same call, an answer naming the older one left the new one open for up to 30 minutes: it held up a clear and stood in `jh resume --coordinator`. An answer naming either request now claims every open one of that call, and the newest answer to a call decides, so an older approval can no longer pass a retry after you denied the newer request.
|
|
11
|
+
- **A session without `SendUserFile` still gets the screenshots across.** The coordinator gives the user the absolute paths instead, without looking at the images. The tool exists only in some session kinds.
|
|
12
|
+
- **Clearing and what outlives it.** The old chat's watcher stream and background tasks outlive `/clear`; starting the new watcher ends the old stream with `superseded by <pid>`. Keep `clearTokens` well above the fill of a new coordinator chat, about 100 000, or the coordinator clears again within minutes. The default of 250 000 is not affected.
|
|
13
|
+
- **A folded lane line opens with its status and how long ago the lane last did anything.** It reads `needs you`, `blocked` or `running` and the age (`needs you 3 min`), then the question to you, what the lane waits on, or its step. The plan's short title and the phase as `P2/5` with its name follow, and the plan is the first part to give way in a narrow pane. A waiting lane's other questions are counted in words (`+2 questions`), a lane without a plan shows its branch, and the head of the Lanes block says `3 need you`. `blocked` names a row of Your turn or the lane's starts-after cell; a lane that rests without a known reason keeps `idle · no reason`, and a lane with no running phase shows no age. `?` lists the new marks.
|
|
14
|
+
- **The herd shows a lane's dev server.** An open lane shows `:3100 ↗` on the line of its branch while a server listens on the port its board row names; a click opens `http://localhost:3100` and does not fold the lane. With no port or no listener there is no badge. The herd checks the ports once per refresh, in parallel, with at most 150 ms for each.
|
|
15
|
+
- **An open lane lists a phase's tasks as a checklist.** The tasks stand in plan order, ticked above, the running one marked in the list, the ones to come below. Above seven tasks the list shows a window around the running one, and one count row above and one below (`… 9 more`); a click on either opens the whole list. The running task is the one an agent reported; without a report, the first open task of a phase the lane runs counts as running (`◌`).
|
|
16
|
+
- **`jh brief` tells you in three lines per lane what it is for, where it stands and what it needs from you.** It reads each open lane's plan from its "For you" head. When you come back after `plans.briefAfterMinutes` minutes without a prompt (60 by default, 0 turns it off), the new `return-brief` hook has Jack show the brief before anything else. Run `jh sync` to get the hook.
|
|
17
|
+
- **A lane's report reads the same every time.** `/jh-implement` asks the lane for five lines, each opening with its field: goal, phase (`2/5`), result with its numbers, what it needs from you, next step, in the language of your plan. Run `jh sync` to get the skill text.
|
|
18
|
+
- **A dialog is no longer sent back for lacking a recommended option.** This replaces the rule from 1.17.0: the `plain-question` hook still accepts the recommendation mark on the first option, `(recommended)` or `(Empfohlen)`, but a dialog without it passes. Run `jh sync` to get the hook.
|
|
19
|
+
- **The security audit runs on the planning model.** `/jh-plan` promises that review gates with `/security-audit` get the strongest model, but the agent ran on the review model (Sonnet by default). It now runs on `models.plan`. If you set `models.plan` and `models.review` to different models, the audit now gets the planning one; `jh sync` brings in the agent, and `models.plan` stays the setting to change.
|
|
20
|
+
- **The README shows the model choice.** A benefit block says that every phase names its model, and the model section says that effort and the advisor come from Claude Code and are inherited by lanes and subagents. The resume block now leads with what it saves you.
|
|
21
|
+
- **The decision card sits in the dialog itself.** A question that asks for a decision now carries its card, the situation and what each option does, inside the dialog instead of in the text above it. The `plain-question` hook checks the question and the previews, and sends back a dialog whose card is missing or malformed. Run `jh sync` to get the hook and the skill texts.
|
|
22
|
+
- **A plan opens with a "For you" head.** Both plan templates start with five lines (what changes for you, status, your open decisions, try it now, next step), `/implement` keeps them current at each phase boundary, and `jh plan check` reports them as a fifth line (`present`, `missing` or `stale`). It is a note only: the exit code does not change, so plans written before the head keep passing.
|
|
23
|
+
|
|
5
24
|
## 1.18.2
|
|
6
25
|
|
|
7
26
|
- **`jh lane close` runs without a permission prompt.** The command already refuses, changing nothing, when anything could be lost (PR not merged or tree differs from the merge commit, a file the worktree removal would delete, an agent at work, a lock), in a real run as in a dry run, so the six ask rules before it added only friction. `jh sync` removes them from your `.claude/settings.json`; the coordinator still closes only lanes it started or you named.
|
package/INSTALL.md
CHANGED
|
@@ -55,7 +55,7 @@ When `init` creates a new config, it asks:
|
|
|
55
55
|
| Use it when | the team shares the kit through the repository | the repository must stay untouched, not even untracked files |
|
|
56
56
|
| Lives in | the project's `.claude/` | `~/.claude/` |
|
|
57
57
|
| Skill names | `/plan`, `/implement`, `/orchestrate`, … | `/jh-plan`, `/jh-implement`, `/jh-orchestrate`, … |
|
|
58
|
-
| Hooks | `git-guard`, `watch-guard`, `lane-start-guard`, `merge-guard`, `approval-gate`, `model-gate`, `model-log`, `ask-hint`, `open-question`, `plain-question`, `sent-file`, `format-on-edit` | none; `init --global` offers only a `SessionStart` update notice |
|
|
58
|
+
| Hooks | `git-guard`, `watch-guard`, `lane-start-guard`, `merge-guard`, `approval-gate`, `model-gate`, `model-log`, `ask-hint`, `open-question`, `plain-question`, `sent-file`, `browser-guard`, `format-on-edit` | none; `init --global` offers only a `SessionStart` update notice |
|
|
59
59
|
| Config | `.jackherd/config.json` | `~/.jackherd/config.json`, used where a repository has none |
|
|
60
60
|
| Update | `jh sync` | `jh update` |
|
|
61
61
|
|
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<p>
|
|
2
|
-
<img alt="jackherd: a black and white Shih Tzu in a turquoise bandana, three lanes running from him to three agent nodes" src="https://unpkg.com/jackherd@1.
|
|
2
|
+
<img alt="jackherd: a black and white Shih Tzu in a turquoise bandana, three lanes running from him to three agent nodes" src="https://unpkg.com/jackherd@1.19.0/assets/branding/jackherd-logo-outline.svg" width="340">
|
|
3
3
|
<br>
|
|
4
4
|
</p>
|
|
5
5
|
|
|
6
|
-
[](https://www.npmjs.com/package/jackherd) [](https://www.npmjs.com/package/jackherd) [](https://www.npmjs.com/package/jackherd?activeTab=dependencies) [](https://unpkg.com/jackherd/INSTALL.md) [](https://unpkg.com/jackherd/INSTALL.md)<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.
|
|
6
|
+
[](https://www.npmjs.com/package/jackherd) [](https://www.npmjs.com/package/jackherd) [](https://www.npmjs.com/package/jackherd?activeTab=dependencies) [](https://unpkg.com/jackherd/INSTALL.md) [](https://unpkg.com/jackherd/INSTALL.md)<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.19.0/assets/icons/space.svg">
|
|
7
7
|
|
|
8
8
|
# Jack herds your coding agents.
|
|
9
9
|
|
|
@@ -15,27 +15,29 @@ For developers who'd rather decide than supervise.
|
|
|
15
15
|
curl -fsSL https://unpkg.com/jackherd/install.sh | sh
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Then `/jh-start` in a repository, and Jack offers your first plan. → [Quickstart](#quickstart)<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.
|
|
18
|
+
Then `/jh-start` in a repository, and Jack offers your first plan. → [Quickstart](#quickstart)<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.19.0/assets/icons/space.svg">
|
|
19
19
|
|
|
20
20
|
<p>
|
|
21
|
-
<img src="https://unpkg.com/jackherd@1.
|
|
21
|
+
<img src="https://unpkg.com/jackherd@1.19.0/docs/workflow-dark.svg" width="720" alt="jackherd in herdr: a lane hits a question, Jack asks you as a choice, you pick, and the lane works on while the herd view counts its progress.">
|
|
22
22
|
<br>
|
|
23
|
-
<sub>Jack and his lanes in <a href="https://herdr.dev/">herdr</a>, a terminal for coding agents (recommended). Without it, one Claude Code session builds with subagents.</sub><br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.
|
|
23
|
+
<sub>Jack and his lanes in <a href="https://herdr.dev/">herdr</a>, a terminal for coding agents (recommended). Without it, one Claude Code session builds with subagents.</sub><br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.19.0/assets/icons/space.svg">
|
|
24
24
|
</p>
|
|
25
25
|
|
|
26
|
-
<p><img src="https://unpkg.com/jackherd@1.
|
|
26
|
+
<p><img src="https://unpkg.com/jackherd@1.19.0/assets/icons/lanes.svg" width="24" height="34" align="middle" alt=""> <b>Parallel where it pays.</b><br>Phases that don't collide run side by side, each lane on its own branch and worktree. Jack keeps the merge order and has the others rebase.</p>
|
|
27
27
|
|
|
28
|
-
<p><img src="https://unpkg.com/jackherd@1.
|
|
28
|
+
<p><img src="https://unpkg.com/jackherd@1.19.0/assets/icons/decide.svg" width="24" height="34" align="middle" alt=""> <b>You make the calls.</b><br>Commits, pushes and merges wait for your approval. Jack merges on green checks only where you said so: one pull request, or a plan's for up to 24 hours. The guards catch mistakes, not intent; a hard boundary takes branch protection.</p>
|
|
29
29
|
|
|
30
|
-
<p><img src="https://unpkg.com/jackherd@1.
|
|
30
|
+
<p><img src="https://unpkg.com/jackherd@1.19.0/assets/icons/bark.svg" width="24" height="34" align="middle" alt=""> <b>Jack barks.</b><br>A lane gets stuck, a check goes red, a decision needs you: Jack steps in and brings you only what's yours to decide. The herd view shows where every lane stands.</p>
|
|
31
31
|
|
|
32
|
-
<p><img src="https://unpkg.com/jackherd@1.
|
|
32
|
+
<p><img src="https://unpkg.com/jackherd@1.19.0/assets/icons/skills.svg" width="24" height="34" align="middle" alt=""> <b>Works with your skills.</b><br>Keep your own skills: a lane builds with whichever one you pick. Plans written elsewhere run too, once Jack fills in what they're missing.</p>
|
|
33
33
|
|
|
34
|
-
<p><img src="https://unpkg.com/jackherd@1.
|
|
34
|
+
<p><img src="https://unpkg.com/jackherd@1.19.0/assets/icons/ear.svg" width="24" height="34" align="middle" alt=""> <b>Jack listens.</b><br>Review comments on a lane's pull request go back to that lane, which fixes them with a test. <code>/jh-follow</code> brings in anything a CLI or an API can read as JSON: tickets, error logs, status pages.</p>
|
|
35
35
|
|
|
36
|
-
<p><img src="https://unpkg.com/jackherd@1.
|
|
36
|
+
<p><img src="https://unpkg.com/jackherd@1.19.0/assets/icons/model.svg" width="24" height="34" align="middle" alt=""> <b>The right model for each phase.</b><br>Every phase names its model: the stronger one where a mistake is expensive (data, security, a migration), the cheaper one for the rest. Lanes start on it, and a hook refuses to start a phase's subagent on a weaker one.</p>
|
|
37
37
|
|
|
38
|
-
<p><img src="https://unpkg.com/jackherd@1.
|
|
38
|
+
<p><img src="https://unpkg.com/jackherd@1.19.0/assets/icons/bowl.svg" width="24" height="34" align="middle" alt=""> <b>A crash or a full context doesn't cost you the work.</b><br>Plan, board and a hand-over file hold the state, not the chat: the next session picks up where the last one stopped.</p>
|
|
39
|
+
|
|
40
|
+
<p><img src="https://unpkg.com/jackherd@1.19.0/assets/icons/plan.svg" width="24" height="34" align="middle" alt=""> <b>Lives in your repository.</b><br>Plans, board and every decision are Markdown, reviewed like code. <code>jh init</code> gives your team the same setup.<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.19.0/assets/icons/space.svg"></p>
|
|
39
41
|
|
|
40
42
|
## Quickstart
|
|
41
43
|
|
|
@@ -66,22 +68,22 @@ Then `/jh-start` in a repository, and Jack offers your first plan. → [Quicksta
|
|
|
66
68
|
/jh-orchestrate docs/plans/board-<name>/board.md
|
|
67
69
|
```
|
|
68
70
|
|
|
69
|
-
Linux and macOS are supported (Windows through WSL); the requirements are in [INSTALL.md](https://unpkg.com/jackherd/INSTALL.md). By hand (Bun 1.3+): `bun add -g jackherd` or `npm install -g jackherd`, then `jh init --global` for yourself, or `jh init` in a repository to give your team the same skills and guard hooks.<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.
|
|
71
|
+
Linux and macOS are supported (Windows through WSL); the requirements are in [INSTALL.md](https://unpkg.com/jackherd/INSTALL.md). By hand (Bun 1.3+): `bun add -g jackherd` or `npm install -g jackherd`, then `jh init --global` for yourself, or `jh init` in a repository to give your team the same skills and guard hooks.<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.19.0/assets/icons/space.svg">
|
|
70
72
|
|
|
71
73
|
## Follow anything you can query
|
|
72
74
|
|
|
73
75
|
Tickets, error logs, status pages: if a command or an API call can read it as JSON with your login, Jack can watch it. Recipes cover Jira, Linear, GitHub issues and Projects, Sentry, Google Calendar and status pages; for anything else, `/jh-follow` writes the command with you. One yes, and every change shows up like this:
|
|
74
76
|
|
|
75
|
-
<img src="https://unpkg.com/jackherd@1.
|
|
77
|
+
<img src="https://unpkg.com/jackherd@1.19.0/docs/follow-dark.svg" width="720" alt="A source (ticket, error log or status page) has a new or changed entry; jh watch reports it to Jack; Jack puts a row into Your turn, prefixed with the source's label; its [ask] button makes Jack ask you, and then a lane works it.">
|
|
76
78
|
|
|
77
|
-
The herd sums up your sources in one `Sources` line: new entries per source, or its last run, red while it fails; opened, a click opens an entry. One that needs you lands in Your turn under the source's label, [ask] has Jack look at it, and a ticket shows on the lane that works it.<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.
|
|
79
|
+
The herd sums up your sources in one `Sources` line: new entries per source, or its last run, red while it fails; opened, a click opens an entry. One that needs you lands in Your turn under the source's label, [ask] has Jack look at it, and a ticket shows on the lane that works it.<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd@1.19.0/assets/icons/space.svg">
|
|
78
80
|
|
|
79
81
|
## In detail
|
|
80
82
|
|
|
81
83
|
<details>
|
|
82
84
|
<summary><b>What Jack does on his own, and what waits for you</b></summary>
|
|
83
85
|
|
|
84
|
-
<img src="https://unpkg.com/jackherd@1.
|
|
86
|
+
<img src="https://unpkg.com/jackherd@1.19.0/docs/lanes-dark.svg" alt="Jack prompts two lanes and asks you for decisions and approvals; the lanes send questions back as text; jh watch reads lane state, pull requests and checks and wakes Jack.">
|
|
85
87
|
|
|
86
88
|
| On his own | After your approval | Never |
|
|
87
89
|
| --- | --- | --- |
|
|
@@ -116,7 +118,7 @@ The guards catch mistakes, not intent; for that, use branch protection. The hook
|
|
|
116
118
|
|
|
117
119
|
A **plan** is Markdown with phases, checkbox tasks, a model and a review gate per phase. A **board** lists the lanes of one or more plans: which phases each lane builds, on which model, after what. A **lane** is one agent session in its own git worktree (a second checkout of your repository), and **Jack** is the session in the main checkout that runs `/jh-orchestrate` on a board.
|
|
118
120
|
|
|
119
|
-
<img src="https://unpkg.com/jackherd@1.
|
|
121
|
+
<img src="https://unpkg.com/jackherd@1.19.0/docs/skills-dark.svg" alt="Your own plan or an issue is adopted (Jack adds what is missing, you see the diff) and goes to /jh-orchestrate; /jh-grill hands decisions to /jh-plan; /jh-plan feeds /jh-orchestrate or a single /jh-implement, which your own skill can replace; /jh-implement ends in /jh-pre-commit, which runs the reviewers; /jh-diagnose hands a red command to /jh-implement.">
|
|
120
122
|
|
|
121
123
|
| Skill | Does |
|
|
122
124
|
| --- | --- |
|
|
@@ -153,10 +155,10 @@ It has five blocks, top down. **Your turn** holds everything that waits on you,
|
|
|
153
155
|
|
|
154
156
|
▸ Sources sentry-errors 3 entries, 1 new · status-page 20 min ago
|
|
155
157
|
|
|
156
|
-
▾ Lanes · 3 1
|
|
158
|
+
▾ Lanes · 3 1 needs you · 1 idle ──────────────────────────────────────
|
|
157
159
|
▾ ◆ search-ui blocked ██████░░░░ 6/9
|
|
158
160
|
|
|
159
|
-
⎇ feat/search-ui ↑1 ±4 · Opus 5.5
|
|
161
|
+
⎇ feat/search-ui ↑1 ±4 · Opus 5.5 :3100 ↗ 🥣 62 %
|
|
160
162
|
[📄 Plan] [📡 PROJ-123 · In Progress] [🔗 Mockup] +1
|
|
161
163
|
|
|
162
164
|
P3 Docs · 4 min ago · gate ████████░░ 2/3
|
|
@@ -166,7 +168,7 @@ It has five blocks, top down. **Your turn** holds everything that waits on you,
|
|
|
166
168
|
▸ next P4
|
|
167
169
|
▸ done P2
|
|
168
170
|
|
|
169
|
-
▸ ○ checkout-fee
|
|
171
|
+
▸ ○ checkout-fee needs you 2 h · Ship it… · P2/5 Fees ↗ #42 💬 2
|
|
170
172
|
▸ ● search-index ████████░░ 4/5
|
|
171
173
|
● Rebuild the index on deploy
|
|
172
174
|
|
|
@@ -181,11 +183,11 @@ How the herd reads the board:
|
|
|
181
183
|
|
|
182
184
|
- **Your turn** takes its rows from the board's open questions, the questions a session left in its dialog, the files and Artifacts sent to you, the board's appointments and its next section. What blocks a lane comes first, then the newest; five rows show, then `▸ n more · k older than 7 days`. Appointments show for the next seven days, three of them, then `▸ n later`. `unblocks …` under a row names the lanes it frees (the board's Unblocks column). The head keeps the count, how many rows block lanes and the age of the oldest, folded too. At the selected row, `[ask]` asks Jack to put the question to you, `[done]` closes the row, `[run]` asks Jack to run an appointment now and `[move]` to ask you for a new time; enter never presses `[done]`. A row goes once its board row is closed or after `jh waiting close <id>`.
|
|
183
185
|
- **Sources** shows, per source that is no ticket, its entries and how many are new, or when it last ran: amber with a new entry that is not in Your turn yet, red while it fails. Opened, its entries stand newest first by the time they show, and a click on an entry opens it; `↑ in your turn` marks one a row of Your turn asks about.
|
|
184
|
-
- **Lanes** opens at the start. A lane that works or is blocked opens by itself only when it first appears; after that, opening and folding are yours. A lane symbol says the state (`●` working, `◆` blocked, `◉` the agent finished its answer, `○` idle, `(·) no agent` a worktree nobody works in); only blocked wears its word. A
|
|
186
|
+
- **Lanes** opens at the start. A lane that works or is blocked opens by itself only when it first appears; after that, opening and folding are yours. A lane symbol says the state (`●` working, `◆` blocked, `◉` the agent finished its answer, `○` idle, `(·) no agent` a worktree nobody works in); only blocked wears its word. A folded lane line opens with its status and the age of its last activity: `needs you 3 min` and the first open question of its report (`+2 questions` counts the others), `blocked 3 min` and what it waits on (a row of Your turn, or the lane's starts-after cell), or `running 3 min` and its step. The plan's short title and the phase as `P2/5` with its name follow, and the plan is the first part to give way in a narrow pane. A resting lane without a known reason keeps `idle · no reason`. `:3100 ↗` on the branch line of an open lane opens its dev server, while one listens on the port its board row names.
|
|
185
187
|
- **Waiting** lists the lanes not started yet: no worktree yet, something left to do, and what each starts after; it starts folded. Finished lanes (cleaned up, or every phase they name ticked) are not shown.
|
|
186
|
-
- **An open lane** shows, top down: its branch, the model and how long it idles; its link chips on one line, `+n` for the rest; its pull requests; the phases it works on, each with its bar and its
|
|
188
|
+
- **An open lane** shows, top down: its branch, the model and how long it idles; its link chips on one line, `+n` for the rest; its pull requests; the phases it works on, each with its bar and its tasks as a checklist in plan order (ticked above, the running one marked, the ones to come below; above seven tasks a window around the running one, with `… n more` above and below to open the whole list); `▸ next` with the phases that wait, as ranges; `▸ done` with the finished ones. A lane shows only the phases its board rows name; a lane without a worktree reads its plan from the main checkout. A folded lane shows a reported task below its line while it has the mouse; behind each pull request badge it shows the checks, also while the lane rests: `✓ checks`, `checks running`, `✗ test +1` with the first red check, `draft` for a draft.
|
|
187
189
|
- **A phase runs** when an agent reports working on it, one of its boxes was ticked in the last 20 minutes, or some of its tasks are ticked. A phase whose run was merged and that the lane's newest board row no longer names waits behind the others in `▸ next`, its open boxes left open on purpose. `n min ago` counts since the last tick or report; `· gate` means only the review gate is open, `docs open` only the documentation box.
|
|
188
|
-
- **A running task** carries `●` when an agent reported it, from its task list or `jh task`; its text stands in teal and a light band runs over it (`plans.shimmer: false`, `NO_COLOR` and `--once` keep it still). `◌` in dim
|
|
190
|
+
- **A running task** carries `●` when an agent reported it, from its task list or `jh task`; its text stands in teal and a light band runs over it (`plans.shimmer: false`, `NO_COLOR` and `--once` keep it still). `◌` is a guess: in dim, a task guessed from the words of the lane's log; shimmering like a reported one, the first open task of a phase the lane runs when no agent reported one. `now: …` is a reported task no plan task names, `Subagent: …` a running subagent on no phase; a running review sits on the gate box that names it, in the phase it names or else the lane's current one. With several agents in a lane, each task carries its agent's name, dim, at the right edge.
|
|
189
191
|
- **What a working lane does right now:** under its lane line, open or folded, a dim `↳` line shows the last action from the agent's session log, a tool with its target (`↳ Read plans/layout.ts`) or the start of its answer, and each running subagent adds one, indented and led by its task (where `Subagent: …` says what it works on, `↳` says what it does); the lines go when the lane rests.
|
|
190
192
|
- **Counts and colours:** the bar is the progress over the lane's plans; `n/m` counts checkboxes, `n/m ph` finished phases, green when all are ticked; `–` is a phase without checkboxes, `?` one not in the plan. `🥣` is the share of the context window used, on a folded lane only once it warns. `Sonnet ≠ Opus` in amber says a phase's subagent ran on another model than the plan's. `stale?` in Backlog marks a plan file unchanged on the base branch for 14 days.
|
|
191
193
|
- **Chips:** `🔗` an Artifact, `⑂` a pull request or issue, `◈` Figma, `📡` a ticket with its status (`📡 n` in amber on a folded lane when tickets are new), `private` where the plan says so. After the lane: `↗` a pull request with its checks, `💬` new feedback, `✋` changes requested, `🌐` a preview. ctrl+click opens a chip's link.
|
|
@@ -207,7 +209,9 @@ A source that is yours alone, such as your calendar, goes into `~/.jackherd/sour
|
|
|
207
209
|
<details>
|
|
208
210
|
<summary><b>Which model runs each phase</b></summary>
|
|
209
211
|
|
|
210
|
-
Each phase in the plan names its model: the planning model (Opus by default) where a mistake is expensive, such as data, security or a migration, and the cheaper implementation model (Sonnet by default) for everything else. `/jh-implement` and Jack start each phase on its model. In a project install, a hook stops a phase's subagent started on a weaker one, and the watcher tells Jack about a lane that runs on one. Set the models per role under `models` in the config.
|
|
212
|
+
Each phase in the plan names its model: the planning model (Opus by default) where a mistake is expensive, such as data, security or a migration, and the cheaper implementation model (Sonnet by default) for everything else. `/jh-implement` and Jack start each phase on its model. In a project install, a hook stops a phase's subagent started on a weaker one, and the watcher tells Jack about a lane that runs on one. The security audit runs on the planning model too. Set the models per role under `models` in the config.
|
|
213
|
+
|
|
214
|
+
jackherd sets the model, not the effort and not the advisor: those come from Claude Code. Lanes and subagents inherit what you set there (`/effort`, `/advisor`).
|
|
211
215
|
|
|
212
216
|
</details>
|
|
213
217
|
|
|
@@ -222,12 +226,13 @@ Each phase in the plan names its model: the planning model (Opus by default) whe
|
|
|
222
226
|
| `jh check` | types, lint and tests of what you touched, plus the plan and board checks (`--skip-slow`, `--parallel <plan>`) |
|
|
223
227
|
| `jh herd` | the live view (`--once`, `--lane <name>`) |
|
|
224
228
|
| `jh watch` | the watcher Jack runs |
|
|
225
|
-
| `jh resume` | after herdr restarts, wakes the coordinator and the lanes that worked when the machine crashed; runs once per crash and only when the watcher's record shows no `stoppedAt`. Stopping the watcher before quitting herdr prevents it. |
|
|
229
|
+
| `jh resume` | after herdr restarts, wakes the coordinator and the lanes that worked when the machine crashed; runs once per crash and only when the watcher's record shows no `stoppedAt`. Stopping the watcher before quitting herdr prevents it. With `--coordinator` it lists what a coordinator takes up after `/clear` (lanes, PRs, approvals, what waits on you, appointments, standing approvals), from files and herdr; `--clear-line` prints the first input of that chat. |
|
|
226
230
|
| `jh secret` | keeps a personal source's secrets in the system keychain (`set <NAME>`, `list`, `delete <NAME>`); `list` shows which are set, never a value |
|
|
227
231
|
| `jh lane prompt <lane>` | writes a lane's first prompt from its board row and its plan (`--out`, `--handover`); your additions below the marker line at its end stay |
|
|
228
232
|
| `jh lane close <lane>` | removes a finished lane: agent, worktree, herdr workspace and branch, and marks the board; first checks that nothing is lost, and refuses with every reason; `--dry-run` only checks. Runs without a prompt. |
|
|
229
233
|
| `jh preview <file>` | renders a Markdown file through the GitHub API into a preview in GitHub and npm style |
|
|
230
234
|
| `jh waiting` | the files and Artifacts sent to you that you have not answered yet (`close <id>…` or `close --all` once you have) |
|
|
235
|
+
| `jh brief` | three lines for each open lane of the board: its goal, its status and what it needs from you, read from the head of its plan (`--board <board.md>` names the board); after `plans.briefAfterMinutes` (default 60, 0 is off) without a prompt, the `return-brief` hook asks Jack to show it first |
|
|
231
236
|
| `jh context` | how full an agent's context is, as JSON; `--usage [--since 24h\|7d\|<date>]` the tokens a lane used instead (Jack's with `--coordinator`) |
|
|
232
237
|
| `jh config` | the commands and the base branch the repository uses; a missing value goes to stderr with the line to set, and `jh config <key>` for an unset value exits 3 |
|
|
233
238
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26.18 37.09" width="24" height="34" fill="none" stroke-linecap="round" stroke-linejoin="round"><g transform="translate(-3.431 -3.161) scale(1.236)" stroke-width="1.416"><g stroke="#6F818A"><path d="M4 8h16"/><path d="M4 16h16"/></g><circle stroke="#04A5AD" fill="#04A5AD" cx="15.5" cy="8" r="2"/><circle stroke="#6F818A" cx="8.5" cy="16" r="2"/></g></svg>
|
|
@@ -27,6 +27,20 @@ var RECOMMENDED_MARK = {
|
|
|
27
27
|
[PLAN_LANGUAGE.en]: "(recommended)",
|
|
28
28
|
[PLAN_LANGUAGE.de]: "(Empfohlen)"
|
|
29
29
|
};
|
|
30
|
+
var CARD_FIELDS = {
|
|
31
|
+
[PLAN_LANGUAGE.en]: {
|
|
32
|
+
topic: "What this is about",
|
|
33
|
+
consequences: "What each option leads to",
|
|
34
|
+
ifUndecided: "If you do nothing",
|
|
35
|
+
readMore: "Details"
|
|
36
|
+
},
|
|
37
|
+
[PLAN_LANGUAGE.de]: {
|
|
38
|
+
topic: "Worum es geht",
|
|
39
|
+
consequences: "Folgen je Option",
|
|
40
|
+
ifUndecided: "Wenn du nichts entscheidest",
|
|
41
|
+
readMore: "Nachlesen"
|
|
42
|
+
}
|
|
43
|
+
};
|
|
30
44
|
var LANE_PROMPT_OPENING = {
|
|
31
45
|
[PLAN_LANGUAGE.en]: "You are the lane",
|
|
32
46
|
[PLAN_LANGUAGE.de]: "Du bist die Spur"
|
|
@@ -82,6 +96,23 @@ var PLAN_STATUS = {
|
|
|
82
96
|
other: "other",
|
|
83
97
|
none: "none"
|
|
84
98
|
};
|
|
99
|
+
var REPORT_FIELDS = {
|
|
100
|
+
[PLAN_LANGUAGE.en]: { goal: "Goal", phase: "Phase", result: "Result", needsYou: "Needs you", next: "Next" },
|
|
101
|
+
[PLAN_LANGUAGE.de]: {
|
|
102
|
+
goal: "Ziel",
|
|
103
|
+
phase: "Phase",
|
|
104
|
+
result: "Ergebnis",
|
|
105
|
+
needsYou: "Braucht dich",
|
|
106
|
+
next: "N\xE4chster Schritt"
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var HEAD_LINE = {
|
|
110
|
+
changes: "changes",
|
|
111
|
+
status: "status",
|
|
112
|
+
decisions: "decisions",
|
|
113
|
+
tryNow: "tryNow",
|
|
114
|
+
next: "next"
|
|
115
|
+
};
|
|
85
116
|
var PLAN_VOCABULARY = {
|
|
86
117
|
de: {
|
|
87
118
|
header: { date: "Date", status: "Status", scope: "Scope" },
|
|
@@ -94,7 +125,15 @@ var PLAN_VOCABULARY = {
|
|
|
94
125
|
lanes: "Spuren",
|
|
95
126
|
goal: "Sprintziel",
|
|
96
127
|
history: "Verlauf",
|
|
97
|
-
plans: "Pl\xE4ne"
|
|
128
|
+
plans: "Pl\xE4ne",
|
|
129
|
+
forYou: "F\xFCr dich"
|
|
130
|
+
},
|
|
131
|
+
head: {
|
|
132
|
+
changes: "Was sich f\xFCr dich \xE4ndert",
|
|
133
|
+
status: "Stand",
|
|
134
|
+
decisions: "Deine offenen Entscheidungen",
|
|
135
|
+
tryNow: "Schon ausprobieren",
|
|
136
|
+
next: "N\xE4chster Schritt"
|
|
98
137
|
},
|
|
99
138
|
columns: { dependsOn: "H\xE4ngt ab von", writes: "Schreibt", serialMarker: "Seriell-Marker" },
|
|
100
139
|
phase: "Phase",
|
|
@@ -129,7 +168,15 @@ var PLAN_VOCABULARY = {
|
|
|
129
168
|
lanes: "Lanes",
|
|
130
169
|
goal: "Sprint goal",
|
|
131
170
|
history: "History",
|
|
132
|
-
plans: "Plans"
|
|
171
|
+
plans: "Plans",
|
|
172
|
+
forYou: "For you"
|
|
173
|
+
},
|
|
174
|
+
head: {
|
|
175
|
+
changes: "What changes for you",
|
|
176
|
+
status: "Status",
|
|
177
|
+
decisions: "Your open decisions",
|
|
178
|
+
tryNow: "Try it now",
|
|
179
|
+
next: "Next step"
|
|
133
180
|
},
|
|
134
181
|
columns: { dependsOn: "Depends on", writes: "Writes", serialMarker: "Serial marker" },
|
|
135
182
|
phase: "Phase",
|
|
@@ -191,6 +238,7 @@ export {
|
|
|
191
238
|
SELF_MERGE_LABEL,
|
|
192
239
|
STANDING_APPROVAL_TEXTS,
|
|
193
240
|
RECOMMENDED_MARK,
|
|
241
|
+
CARD_FIELDS,
|
|
194
242
|
LANE_PROMPT_OPENING,
|
|
195
243
|
APPROVAL_TEXTS,
|
|
196
244
|
APPOINTMENT_VOCABULARY,
|
|
@@ -198,6 +246,8 @@ export {
|
|
|
198
246
|
WAITING_VOCABULARY,
|
|
199
247
|
isPlanLanguage,
|
|
200
248
|
PLAN_STATUS,
|
|
249
|
+
REPORT_FIELDS,
|
|
250
|
+
HEAD_LINE,
|
|
201
251
|
PLAN_VOCABULARY,
|
|
202
252
|
classifyStatus,
|
|
203
253
|
phaseHeading,
|
package/dist/config.d.ts
CHANGED
|
@@ -140,6 +140,7 @@ declare const jackherdConfigSchema: z.ZodObject<{
|
|
|
140
140
|
plans: z.ZodPrefault<z.ZodObject<{
|
|
141
141
|
fetchIntervalMinutes: z.ZodDefault<z.ZodNumber>;
|
|
142
142
|
shimmer: z.ZodDefault<z.ZodBoolean>;
|
|
143
|
+
briefAfterMinutes: z.ZodDefault<z.ZodNumber>;
|
|
143
144
|
linkKinds: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
144
145
|
pattern: z.ZodString;
|
|
145
146
|
label: z.ZodString;
|
|
@@ -150,10 +151,22 @@ declare const jackherdConfigSchema: z.ZodObject<{
|
|
|
150
151
|
alertTokens: z.ZodDefault<z.ZodNumber>;
|
|
151
152
|
windows: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodNumber>>;
|
|
152
153
|
defaultWindow: z.ZodDefault<z.ZodNumber>;
|
|
153
|
-
coordinator: z.ZodPrefault<z.ZodObject<{
|
|
154
|
+
coordinator: z.ZodPrefault<z.ZodPipe<z.ZodObject<{
|
|
154
155
|
warnTokens: z.ZodDefault<z.ZodNumber>;
|
|
155
156
|
alertTokens: z.ZodDefault<z.ZodNumber>;
|
|
156
|
-
|
|
157
|
+
clearTokens: z.ZodOptional<z.ZodNumber>;
|
|
158
|
+
clearAfterMergeTokens: z.ZodDefault<z.ZodNumber>;
|
|
159
|
+
}, z.core.$strict>, z.ZodTransform<{
|
|
160
|
+
clearTokens: number;
|
|
161
|
+
warnTokens: number;
|
|
162
|
+
alertTokens: number;
|
|
163
|
+
clearAfterMergeTokens: number;
|
|
164
|
+
}, {
|
|
165
|
+
warnTokens: number;
|
|
166
|
+
alertTokens: number;
|
|
167
|
+
clearAfterMergeTokens: number;
|
|
168
|
+
clearTokens?: number | undefined;
|
|
169
|
+
}>>>;
|
|
157
170
|
}, z.core.$strict>>;
|
|
158
171
|
tones: z.ZodPrefault<z.ZodObject<{
|
|
159
172
|
waiting: z.ZodDefault<z.ZodEnum<{
|
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-JDO6O3UO.js";
|
|
5
5
|
|
|
6
6
|
// src/config/json-schema.ts
|
|
7
7
|
import { z as z3 } from "zod";
|
|
@@ -539,12 +539,29 @@ var repositorySources = z2.array(sourceSchema).refine(hasUniqueNames, "source na
|
|
|
539
539
|
});
|
|
540
540
|
});
|
|
541
541
|
});
|
|
542
|
+
var DEFAULT_CLEAR_TOKENS = 25e4;
|
|
542
543
|
var coordinatorSchema = z2.strictObject({
|
|
543
544
|
/** Tokens in the coordinator's context from which the watcher reports `coordinator warn`. */
|
|
544
545
|
warnTokens: tokenCount.default(35e4),
|
|
545
546
|
/** Tokens in the coordinator's context from which the watcher reports `coordinator alert`. */
|
|
546
|
-
alertTokens: tokenCount.default(5e5)
|
|
547
|
-
|
|
547
|
+
alertTokens: tokenCount.default(5e5),
|
|
548
|
+
/**
|
|
549
|
+
* Tokens in the coordinator's context from which the watcher reports `coordinator clear` at a quiet moment; below
|
|
550
|
+
* `warnTokens`. Unset, 250 000, or just below `warnTokens` where a project set those lower.
|
|
551
|
+
*/
|
|
552
|
+
clearTokens: tokenCount.optional(),
|
|
553
|
+
/**
|
|
554
|
+
* Tokens in the coordinator's context from which a merge with the board written afterwards is a moment to clear too.
|
|
555
|
+
* At or above `clearTokens`, a merge adds no moment of its own.
|
|
556
|
+
*/
|
|
557
|
+
clearAfterMergeTokens: tokenCount.default(15e4)
|
|
558
|
+
}).refine(warnBelowAlert, WARN_BELOW_ALERT).refine(({ clearTokens, warnTokens }) => clearTokens === void 0 || clearTokens < warnTokens, {
|
|
559
|
+
message: "clearTokens must be below warnTokens",
|
|
560
|
+
path: ["clearTokens"]
|
|
561
|
+
}).transform(({ clearTokens, ...thresholds }) => ({
|
|
562
|
+
...thresholds,
|
|
563
|
+
clearTokens: clearTokens ?? Math.min(DEFAULT_CLEAR_TOKENS, thresholds.warnTokens - 1)
|
|
564
|
+
}));
|
|
548
565
|
var standingTool = z2.string().regex(
|
|
549
566
|
/^mcp__[A-Za-z0-9_-]+__execute_sql$/,
|
|
550
567
|
"a full MCP tool name ending in execute_sql, such as mcp__<server>__execute_sql"
|
|
@@ -703,6 +720,8 @@ var jackherdConfigSchema = z2.strictObject({
|
|
|
703
720
|
fetchIntervalMinutes: z2.number().min(0).default(5),
|
|
704
721
|
/** The running task of a folded lane shimmers in `jh herd`; `false` keeps it still. `NO_COLOR` keeps it still too. */
|
|
705
722
|
shimmer: z2.boolean().default(true),
|
|
723
|
+
/** Minutes without a prompt after which the `return-brief` hook asks the coordinator to show `jh brief` first; 0 turns it off. */
|
|
724
|
+
briefAfterMinutes: z2.number().min(0).default(60),
|
|
706
725
|
/** Links in a plan that the sprint page shows as chips; the list replaces the built-in kinds. */
|
|
707
726
|
linkKinds: z2.array(
|
|
708
727
|
z2.strictObject({
|
package/dist/plan-format.d.ts
CHANGED
|
@@ -37,6 +37,18 @@ declare const STANDING_APPROVAL_TEXTS: Record<PlanLanguage, {
|
|
|
37
37
|
* a dialog back whose first option lacks it, so it is fixed per language and not a config value.
|
|
38
38
|
*/
|
|
39
39
|
declare const RECOMMENDED_MARK: Record<PlanLanguage, string>;
|
|
40
|
+
/**
|
|
41
|
+
* The four fields of the decision card that stands in every dialog, in the question and the option previews: what it
|
|
42
|
+
* is about, what each option leads to, what happens without a decision, and where to read on. The plain question
|
|
43
|
+
* hook sends a dialog back that lacks one at the start of a line, so they are fixed per language and not a config
|
|
44
|
+
* value.
|
|
45
|
+
*/
|
|
46
|
+
declare const CARD_FIELDS: Record<PlanLanguage, {
|
|
47
|
+
topic: string;
|
|
48
|
+
consequences: string;
|
|
49
|
+
ifUndecided: string;
|
|
50
|
+
readMore: string;
|
|
51
|
+
}>;
|
|
40
52
|
/**
|
|
41
53
|
* The words a lane prompt opens with, followed by the lane's name. The ask hint hook and the project's lane exception
|
|
42
54
|
* recognise a lane by them, so they are fixed per language and not a config value.
|
|
@@ -111,6 +123,28 @@ type StatusWord = {
|
|
|
111
123
|
/** Lower-case fragments that classify a `Status:` line wherever they appear. */
|
|
112
124
|
anywhere: readonly string[];
|
|
113
125
|
};
|
|
126
|
+
/**
|
|
127
|
+
* The five fields of a lane's report, in this order, each opening a line of the report: the goal, the phase (written
|
|
128
|
+
* `<phase> x/y`), the result with its numbers, what the lane needs from the user, the next step. They are fixed per
|
|
129
|
+
* language, like the card, so the report template reads them as `{{kit.report.<key>}}` and the watcher recognises them
|
|
130
|
+
* in either language; the `## Questions` heading stays English in both.
|
|
131
|
+
*/
|
|
132
|
+
declare const REPORT_FIELDS: Record<PlanLanguage, {
|
|
133
|
+
goal: string;
|
|
134
|
+
phase: string;
|
|
135
|
+
result: string;
|
|
136
|
+
needsYou: string;
|
|
137
|
+
next: string;
|
|
138
|
+
}>;
|
|
139
|
+
/** The five lines of a plan's head, in the order a plan writes them. */
|
|
140
|
+
declare const HEAD_LINE: {
|
|
141
|
+
readonly changes: "changes";
|
|
142
|
+
readonly status: "status";
|
|
143
|
+
readonly decisions: "decisions";
|
|
144
|
+
readonly tryNow: "tryNow";
|
|
145
|
+
readonly next: "next";
|
|
146
|
+
};
|
|
147
|
+
type HeadLine = (typeof HEAD_LINE)[keyof typeof HEAD_LINE];
|
|
114
148
|
type PlanVocabulary = {
|
|
115
149
|
header: {
|
|
116
150
|
date: string;
|
|
@@ -127,7 +161,10 @@ type PlanVocabulary = {
|
|
|
127
161
|
goal: string;
|
|
128
162
|
history: string;
|
|
129
163
|
plans: string;
|
|
164
|
+
forYou: string;
|
|
130
165
|
};
|
|
166
|
+
/** The five labels of the `forYou` section, fixed per language: `- **<label>:** <text>`. */
|
|
167
|
+
head: Record<HeadLine, string>;
|
|
131
168
|
columns: {
|
|
132
169
|
dependsOn: string;
|
|
133
170
|
writes: string;
|
|
@@ -463,6 +500,52 @@ type PhaseTally = {
|
|
|
463
500
|
*/
|
|
464
501
|
declare const tallyPhases: (markdown: string, language: PlanLanguage) => PhaseTally[];
|
|
465
502
|
|
|
503
|
+
/** What a plan holds of its head: all of it and current, none of it, or something that no longer matches the plan. */
|
|
504
|
+
declare const HEAD_STATUS: {
|
|
505
|
+
readonly present: "present";
|
|
506
|
+
readonly missing: "missing";
|
|
507
|
+
readonly stale: "stale";
|
|
508
|
+
};
|
|
509
|
+
type HeadStatus = (typeof HEAD_STATUS)[keyof typeof HEAD_STATUS];
|
|
510
|
+
/** `line` is the 1-based line of the head's heading, or of its `Phase x/y` line; null when the plan has no head. */
|
|
511
|
+
type HeadVerdict = {
|
|
512
|
+
status: HeadStatus;
|
|
513
|
+
line: number | null;
|
|
514
|
+
message: string;
|
|
515
|
+
};
|
|
516
|
+
/**
|
|
517
|
+
* The `Phase x/y` of the status line: `current` is the id of the running phase as its heading spells it (`3`, `3a`),
|
|
518
|
+
* `total` the number of phases.
|
|
519
|
+
*/
|
|
520
|
+
type HeadPhase = {
|
|
521
|
+
current: string;
|
|
522
|
+
total: number;
|
|
523
|
+
};
|
|
524
|
+
type PlanHead = {
|
|
525
|
+
/** 1-based line of the `## Für dich` heading. */
|
|
526
|
+
line: number;
|
|
527
|
+
/** The text after each label found. */
|
|
528
|
+
texts: Partial<Record<HeadLine, string>>;
|
|
529
|
+
/** 1-based line of each label found. */
|
|
530
|
+
lineNumbers: Partial<Record<HeadLine, number>>;
|
|
531
|
+
/** The labels the head lacks, in head order. */
|
|
532
|
+
missing: HeadLine[];
|
|
533
|
+
phase: HeadPhase | null;
|
|
534
|
+
/** True when another level-2 section stands between the header lines and the head. */
|
|
535
|
+
misplaced: boolean;
|
|
536
|
+
};
|
|
537
|
+
/**
|
|
538
|
+
* Reads the head section (`## Für dich` / `## For you`) and its five lines: `- **<label>:** <text>`, also with the
|
|
539
|
+
* colon outside the bold or without the list mark. Null when the plan has no such section.
|
|
540
|
+
*/
|
|
541
|
+
declare const parsePlanHead: (markdown: string, language: PlanLanguage) => PlanHead | null;
|
|
542
|
+
/**
|
|
543
|
+
* The verdict on a plan's head. Stale when it stands behind another section, lacks a line, has no `Phase x/y` in the
|
|
544
|
+
* status line, or names a phase other than the first one with an open checkbox (the last one when all are done) or a
|
|
545
|
+
* wrong phase count. Pure: it reads only the Markdown.
|
|
546
|
+
*/
|
|
547
|
+
declare const checkPlanHead: (markdown: string, language: PlanLanguage) => HeadVerdict;
|
|
548
|
+
|
|
466
549
|
/** A `### Phase` heading (1-based line) whose section has tasks and neither a review gate nor the line saying why not. */
|
|
467
550
|
type PhaseWithoutGate = PhaseHeading;
|
|
468
551
|
/** A row of the lanes table (1-based line) whose phases cell names no phase id. */
|
|
@@ -626,4 +709,4 @@ declare const readSprintDocument: (markdown: string, language: PlanLanguage) =>
|
|
|
626
709
|
*/
|
|
627
710
|
declare const readPhaseDependencies: (planMarkdown: string, language: PlanLanguage) => Record<string, string>;
|
|
628
711
|
|
|
629
|
-
export { ADDRESS_FORM, APPOINTMENT_VOCABULARY, APPROVAL_TEXTS, type ChecklistItem, type ColumnModel, type DeferredItem, type DriftFinding, LANE_PROMPT_OPENING, LANGUAGE_NAME, type LaneProgress, type LongPhaseTitle, type MergedPhaseWithOpenBoxes, type MisplacedDeferral, type ModelRow, NEXT_VOCABULARY, NO_DEPENDENCY_TABLE, PHASE_CELL_LIMIT, PHASE_ID_PREFIX, PHASE_TITLE_LIMIT, PHASE_WORK, PLAN_LANGUAGE, PLAN_STATUS, PLAN_VOCABULARY, PROSE_REASON, type PhaseDependency, type PhaseHeading, type PhaseProgress, type PhaseSchedule, type PhaseTally, type PhaseWithOpenBoxes, type PhaseWithoutGate, type PhaseWithoutRow, type PhaseWork, type PhaseWorkFields, type PlanHeader, type PlanLanguage, type PlanPhase, type PlanStatus, type PlanStep, type PlanVocabulary, type PlansByHref, type ProseReason, RECOMMENDED_MARK, RESPONSE_ADDRESS, type ResponseAddress, type RowWithProse, type RowWithoutPhase, SELF_MERGE_LABEL, SHORT_NAME_LIMIT, SHORT_NAME_PROBLEM, STANDING_APPROVAL_TEXTS, type ShortNameFinding, type ShortNameProblem, type SprintDocument, type SprintLane, type SprintPlanRow, type SprintPlanTable, type StatusWord, type StepProgress, WAITING_VOCABULARY, activeItem, boardRowsWithProse, boardRowsWithoutPhase, classifyStatus, columnModels, countDecisions, criticalPath, currentPhase, currentPhaseOf, deferralTarget, differsFromColumn, endsPhase, findDrift, hasLanesTable, isCheckboxLine, isDocumentationGateItem, isOpenCheckboxLine, isPhaseFinished, isPhaseOpen, isPlanLanguage, isReviewGateLine, isTickedUnmerged, laneNameOf, laneProgress, longPhaseTitles, mergedPhasesWithOpenBoxes, misplacedDeferrals, newPhasesWithoutReviewGate, onlyDocumentationOpen, openBoxesOfPhase, parallelGroups, parallelGroupsOfPlan, parseDependencyTable, parseModelTable, parsePlanPhases, parseSprintLanes, phaseCount, phaseHeading, phaseHeadingPattern, phaseHeadings, phaseIdOf, phaseIdsOfCell, phaseIdsOfPlan, phaseLabel, phaseLabels, phaseProgress, phaseWaves, phaseWorkFields, phasesText, phasesWithoutDependencyRow, readPhaseDependencies, readPlanHeader, readSprintDocument, resolvePlanPath, sectionHeading, shortNameFindings, shortTitle, sprintTitleOf, sumPhases, tallyPhases, wavesOfPlan, withoutRepeats };
|
|
712
|
+
export { ADDRESS_FORM, APPOINTMENT_VOCABULARY, APPROVAL_TEXTS, CARD_FIELDS, type ChecklistItem, type ColumnModel, type DeferredItem, type DriftFinding, HEAD_LINE, HEAD_STATUS, type HeadLine, type HeadPhase, type HeadStatus, type HeadVerdict, LANE_PROMPT_OPENING, LANGUAGE_NAME, type LaneProgress, type LongPhaseTitle, type MergedPhaseWithOpenBoxes, type MisplacedDeferral, type ModelRow, NEXT_VOCABULARY, NO_DEPENDENCY_TABLE, PHASE_CELL_LIMIT, PHASE_ID_PREFIX, PHASE_TITLE_LIMIT, PHASE_WORK, PLAN_LANGUAGE, PLAN_STATUS, PLAN_VOCABULARY, PROSE_REASON, type PhaseDependency, type PhaseHeading, type PhaseProgress, type PhaseSchedule, type PhaseTally, type PhaseWithOpenBoxes, type PhaseWithoutGate, type PhaseWithoutRow, type PhaseWork, type PhaseWorkFields, type PlanHead, type PlanHeader, type PlanLanguage, type PlanPhase, type PlanStatus, type PlanStep, type PlanVocabulary, type PlansByHref, type ProseReason, RECOMMENDED_MARK, REPORT_FIELDS, RESPONSE_ADDRESS, type ResponseAddress, type RowWithProse, type RowWithoutPhase, SELF_MERGE_LABEL, SHORT_NAME_LIMIT, SHORT_NAME_PROBLEM, STANDING_APPROVAL_TEXTS, type ShortNameFinding, type ShortNameProblem, type SprintDocument, type SprintLane, type SprintPlanRow, type SprintPlanTable, type StatusWord, type StepProgress, WAITING_VOCABULARY, activeItem, boardRowsWithProse, boardRowsWithoutPhase, checkPlanHead, classifyStatus, columnModels, countDecisions, criticalPath, currentPhase, currentPhaseOf, deferralTarget, differsFromColumn, endsPhase, findDrift, hasLanesTable, isCheckboxLine, isDocumentationGateItem, isOpenCheckboxLine, isPhaseFinished, isPhaseOpen, isPlanLanguage, isReviewGateLine, isTickedUnmerged, laneNameOf, laneProgress, longPhaseTitles, mergedPhasesWithOpenBoxes, misplacedDeferrals, newPhasesWithoutReviewGate, onlyDocumentationOpen, openBoxesOfPhase, parallelGroups, parallelGroupsOfPlan, parseDependencyTable, parseModelTable, parsePlanHead, parsePlanPhases, parseSprintLanes, phaseCount, phaseHeading, phaseHeadingPattern, phaseHeadings, phaseIdOf, phaseIdsOfCell, phaseIdsOfPlan, phaseLabel, phaseLabels, phaseProgress, phaseWaves, phaseWorkFields, phasesText, phasesWithoutDependencyRow, readPhaseDependencies, readPlanHeader, readSprintDocument, resolvePlanPath, sectionHeading, shortNameFindings, shortTitle, sprintTitleOf, sumPhases, tallyPhases, wavesOfPlan, withoutRepeats };
|