toolroll 0.9.32 → 0.9.34

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 (49) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/browser/workspace.css +1 -1
  3. package/dist/browser/workspace.js +17 -17
  4. package/dist/browser-crew.js +1 -0
  5. package/dist/browser-workspace.d.ts +2 -0
  6. package/dist/cli.d.ts +1 -1
  7. package/dist/cli.js +124 -63
  8. package/dist/coding-context.js +2 -2
  9. package/dist/coding-handoff.js +2 -2
  10. package/dist/contracts/contract-test.d.ts +45 -0
  11. package/dist/contracts/contract-test.js +69 -0
  12. package/dist/contracts/contract.d.ts +59 -0
  13. package/dist/contracts/contract.js +181 -0
  14. package/dist/contracts/plan.d.ts +58 -0
  15. package/dist/contracts/plan.js +67 -0
  16. package/dist/desktop-update.d.ts +1 -1
  17. package/dist/evidence.js +2 -2
  18. package/dist/guides.js +3 -0
  19. package/dist/knowledge-cli.d.ts +31 -0
  20. package/dist/knowledge-cli.js +35 -2
  21. package/dist/knowledge-ui.d.ts +1 -1
  22. package/dist/knowledge-ui.js +7 -0
  23. package/dist/operate.js +65 -13
  24. package/dist/plan.d.ts +12 -12
  25. package/dist/plan.js +129 -72
  26. package/dist/planner-source.js +2 -1
  27. package/dist/planner.js +55 -25
  28. package/dist/project-admission.d.ts +93 -0
  29. package/dist/project-admission.js +134 -0
  30. package/dist/project-delete-ui.js +5 -2
  31. package/dist/project-delete.js +1 -1
  32. package/dist/project-knowledge.d.ts +28 -3
  33. package/dist/project-knowledge.js +64 -25
  34. package/dist/project-learning.d.ts +33 -0
  35. package/dist/project-learning.js +105 -15
  36. package/dist/project-skills.js +27 -21
  37. package/dist/runner.d.ts +10 -0
  38. package/dist/runner.js +16 -0
  39. package/dist/scope.js +4 -3
  40. package/dist/serve.d.ts +4 -0
  41. package/dist/serve.js +111 -65
  42. package/dist/store.d.ts +2 -0
  43. package/dist/store.js +4 -0
  44. package/dist/surface.js +9 -3
  45. package/dist/text-limits.d.ts +17 -0
  46. package/dist/text-limits.js +16 -0
  47. package/dist/when-html.d.ts +2 -0
  48. package/dist/when-html.js +13 -0
  49. package/package.json +3 -2
package/dist/surface.js CHANGED
@@ -81,8 +81,14 @@ export const COMMAND_GUIDE = [
81
81
  operator('conversation read', 'explicitly record your read position at --message within --conversation'),
82
82
  operator('conversation follow', 'enable or pause automatic lead summaries with --conversation and --enabled true|false, within the existing paid chat authorization; passive chat --follow only reads updates'),
83
83
  operator('conversation stop', 'request stopping the exact --message in --conversation; retain uncertain work until its owner settles it'),
84
- operator("repos add", "connect a repository to the installation"),
85
- operator("repos remove", "disconnect a repository"),
84
+ { invocation: "repos add", synopsis: "add a project: a Git repository, in the console at once; the lead adds with its token", audience: "agent", agentMayInvoke: true, mutation: "identity-idempotent",
85
+ positionals: [{ name: "path", required: false, meaning: "the repository (default: the one you are in)" }],
86
+ flags: [jsonFlag, { name: "token", takesValue: true, meaning: "the lead token (or TOOLROLL_LEAD_TOKEN)" }],
87
+ notableReasons: ["not-git", "unavailable", "refused", "locked"] },
88
+ { invocation: "repos remove", synopsis: "remove a project from the console and the builder; its tasks and results stay saved", audience: "agent", agentMayInvoke: true, mutation: "identity-idempotent",
89
+ positionals: [{ name: "path", required: true, meaning: "the repository" }],
90
+ flags: [jsonFlag, { name: "token", takesValue: true, meaning: "the lead token (or TOOLROLL_LEAD_TOKEN)" }],
91
+ notableReasons: ["refused", "locked"] },
86
92
  operator("repos add-from-github", "preview, clone from GitHub, and connect - the console onboarding ceremony as a CLI verb"),
87
93
  { invocation: "contract", synopsis: "the machine contract: envelope version + capability tokens; --commands dumps this guide", audience: "agent", agentMayInvoke: true, mutation: "none",
88
94
  flags: [jsonFlag, { name: "commands", takesValue: false, meaning: "dump the declared command guide" }] },
@@ -114,7 +120,7 @@ export const COMMAND_GUIDE = [
114
120
  mutation: spec.mutation ? 'keyed' : 'none', inputSchema: spec.inputSchema,
115
121
  flags: Object.entries(sessionCliFlags(spec)).map(([name, arity]) => ({ name, takesValue: arity === 'value', meaning: name === 'key' ? 'keep the same key when reconciling; inspect after unknown delivery, never blind-retry' : `see session ${spec.operation} --help` })),
116
122
  })),
