team 0.1.2 → 0.2.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.
Files changed (114) hide show
  1. package/README.md +22 -11
  2. package/dist/approve/approval.js +14 -9
  3. package/dist/approve/fingerprint.d.ts +14 -2
  4. package/dist/approve/fingerprint.js +21 -21
  5. package/dist/budgets/gate.js +7 -2
  6. package/dist/budgets/readings.d.ts +6 -2
  7. package/dist/budgets/readings.js +28 -2
  8. package/dist/budgets/run.js +8 -2
  9. package/dist/budgets/table.d.ts +2 -0
  10. package/dist/budgets/table.js +10 -5
  11. package/dist/cli.d.ts +2 -1
  12. package/dist/cli.js +8 -5
  13. package/dist/commands/add.d.ts +0 -1
  14. package/dist/commands/add.js +7 -5
  15. package/dist/commands/approve.js +17 -1
  16. package/dist/commands/doctor.d.ts +15 -1
  17. package/dist/commands/doctor.js +126 -8
  18. package/dist/commands/down.d.ts +4 -0
  19. package/dist/commands/down.js +32 -13
  20. package/dist/commands/init.d.ts +1 -1
  21. package/dist/commands/init.js +4 -2
  22. package/dist/commands/remove.js +5 -2
  23. package/dist/commands/status.d.ts +2 -0
  24. package/dist/commands/status.js +19 -1
  25. package/dist/commands/up.js +3 -1
  26. package/dist/commands/watch.d.ts +2 -0
  27. package/dist/commands/watch.js +28 -4
  28. package/dist/conformance/adapter.d.ts +5 -0
  29. package/dist/conformance/adapter.js +44 -0
  30. package/dist/file/check.d.ts +20 -0
  31. package/dist/file/check.js +112 -0
  32. package/dist/file/lines.js +13 -2
  33. package/dist/file/sections/budgets.d.ts +15 -0
  34. package/dist/file/sections/budgets.js +180 -0
  35. package/dist/file/sections/coordinator.d.ts +2 -0
  36. package/dist/file/sections/coordinator.js +11 -0
  37. package/dist/file/sections/format.d.ts +2 -0
  38. package/dist/file/sections/format.js +13 -0
  39. package/dist/file/sections/identity.d.ts +2 -0
  40. package/dist/file/sections/identity.js +103 -0
  41. package/dist/file/sections/index.d.ts +9 -0
  42. package/dist/file/sections/index.js +43 -0
  43. package/dist/file/sections/lead.d.ts +4 -0
  44. package/dist/file/sections/lead.js +18 -0
  45. package/dist/file/sections/limits.d.ts +2 -0
  46. package/dist/file/sections/limits.js +43 -0
  47. package/dist/file/sections/machine.d.ts +2 -0
  48. package/dist/file/sections/machine.js +38 -0
  49. package/dist/file/sections/operator.d.ts +2 -0
  50. package/dist/file/sections/operator.js +11 -0
  51. package/dist/file/sections/project.d.ts +2 -0
  52. package/dist/file/sections/project.js +13 -0
  53. package/dist/file/sections/rules.d.ts +2 -0
  54. package/dist/file/sections/rules.js +9 -0
  55. package/dist/file/sections/seats.d.ts +7 -0
  56. package/dist/file/sections/seats.js +161 -0
  57. package/dist/file/sections/section.d.ts +32 -0
  58. package/dist/file/sections/section.js +7 -0
  59. package/dist/file/sections/session.d.ts +2 -0
  60. package/dist/file/sections/session.js +16 -0
  61. package/dist/file/sections/tools.d.ts +2 -0
  62. package/dist/file/sections/tools.js +43 -0
  63. package/dist/file/sections/trust.d.ts +2 -0
  64. package/dist/file/sections/trust.js +20 -0
  65. package/dist/file/sections/units.d.ts +16 -0
  66. package/dist/file/sections/units.js +8 -0
  67. package/dist/file/sections/visibility.d.ts +2 -0
  68. package/dist/file/sections/visibility.js +12 -0
  69. package/dist/file/sections/watch-checks.d.ts +9 -0
  70. package/dist/file/sections/watch-checks.js +14 -0
  71. package/dist/file/sections/watch.d.ts +14 -0
  72. package/dist/file/sections/watch.js +111 -0
  73. package/dist/file/sections/workspace.d.ts +4 -0
  74. package/dist/file/sections/workspace.js +77 -0
  75. package/dist/file/types.d.ts +1 -0
  76. package/dist/file/validate.d.ts +4 -12
  77. package/dist/file/validate.js +45 -688
  78. package/dist/herdr.d.ts +1 -0
  79. package/dist/herdr.js +11 -1
  80. package/dist/launch/agent.js +4 -3
  81. package/dist/launch/deliver.d.ts +4 -0
  82. package/dist/launch/deliver.js +151 -8
  83. package/dist/launch/execute.d.ts +2 -0
  84. package/dist/launch/execute.js +21 -11
  85. package/dist/launch/plan.js +16 -2
  86. package/dist/profiles/antigravity.yaml +12 -2
  87. package/dist/profiles/claude-code.yaml +21 -6
  88. package/dist/profiles/codex.yaml +14 -1
  89. package/dist/profiles/cursor.yaml +45 -5
  90. package/dist/profiles/overrides.d.ts +67 -0
  91. package/dist/profiles/overrides.js +190 -0
  92. package/dist/profiles/profile.d.ts +3 -0
  93. package/dist/profiles/profile.js +5 -1
  94. package/dist/state.d.ts +2 -0
  95. package/dist/status/compare.js +7 -4
  96. package/dist/store/store.d.ts +5 -0
  97. package/dist/version.d.ts +1 -0
  98. package/dist/version.js +7 -0
  99. package/dist/watch/checks/budget.js +49 -53
  100. package/dist/watch/dialect.d.ts +6 -1
  101. package/dist/watch/dialect.js +68 -12
  102. package/dist/watch/pass.d.ts +8 -1
  103. package/dist/watch/pass.js +19 -9
  104. package/dist/watch/screen-core.d.ts +41 -4
  105. package/dist/watch/screen-core.js +458 -93
  106. package/dist/watch/screen-data.d.ts +25 -0
  107. package/dist/watch/screen-file.d.ts +8 -2
  108. package/dist/watch/screen-file.js +325 -38
  109. package/dist/watch/screen-profile.d.ts +19 -0
  110. package/dist/watch/screen-profile.js +1 -0
  111. package/dist/watch/screen.d.ts +22 -4
  112. package/dist/watch/screen.js +39 -5
  113. package/package.json +9 -3
  114. package/schema/team.schema.json +498 -0
