team 0.0.1 → 0.1.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.
Files changed (169) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +310 -0
  3. package/dist/approve/approval.d.ts +38 -0
  4. package/dist/approve/approval.js +78 -0
  5. package/dist/approve/diff.d.ts +13 -0
  6. package/dist/approve/diff.js +47 -0
  7. package/dist/approve/fingerprint.d.ts +44 -0
  8. package/dist/approve/fingerprint.js +109 -0
  9. package/dist/args.d.ts +7 -0
  10. package/dist/args.js +22 -0
  11. package/dist/budgets/checks.d.ts +35 -0
  12. package/dist/budgets/checks.js +77 -0
  13. package/dist/budgets/gate.d.ts +24 -0
  14. package/dist/budgets/gate.js +127 -0
  15. package/dist/budgets/readings.d.ts +69 -0
  16. package/dist/budgets/readings.js +156 -0
  17. package/dist/budgets/run.d.ts +66 -0
  18. package/dist/budgets/run.js +119 -0
  19. package/dist/budgets/table.d.ts +24 -0
  20. package/dist/budgets/table.js +90 -0
  21. package/dist/caller.d.ts +48 -0
  22. package/dist/caller.js +126 -0
  23. package/dist/check/config.d.ts +51 -0
  24. package/dist/check/config.js +50 -0
  25. package/dist/check/git.d.ts +27 -0
  26. package/dist/check/git.js +97 -0
  27. package/dist/check/message.d.ts +27 -0
  28. package/dist/check/message.js +101 -0
  29. package/dist/check/run.d.ts +31 -0
  30. package/dist/check/run.js +77 -0
  31. package/dist/check/signature.d.ts +10 -0
  32. package/dist/check/signature.js +22 -0
  33. package/dist/cli.d.ts +9 -0
  34. package/dist/cli.js +76 -0
  35. package/dist/clis.d.ts +7 -0
  36. package/dist/clis.js +9 -0
  37. package/dist/commands/add.d.ts +23 -0
  38. package/dist/commands/add.js +445 -0
  39. package/dist/commands/approve.d.ts +11 -0
  40. package/dist/commands/approve.js +146 -0
  41. package/dist/commands/check.d.ts +17 -0
  42. package/dist/commands/check.js +103 -0
  43. package/dist/commands/doctor.d.ts +38 -0
  44. package/dist/commands/doctor.js +232 -0
  45. package/dist/commands/down.d.ts +37 -0
  46. package/dist/commands/down.js +258 -0
  47. package/dist/commands/init.d.ts +9 -0
  48. package/dist/commands/init.js +138 -0
  49. package/dist/commands/remove.d.ts +23 -0
  50. package/dist/commands/remove.js +235 -0
  51. package/dist/commands/status.d.ts +41 -0
  52. package/dist/commands/status.js +147 -0
  53. package/dist/commands/up.d.ts +49 -0
  54. package/dist/commands/up.js +362 -0
  55. package/dist/commands/watch.d.ts +35 -0
  56. package/dist/commands/watch.js +324 -0
  57. package/dist/commands/worktree.d.ts +12 -0
  58. package/dist/commands/worktree.js +388 -0
  59. package/dist/end/condition.d.ts +28 -0
  60. package/dist/end/condition.js +77 -0
  61. package/dist/file/current.d.ts +13 -0
  62. package/dist/file/current.js +53 -0
  63. package/dist/file/lines.d.ts +25 -0
  64. package/dist/file/lines.js +277 -0
  65. package/dist/file/load.d.ts +7 -0
  66. package/dist/file/load.js +90 -0
  67. package/dist/file/paths.d.ts +6 -0
  68. package/dist/file/paths.js +77 -0
  69. package/dist/file/secrets.d.ts +6 -0
  70. package/dist/file/secrets.js +54 -0
  71. package/dist/file/signature.d.ts +13 -0
  72. package/dist/file/signature.js +36 -0
  73. package/dist/file/types.d.ts +130 -0
  74. package/dist/file/types.js +1 -0
  75. package/dist/file/validate.d.ts +13 -0
  76. package/dist/file/validate.js +702 -0
  77. package/dist/file/write.d.ts +11 -0
  78. package/dist/file/write.js +13 -0
  79. package/dist/herdr.d.ts +38 -0
  80. package/dist/herdr.js +227 -0
  81. package/dist/index.d.ts +10 -0
  82. package/dist/index.js +6 -0
  83. package/dist/io.d.ts +10 -0
  84. package/dist/io.js +1 -0
  85. package/dist/launch/deliver.d.ts +10 -0
  86. package/dist/launch/deliver.js +39 -0
  87. package/dist/launch/execute.d.ts +46 -0
  88. package/dist/launch/execute.js +284 -0
  89. package/dist/launch/plan.d.ts +185 -0
  90. package/dist/launch/plan.js +280 -0
  91. package/dist/launch/rules.d.ts +25 -0
  92. package/dist/launch/rules.js +36 -0
  93. package/dist/log.d.ts +1 -0
  94. package/dist/log.js +24 -0
  95. package/dist/profiles/antigravity.yaml +66 -0
  96. package/dist/profiles/claude-code.yaml +69 -0
  97. package/dist/profiles/codex.yaml +77 -0
  98. package/dist/profiles/cursor.yaml +68 -0
  99. package/dist/profiles/index.d.ts +1 -0
  100. package/dist/profiles/index.js +1 -0
  101. package/dist/profiles/profile.d.ts +60 -0
  102. package/dist/profiles/profile.js +313 -0
  103. package/dist/profiles/quota.d.ts +27 -0
  104. package/dist/profiles/quota.js +57 -0
  105. package/dist/state.d.ts +61 -0
  106. package/dist/state.js +127 -0
  107. package/dist/status/compare.d.ts +26 -0
  108. package/dist/status/compare.js +110 -0
  109. package/dist/status/statusline.d.ts +9 -0
  110. package/dist/status/statusline.js +26 -0
  111. package/dist/store/store.d.ts +62 -0
  112. package/dist/store/store.js +116 -0
  113. package/dist/watch/check.d.ts +82 -0
  114. package/dist/watch/check.js +29 -0
  115. package/dist/watch/checks/approval.d.ts +2 -0
  116. package/dist/watch/checks/approval.js +16 -0
  117. package/dist/watch/checks/attention.d.ts +2 -0
  118. package/dist/watch/checks/attention.js +23 -0
  119. package/dist/watch/checks/budget.d.ts +2 -0
  120. package/dist/watch/checks/budget.js +141 -0
  121. package/dist/watch/checks/disk.d.ts +2 -0
  122. package/dist/watch/checks/disk.js +13 -0
  123. package/dist/watch/checks/extra.d.ts +2 -0
  124. package/dist/watch/checks/extra.js +18 -0
  125. package/dist/watch/checks/idle.d.ts +2 -0
  126. package/dist/watch/checks/idle.js +32 -0
  127. package/dist/watch/checks/load.d.ts +2 -0
  128. package/dist/watch/checks/load.js +11 -0
  129. package/dist/watch/checks/memory.d.ts +2 -0
  130. package/dist/watch/checks/memory.js +11 -0
  131. package/dist/watch/checks/missing.d.ts +2 -0
  132. package/dist/watch/checks/missing.js +12 -0
  133. package/dist/watch/checks/model-drift.d.ts +2 -0
  134. package/dist/watch/checks/model-drift.js +14 -0
  135. package/dist/watch/checks/swap-free.d.ts +2 -0
  136. package/dist/watch/checks/swap-free.js +12 -0
  137. package/dist/watch/checks/swap-growth.d.ts +2 -0
  138. package/dist/watch/checks/swap-growth.js +18 -0
  139. package/dist/watch/checks/team-idle.d.ts +2 -0
  140. package/dist/watch/checks/team-idle.js +18 -0
  141. package/dist/watch/checks/unsent.d.ts +2 -0
  142. package/dist/watch/checks/unsent.js +18 -0
  143. package/dist/watch/close.d.ts +19 -0
  144. package/dist/watch/close.js +40 -0
  145. package/dist/watch/dialect.d.ts +5 -0
  146. package/dist/watch/dialect.js +430 -0
  147. package/dist/watch/end.d.ts +11 -0
  148. package/dist/watch/end.js +17 -0
  149. package/dist/watch/machine.d.ts +38 -0
  150. package/dist/watch/machine.js +137 -0
  151. package/dist/watch/notify.d.ts +1 -0
  152. package/dist/watch/notify.js +15 -0
  153. package/dist/watch/pass.d.ts +42 -0
  154. package/dist/watch/pass.js +242 -0
  155. package/dist/watch/screen-core.d.ts +20 -0
  156. package/dist/watch/screen-core.js +356 -0
  157. package/dist/watch/screen-data.d.ts +65 -0
  158. package/dist/watch/screen-data.js +1 -0
  159. package/dist/watch/screen-file.d.ts +2 -0
  160. package/dist/watch/screen-file.js +269 -0
  161. package/dist/watch/screen.d.ts +24 -0
  162. package/dist/watch/screen.js +47 -0
  163. package/dist/worktree/place.d.ts +18 -0
  164. package/dist/worktree/place.js +126 -0
  165. package/dist/yaml.d.ts +30 -0
  166. package/dist/yaml.js +380 -0
  167. package/examples/checks/codex-quota +217 -0
  168. package/examples/team.yaml +76 -0
  169. package/package.json +29 -10