117
- ...KNOWLEDGE_DESCRIPTORS.map(spec => ({ invocation: `knowledge ${spec.action}`, synopsis: spec.synopsis, audience: "agent", agentMayInvoke: true, mutation: spec.mutation, flags: spec.flags, ...(spec.takesQuery ? { positionals: [{ name: "query", required: true, meaning: "search text or source file for impact" }] } : {}) })),
123
+ ...KNOWLEDGE_DESCRIPTORS.map(spec => ({ invocation: `knowledge ${spec.action}`, synopsis: spec.synopsis, audience: "audience" in spec ? spec.audience : "agent", agentMayInvoke: !("audience" in spec), mutation: spec.mutation, flags: spec.flags, ...(spec.takesQuery ? { positionals: [{ name: "query", required: true, meaning: "search text or source file for impact" }] } : {}) })),
118
124
  ...MEMORY_DESCRIPTORS.map(spec => ({ invocation: `memory ${spec.action}`, synopsis: spec.synopsis, audience: "agent", agentMayInvoke: true, mutation: spec.mutation, flags: spec.flags, ...(spec.takesQuery ? { positionals: [{ name: "query", required: true, meaning: "search text, a decision id, or the decision sentence" }] } : {}) })),
119
125
  // Flow writes carry an approver's credential: an agent runs them only as the person asked, after showing the preview.