@@ -4,7 +4,8 @@
4
4
  // handed (RFC 0002 § 4.2).
5
5
  import { seatNamed } from "../approve/fingerprint.js";
6
6
  import { observe, observeCheck } from "../budgets/readings.js";
7
- import { quotaFor } from "../profiles/profile.js";
7
+ import { reportedLiveAgent } from "../launch/agent.js";
8
+ import { profileFor, quotaFor as shippedQuota } from "../profiles/profile.js";
8
9
  import { figuresOf } from "../profiles/quota.js";
9
10
  import { seatModel } from "../status/statusline.js";
10
11
  import { ALWAYS_ON, } from "./check.js";
@@ -52,16 +53,20 @@ function attentionOf(screen, status, quiet) {
52
53
  }
53
54
  // The figures off a seat's own pane: only a composer screen — idle, unsent or working — shows a
54
55
  // status row at all, and only that row's line is read. A dialog, a question, a trust screen or an
55
- // unknown one gives no figures, and neither does a line the seat printed or typed.
56
- function quotaOf(cli, screen, pane) {
57
- if (pane === undefined)
56
+ // unknown one gives no figures, and neither does a line the seat printed or typed. And only a
57
+ // pane where herdr reports the seat's CLI still running: a shell's last row is a last row by
58
+ // position, not a status row, and a pane herdr could not read gives none either — no figure is
59
+ // invented where the CLI was not seen. (`down` and `remove` read that same null the other way at
60
+ // their departure wait; not knowing must not end a wait.)
61
+ function quotaOf(cli, screen, pane, runs, patterns) {
62
+ if (pane === undefined || !runs)
58
63
  return [];
59
64
  if (screen.kind !== 'idle' && screen.kind !== 'unsent' && screen.kind !== 'working')
60
65
  return [];
61
- return figuresOf(quotaFor(cli), statusRow(cli, pane));
66
+ return figuresOf(patterns, statusRow(cli, pane));
62
67
  }
63
68
  // One pass of the watch. Pure: it reads what it is handed and changes only `memory`.
64
- export function pass({ team, state, live, machine, now, memory, approval, watch, outcomes = [], budgets = team.budgets, readings: stored = [], }) {
69
+ export function pass({ team, state, live, machine, now, memory, approval, watch, outcomes = [], budgets = team.budgets, readings: stored = [], foreground, readScreen: read = readScreen, quotaFor: patternsOf = shippedQuota, }) {
65
70
  const reports = [];
66
71
  const current = new Set();
67
72
  // Reported when it starts, and again only after it has cleared.
@@ -130,7 +135,7 @@ export function pass({ team, state, live, machine, now, memory, approval, watch,
130
135
  }
131
136
  known.add(agent.pane);
132
137
  const pane = live.screens[agent.pane];
133
- const screen = readScreen(cli, pane);
138
+ const screen = read(cli, pane);
134
139
  const quiet = agent.status === 'idle' || agent.status === 'done';
135
140
  // Working is herdr's word or the screen's: a seat mid-turn is never idle, whatever its
136
141
  // status says.
@@ -157,7 +162,7 @@ export function pass({ team, state, live, machine, now, memory, approval, watch,
157
162
  cli,
158
163
  vendor,
159
164
  account,
160
- quota: quotaOf(cli, screen, pane),
165
+ quota: quotaOf(cli, screen, pane, reportedLiveAgent(foreground?.[agent.pane] ?? null, profileFor(cli)?.processNames ?? []), patternsOf(cli)),
161
166
  running: true,
162
167
  quiet,
163
168
  working,
@@ -183,6 +188,11 @@ export function pass({ team, state, live, machine, now, memory, approval, watch,
183
188
  // not move its figure into another account's bucket, where `up` and `add` would count it.
184
189
  // Nothing is saved for that seat until the owner approves.
185
190
  const drift = new Set((Array.isArray(approval) ? approval : []).map(seatNamed).filter((name) => name !== null));
191
+ for (const [name, recorded] of Object.entries(state.seats)) {
192
+ if (recorded.temporary && drift.has(recorded.temporary.like)) {
193
+ drift.add(name);
194
+ }
195
+ }
186
196
  let readings = stored.slice();
187
197
  for (const seat of observations) {
188
198
  if (!seat.running || drift.has(seat.name))
@@ -257,7 +267,7 @@ export function pass({ team, state, live, machine, now, memory, approval, watch,
257
267
  const operator = live.agents.find((agent) => agent.name === team.operator);
258
268
  const cli = team.seats.find((seat) => seat.name === team.operator)?.cli ?? '';
259
269
  const free = operator !== undefined && (operator.status === 'idle' || operator.status === 'done')
260
- && readScreen(cli, live.screens[operator.pane]).kind === 'idle';
270
+ && read(cli, live.screens[operator.pane]).kind === 'idle';
261
271
  if (operator && free) {
262
272
  nudge = { pane: operator.pane, text: NUDGE_TEXT, pending: memory.pending.slice() };
263
273
  }
@@ -1,6 +1,7 @@
1
1
  import type { Screen } from './screen.ts';
2
- import type { ScreenData } from './screen-data.ts';
3
- export type { Composer, FallbackRule, LinePattern, Placeholder, PlaceholderStyle, Rule, ScreenData, Stage } from './screen-data.ts';
2
+ import type { ScreenData, Wrap } from './screen-data.ts';
3
+ export type { Composer, FallbackRule, LinePattern, Placeholder, PlaceholderStyle, Rule, ScreenData, Stage, Wrap } from './screen-data.ts';
4
+ export type { ScreenProfile, ComposerReading } from './screen-profile.ts';
4
5
  export type ReadClock = {
5
6
  now(): number;
6
7
  budgetMs: number;
@@ -11,10 +12,46 @@ export type ReadClock = {
11
12
  * typed — is never the row. The caller still has to know the screen is a composer screen.
12
13
  */
13
14
  export declare function statusRowOf(data: ScreenData, lines: string[]): string | null;
15
+ export type Fold = {
16
+ count: number;
17
+ rows: string[];
18
+ width: number;
19
+ };
20
+ /** The input box a composer draws for its current text: the first line after the prompt, the
21
+ * continuation rows under it, the column those rows start at (the prompt's own width plus
22
+ * the separator the input row draws), and the profile's wrap rule when a capture shows how
23
+ * the box continues a line onto its next row. */
24
+ export type Box = {
25
+ first: string;
26
+ indent: number;
27
+ rows: string[];
28
+ wrap?: Wrap;
29
+ };
30
+ /**
31
+ * The fold a `two-rules-footer-below` composer's window shows, or null. A marker whose count is
32
+ * zero names no hidden rows to compare against, so it is no fold; it is still a marker, and
33
+ * `foldMarked` catches it.
34
+ */
35
+ export declare function foldOf(data: ScreenData, lines: string[]): Fold | null;
36
+ /**
37
+ * Whether the window shows a fold marker at all, whatever count it names: a marker claiming zero
38
+ * hidden rows (or a count a fold could not have) is still a box that is not showing the whole
39
+ * text, and it must never be taken for an ordinary unsent box and submitted unverified.
40
+ */
41
+ export declare function foldMarked(data: ScreenData, lines: string[]): boolean;
14
42
  /** `lines` is already the window: the last 20 lines, each trimmed at the end. */
15
43
  export declare function classifyLines(data: ScreenData, lines: string[], clock?: ReadClock): Screen;
16
44
  /**
17
- * The composer alone, for a turn that is still running. The unknown stage is
18
- * read first, as in the full classification, and the floor still applies.
45
+ * The composer alone, for a turn that is still running. The dialog stages and
46
+ * floor must not be overridden by composer readings returning idle or unsent.
19
47
  */
20
48
  export declare function composeLines(data: ScreenData, lines: string[], clock?: ReadClock): Screen;
49
+ /**
50
+ * The input box a composer draws for its current text, or null when the composer does not read
51
+ * `unsent`: an idle box holds nothing, and every other shape is not the box. The rows are the
52
+ * ones the mode's own frame delimits — between the prompt row and the box's closing line; the
53
+ * `status-then-one` fallback (the captured completion frame) delimits nothing, so its box is
54
+ * its one input row, the popup rows below it being its filter's to exclude. The caller compares
55
+ * the box to the text it typed; nothing here decides that.
56
+ */
57
+ export declare function composerBox(data: ScreenData, lines: string[]): Box | null;