@@ -0,0 +1,18 @@
1
+ import { WATCH_LABEL } from "../../status/compare.js";
2
+ // An agent herdr lists in a pane no seat of the file answers for: started outside the team, and
3
+ // nobody's. The watch's own workspace is the watch itself, and never extra.
4
+ export const extra = {
5
+ name: 'extra',
6
+ run(team, ctx) {
7
+ const labels = new Map(team.live.workspaces.map((workspace) => [workspace.id, workspace.label]));
8
+ const reports = [];
9
+ for (const agent of team.live.agents) {
10
+ if (team.known.has(agent.pane) || labels.get(agent.workspace) === WATCH_LABEL)
11
+ continue;
12
+ const report = ctx.once(`extra:${agent.pane}`, `${agent.name ?? `an unnamed ${agent.agent ?? 'agent'}`} (${agent.pane}) is running and is not in the file`);
13
+ if (report)
14
+ reports.push(report);
15
+ }
16
+ return reports;
17
+ },
18
+ };
@@ -0,0 +1,2 @@
1
+ import { type SeatCheck } from '../check.ts';
2
+ export declare const idle: SeatCheck;
@@ -0,0 +1,32 @@
1
+ import { minutes } from "../check.js";
2
+ // A seat that has stopped: quiet, with no running turn, no prompt and no unsent text. The
3
+ // duration counts from the last moment it was seen working. A seat never seen working was already
4
+ // idle when the watch started: it is reported that way, with no duration from another source.
5
+ // The leads and parked seats are reported on, but their idle time is not the team's: skipped.
6
+ export const idle = {
7
+ name: 'idle',
8
+ run(seat, ctx) {
9
+ const told = ctx.memory('idle', () => ({}));
10
+ if (!seat.running)
11
+ return [];
12
+ if (!seat.quiet || seat.working || seat.prompt) {
13
+ delete told[seat.name];
14
+ return [];
15
+ }
16
+ if (seat.lead || seat.parked)
17
+ return [];
18
+ const worked = seat.history.lastWorking;
19
+ const since = ctx.now - (worked ?? seat.history.idleSince ?? ctx.now);
20
+ const at = told[seat.name];
21
+ if (since < ctx.watch.idleFirst * 1000 || (at !== undefined && ctx.now - at < ctx.watch.idleRepeat * 1000))
22
+ return [];
23
+ told[seat.name] = ctx.now;
24
+ return [{
25
+ key: `idle:${seat.name}`,
26
+ text: worked === undefined
27
+ ? `${seat.name} has been idle since the watch started`
28
+ : `${seat.name} has been idle for ${minutes(since)} minutes`,
29
+ to: 'operator',
30
+ }];
31
+ },
32
+ };
@@ -0,0 +1,2 @@
1
+ import { type TeamCheck } from '../check.ts';
2
+ export declare const load: TeamCheck;
@@ -0,0 +1,11 @@
1
+ import { reported } from "../check.js";
2
+ // Load per core above the file's maximum. A figure that wasn't read is never reported.
3
+ export const load = {
4
+ name: 'load',
5
+ run(team, ctx) {
6
+ const value = team.machine.loadPerCore;
7
+ if (value === null || value <= team.limits.loadMax)
8
+ return [];
9
+ return reported(ctx.once('load', `the load is ${value.toFixed(1)} per core, above ${team.limits.loadMax}`, 'owner'));
10
+ },
11
+ };
@@ -0,0 +1,2 @@
1
+ import { type TeamCheck } from '../check.ts';
2
+ export declare const memory: TeamCheck;
@@ -0,0 +1,11 @@
1
+ import { reported } from "../check.js";
2
+ // Free memory below the file's minimum, in percent. A figure that wasn't read is never reported.
3
+ export const memory = {
4
+ name: 'memory',
5
+ run(team, ctx) {
6
+ const value = team.machine.memoryFree;
7
+ if (value === null || value >= team.limits.memoryMin)
8
+ return [];
9
+ return reported(ctx.once('memory', `free memory is ${Math.round(value)}%, below ${team.limits.memoryMin}%`, 'owner'));
10
+ },
11
+ };
@@ -0,0 +1,2 @@
1
+ import { type SeatCheck } from '../check.ts';
2
+ export declare const missing: SeatCheck;
@@ -0,0 +1,12 @@
1
+ import { reported } from "../check.js";
2
+ // A seat the file holds that no agent answers for. A stopped seat is not started: absent from
3
+ // herdr is its normal state, and draws nothing. And when the session itself doesn't answer, every
4
+ // seat is absent for the same reason — the watch reports none of them.
5
+ export const missing = {
6
+ name: 'missing',
7
+ run(seat, ctx) {
8
+ if (seat.running || seat.stopped || !seat.herdr)
9
+ return [];
10
+ return reported(ctx.once(`missing:${seat.name}`, `${seat.name} is in the file and is not running`));
11
+ },
12
+ };
@@ -0,0 +1,2 @@
1
+ import { type SeatCheck } from '../check.ts';
2
+ export declare const modelDrift: SeatCheck;
@@ -0,0 +1,14 @@
1
+ import { reported } from "../check.js";
2
+ // A seat that runs a model other than the one the file declares: what it signs with is not what
3
+ // the owner approved. A temporary seat has no file model, and a screen the profile cannot read is
4
+ // unread, never a mismatch.
5
+ export const modelDrift = {
6
+ name: 'model-drift',
7
+ run(seat, ctx) {
8
+ const file = seat.seat;
9
+ const running = seat.model;
10
+ if (!file || !running || (running.model === file.model && running.version === file.version))
11
+ return [];
12
+ return reported(ctx.once(`model:${seat.name}`, `${seat.name} runs ${running.model} ${running.version}; the file says ${file.model} ${file.version}: it signs with the wrong model`));
13
+ },
14
+ };
@@ -0,0 +1,2 @@
1
+ import { type TeamCheck } from '../check.ts';
2
+ export declare const swapFree: TeamCheck;
@@ -0,0 +1,12 @@
1
+ import { gb } from "../machine.js";
2
+ import { reported } from "../check.js";
3
+ // Free swap below the file's minimum. A machine with no swap reads none, and reports nothing.
4
+ export const swapFree = {
5
+ name: 'swap-free',
6
+ run(team, ctx) {
7
+ const value = team.machine.swapFree;
8
+ if (value === null || value >= team.limits.swapFreeMin)
9
+ return [];
10
+ return reported(ctx.once('swap-free', `free swap is ${gb(value)}, below ${gb(team.limits.swapFreeMin)}`, 'owner'));
11
+ },
12
+ };
@@ -0,0 +1,2 @@
1
+ import { type TeamCheck } from '../check.ts';
2
+ export declare const swapGrowth: TeamCheck;
@@ -0,0 +1,18 @@
1
+ import { gb, recordSwap } from "../machine.js";
2
+ import { minutes, reported } from "../check.js";
3
+ // Swap that grew inside the window, even while free swap is high: the growth is the pressure.
4
+ // The samples are this check's own memory, shared with nothing. A figure that wasn't read is
5
+ // never reported.
6
+ export const swapGrowth = {
7
+ name: 'swap-growth',
8
+ run(team, ctx) {
9
+ const used = team.machine.swapUsed;
10
+ if (used === null)
11
+ return [];
12
+ const samples = ctx.memory('swap-growth', () => []);
13
+ const growth = recordSwap(samples, used, ctx.now, team.limits.swapGrowthWindow);
14
+ if (growth <= team.limits.swapGrowthMax)
15
+ return [];
16
+ return reported(ctx.once('swap-growth', `swap grew by ${gb(growth)} in ${minutes(team.limits.swapGrowthWindow * 1000)} minutes, above ${gb(team.limits.swapGrowthMax)}`, 'owner'));
17
+ },
18
+ };
@@ -0,0 +1,2 @@
1
+ import type { TeamCheck } from '../check.ts';
2
+ export declare const teamIdle: TeamCheck;
@@ -0,0 +1,18 @@
1
+ // Every worker idle at once, reported once per idle stretch, after `team_idle`. A worker that
2
+ // works again re-arms it. The leads and parked seats never count as the team's workers.
3
+ export const teamIdle = {
4
+ name: 'team-idle',
5
+ run(team, ctx) {
6
+ const memory = ctx.memory('team-idle', () => ({ since: null, told: false }));
7
+ if (!team.workers.length || !team.workers.every((worker) => worker.idle)) {
8
+ memory.since = null;
9
+ memory.told = false;
10
+ return [];
11
+ }
12
+ memory.since ??= ctx.now;
13
+ if (memory.told || ctx.now - memory.since < ctx.watch.teamIdle * 1000)
14
+ return [];
15
+ memory.told = true;
16
+ return [{ key: 'team-idle', text: 'every agent is idle', to: 'operator' }];
17
+ },
18
+ };
@@ -0,0 +1,2 @@
1
+ import { type SeatCheck } from '../check.ts';
2
+ export declare const unsent: SeatCheck;
@@ -0,0 +1,18 @@
1
+ import { reported } from "../check.js";
2
+ // Text held in the composer that was never sent: a seat herdr calls idle, holding a sentence. It
3
+ // is reported once the text has stood there for `unsent_after`, and its clock clears the moment
4
+ // the seat is anything else — running, at a prompt, or holding nothing.
5
+ export const unsent = {
6
+ name: 'unsent',
7
+ run(seat, ctx) {
8
+ const since = ctx.memory('unsent', () => ({}));
9
+ if (!seat.running || !seat.quiet || seat.working || seat.prompt || seat.screen.kind !== 'unsent') {
10
+ delete since[seat.name];
11
+ return [];
12
+ }
13
+ since[seat.name] ??= ctx.now;
14
+ if (ctx.now - since[seat.name] < ctx.watch.unsentAfter * 1000)
15
+ return [];
16
+ return reported(ctx.once(`unsent:${seat.name}`, `${seat.name} holds text in its input box that was never sent`));
17
+ },
18
+ };
@@ -0,0 +1,19 @@
1
+ import type { EndView } from './end.ts';
2
+ export type CloseDecision = {
3
+ close: boolean;
4
+ /** Set when this pass saw commits of the branch's own. The next pass can then prove a merge. */
5
+ ownCommits?: boolean;
6
+ report?: string;
7
+ };
8
+ export declare function judgeTemporary(input: {
9
+ worked: boolean;
10
+ free: boolean;
11
+ ownBefore: boolean;
12
+ end: EndView;
13
+ }): CloseDecision;
14
+ export declare function judgeWorktree(input: {
15
+ policy: 'on-merge' | 'manual';
16
+ occupied: boolean;
17
+ ownBefore: boolean;
18
+ end: EndView;
19
+ }): CloseDecision;
@@ -0,0 +1,40 @@
1
+ export function judgeTemporary(input) {
2
+ if (input.end.kind === 'result') {
3
+ if (!input.end.exists || !input.worked || !input.free)
4
+ return { close: false };
5
+ return { close: true };
6
+ }
7
+ if (input.end.ownNow > 0)
8
+ return openBranch(input.end.detail);
9
+ if (input.end.verdict === 'unproven')
10
+ return { close: false, report: input.end.detail };
11
+ if (!input.ownBefore || !input.worked || !input.free)
12
+ return { close: false };
13
+ if (input.end.verdict === 'merged')
14
+ return { close: true };
15
+ return { close: false };
16
+ }
17
+ export function judgeWorktree(input) {
18
+ if (input.policy !== 'on-merge')
19
+ return { close: false };
20
+ if (input.end.kind !== 'merged')
21
+ return { close: false };
22
+ if (input.end.ownNow > 0)
23
+ return openBranch(input.end.detail);
24
+ if (input.end.verdict === 'unproven')
25
+ return { close: false, report: input.end.detail };
26
+ if (!input.ownBefore || input.occupied)
27
+ return { close: false };
28
+ if (input.end.verdict === 'merged')
29
+ return { close: true };
30
+ return { close: false };
31
+ }
32
+ // A squash leaves commits on the branch while its tree matches the base. That is reported once,
33
+ // the same way a failed fetch is, and nothing is closed.
34
+ function openBranch(detail) {
35
+ return {
36
+ close: false,
37
+ ownCommits: true,
38
+ ...(detail.includes('not provable') ? { report: detail } : {}),
39
+ };
40
+ }
@@ -0,0 +1,5 @@
1
+ export declare class DialectError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ /** Compile one pattern. `ignoreCase` is the stage's flag, never an inline `(?i)`. */
5
+ export declare function compilePattern(source: string, ignoreCase?: boolean): RegExp;