120
126
  ...FLOWS_DESCRIPTORS.map(spec => ({ invocation: `flows ${spec.action}`, synopsis: spec.synopsis, audience: "agent", agentMayInvoke: true, mutation: spec.mutation, flags: spec.flags,
@@ -20,7 +20,24 @@ export declare const TEXT_LIMITS: {
20
20
  readonly reportSummary: 2500;
21
21
  /** What one flow step passes on to the steps after it. */
22
22
  readonly stageOutput: 12000;
23
+ /** The planner's whole handoff file, in UTF-8 bytes. */
24
+ readonly planPayloadBytes: number;
25
+ /** The plan document (markdown), in UTF-8 bytes. */
26
+ readonly planDocumentBytes: number;
27
+ /** The plan document's Approach section. */
28
+ readonly planApproach: 2000;
29
+ /** One Milestones, Dependencies, Risks or Proof item in the plan document. */
30
+ readonly planItem: 600;
31
+ /** One path a plan expects to touch. */
32
+ readonly planTouch: 200;
33
+ /** A planner's amendment note: why the filed contract must change. */
34
+ readonly planAmendment: 1000;
35
+ /** An acceptance criterion's id, statement and advisory how, in UTF-8 bytes. */
36
+ readonly acceptanceIdBytes: 40;
37
+ readonly acceptanceStatementBytes: 1000;
38
+ readonly acceptanceHowBytes: 500;
23
39
  };
40
+ export type TextLimitKey = keyof typeof TEXT_LIMITS;
24
41
  /** One chat message on each platform. Longer text is split across messages, never cut. Teams: the text one Adaptive Card
25
42
  * holds, well inside its 28 KB message. */
26
43
  export declare const PLATFORM_LIMITS: {
@@ -20,6 +20,22 @@ export const TEXT_LIMITS = {
20
20
  reportSummary: 2_500,
21
21
  /** What one flow step passes on to the steps after it. */
22
22
  stageOutput: 12_000,
23
+ /** The planner's whole handoff file, in UTF-8 bytes. */
24
+ planPayloadBytes: 64 * 1024,
25
+ /** The plan document (markdown), in UTF-8 bytes. */
26
+ planDocumentBytes: 16 * 1024,
27
+ /** The plan document's Approach section. */
28
+ planApproach: 2_000,
29
+ /** One Milestones, Dependencies, Risks or Proof item in the plan document. */
30
+ planItem: 600,
31
+ /** One path a plan expects to touch. */
32
+ planTouch: 200,
33
+ /** A planner's amendment note: why the filed contract must change. */
34
+ planAmendment: 1_000,
35
+ /** An acceptance criterion's id, statement and advisory how, in UTF-8 bytes. */
36
+ acceptanceIdBytes: 40,
37
+ acceptanceStatementBytes: 1_000,
38
+ acceptanceHowBytes: 500,
23
39
  };
24
40
  /** One chat message on each platform. Longer text is split across messages, never cut. Teams: the text one Adaptive Card
25
41
  * holds, well inside its 28 KB message. */
@@ -10,6 +10,8 @@ export declare function deadlineWords(deadline: {
10
10
  at: string;
11
11
  label: string;
12
12
  }, now?: Date, zone?: string): string;
13
+ /** How long ago, in one short mark: "now", "4m", "2h", "3d". A future stamp reads "now"; an unreadable one, "". */
14
+ export declare function shortAge(iso: string, now?: Date): string;
13
15
  /** The exact minute in `zone` ("2026-09-30 16:39", with " UTC" when it is UTC): a time's title, one hover away. */
14
16
  export declare function fullWhen(iso: string, zone?: string): string;
15
17
  /** Every server-rendered stamp (`whenHtml`'s `<time data-when>`) inside `root`, reworded by the one formatter in the
package/dist/when-html.js CHANGED
@@ -66,6 +66,19 @@ export function deadlineWords(deadline, now = new Date(), zone = viewerZone()) {
66
66
  const words = shortWhen(deadline.at, now, zone, true);
67
67
  return /^(?:\d|Tomorrow|Yesterday)/.test(words) ? `${deadline.label} ${words}` : `${deadline.label.replace(/ at$/, "")} ${words}`;
68
68
  }
69
+ /** How long ago, in one short mark: "now", "4m", "2h", "3d". A future stamp reads "now"; an unreadable one, "". */
70
+ export function shortAge(iso, now = new Date()) {
71
+ const at = new Date(iso).getTime();
72
+ if (Number.isNaN(at))
73
+ return "";
74
+ const minutes = Math.max(0, Math.floor((now.getTime() - at) / 60_000));
75
+ if (minutes < 1)
76
+ return "now";
77
+ if (minutes < 60)
78
+ return `${minutes}m`;
79
+ const hours = Math.floor(minutes / 60);
80
+ return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;
81
+ }
69
82
  /** The exact minute in `zone` ("2026-09-30 16:39", with " UTC" when it is UTC): a time's title, one hover away. */
70
83
  export function fullWhen(iso, zone = "UTC") {
71
84
  const at = new Date(iso);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolroll",
3
- "version": "0.9.32",
3
+ "version": "0.9.34",
4
4
  "description": "A control plane for unattended coding agents — queue tasks, walk away, come back to pull requests. Agents build in leased worktrees, never touch your default branch, and interrupt you only for decisions that need a human.",
5
5
  "directories": {
6
6
  "doc": "docs"
@@ -120,6 +120,7 @@
120
120
  "tailwind-merge": "3.7.0",
121
121
  "typescript-parser": "npm:typescript@6.0.3",
122
122
  "use-stick-to-bottom": "1.1.6",
123
- "yaml": "2.9.1"
123
+ "yaml": "2.9.1",
124
+ "zod": "^4.6.5"
124
125
  }
125
126
  }