@ai-setting/roy-task-plugin 0.7.4 → 0.7.6

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.
@@ -46,13 +46,20 @@ Report progress as you go, not only at the end:
46
46
  If the scope changes, `task_update` the description/goals instead of silently
47
47
  doing something else.
48
48
 
49
- ### 4. Record milestones — `task_operation_create`
49
+ ### 4. Record milestones — `task_operation_create` — **as you work**
50
+ Call this tool the moment a stage is reached — **not after the fact**,
51
+ not in a batch at the end. Finished a chunk of code? A test just went
52
+ green? Hit a blocker? Made a decision? Record it **immediately**, then
53
+ keep working. The record is the running log of the work, written while
54
+ it happens.
55
+
50
56
  This tool has **two orthogonal dimensions** and you must keep them distinct:
51
57
  - **state / milestone dimension** — `milestone_type` + `milestone_title` +
52
58
  `milestone_description`: *what* was reached (e.g. "GREEN: all tests pass").
53
59
  - **process dimension** — `process_description`: *how* you got there —
54
- strategy + tool steps, strictly **100–150 characters**.
55
- Too short = rejected (no value); too long = rejected (use the session log).
60
+ the operations just performed and why, written in the moment,
61
+ **100–500 characters**. Too short = rejected (no value);
62
+ too long = rejected (that is a log, not a summary).
56
63
 
57
64
  Rules: do **not** use the process field to restate the milestone, and do not
58
65
  use milestones as a substitute for progress. Milestones mark *state
@@ -32,7 +32,7 @@ If you do have the MCP server, call `task_operation_create` with:
32
32
  `solution`, `decision`, `review`, `completed`
33
33
  - `milestone_title` — one line
34
34
  - `milestone_description` — what was reached
35
- - `process_description` — **how** you got there, strictly 100–150 characters
35
+ - `process_description` — **how** you got there, 100–500 characters
36
36
  (this is enforced; too short or too long is rejected)
37
37
 
38
38
  Keep the two dimensions distinct: the milestone says *what* was reached, the
package/dist/cli.js CHANGED
@@ -444,126 +444,6 @@ class NdjsonAssembler {
444
444
  }
445
445
  }
446
446
 
447
- // ../../../packages/cli/src/daemon/runners/codex-stream.ts
448
- var CODEX_ITEM_TYPES = Object.freeze({
449
- AGENT_MESSAGE: "agent_message",
450
- COMMAND_EXECUTION: "command_execution",
451
- MCP_TOOL_CALL: "mcp_tool_call",
452
- ERROR: "error"
453
- });
454
-
455
- class CodexStreamDecoder {
456
- lines = new LineSplitter;
457
- state = { tools: [], errors: [], turnCompleted: false };
458
- mcpSeen = new Set;
459
- pushChunk(chunk) {
460
- for (const line of this.lines.pushChunk(chunk))
461
- this.consume(line);
462
- }
463
- finish() {
464
- for (const line of this.lines.finish())
465
- this.consume(line);
466
- return this.toResult();
467
- }
468
- snapshot() {
469
- return { ...this.state, tools: [...this.state.tools], errors: [...this.state.errors] };
470
- }
471
- consume(rawLine) {
472
- const line = rawLine.trim();
473
- if (!line.startsWith("{"))
474
- return;
475
- let event;
476
- try {
477
- event = JSON.parse(line);
478
- } catch {
479
- return;
480
- }
481
- if (typeof event !== "object" || event === null)
482
- return;
483
- const ev = event;
484
- if (ev.type === "thread.started") {
485
- const id = ev.thread_id;
486
- if (typeof id === "string" && id)
487
- this.state.sessionId = id;
488
- return;
489
- }
490
- if (ev.type === "turn.completed") {
491
- this.state.turnCompleted = true;
492
- return;
493
- }
494
- if (ev.type === "item.started" || ev.type === "item.completed") {
495
- this.consumeItem(ev.item, ev.type === "item.completed");
496
- }
497
- }
498
- consumeItem(raw, completed) {
499
- if (typeof raw !== "object" || raw === null)
500
- return;
501
- const item = raw;
502
- if (item.type === CODEX_ITEM_TYPES.AGENT_MESSAGE) {
503
- if (typeof item.text === "string" && item.text.length > 0) {
504
- this.state.text = item.text;
505
- }
506
- return;
507
- }
508
- if (item.type === CODEX_ITEM_TYPES.ERROR) {
509
- if (typeof item.message === "string" && item.message.length > 0) {
510
- this.state.errors.push(item.message);
511
- }
512
- return;
513
- }
514
- if (item.type === CODEX_ITEM_TYPES.COMMAND_EXECUTION) {
515
- const id = item.id;
516
- if (typeof id === "string" && id && this.state.tools.includes(id)) {} else {
517
- this.state.tools.push(typeof id === "string" ? id : `cmd-${this.state.tools.length}`);
518
- }
519
- if (completed && this.state.createdTask === undefined) {
520
- this.state.createdTask = extractCreatedTask(item.aggregated_output);
521
- }
522
- return;
523
- }
524
- if (item.type === CODEX_ITEM_TYPES.MCP_TOOL_CALL) {
525
- const id = item.id;
526
- if (typeof id === "string" && id) {
527
- if (this.mcpSeen.has(id))
528
- return;
529
- this.mcpSeen.add(id);
530
- }
531
- const name = typeof item.tool === "string" && item.tool ? item.tool : undefined;
532
- this.state.tools.push(name ?? (typeof id === "string" && id ? id : `mcp-${this.state.tools.length}`));
533
- return;
534
- }
535
- }
536
- toResult() {
537
- const result = {
538
- text: this.state.text ?? ""
539
- };
540
- if (this.state.sessionId)
541
- result.sessionId = this.state.sessionId;
542
- if (this.state.tools.length > 0) {
543
- result.toolCalls = this.state.tools.length;
544
- result.tools = [...this.state.tools];
545
- }
546
- if (this.state.createdTask)
547
- result.createdTask = this.state.createdTask;
548
- return result;
549
- }
550
- }
551
-
552
- // ../../../packages/cli/src/daemon/runners/codex-sessions.ts
553
- function createCodexSessionRegistry() {
554
- const sessions = new Map;
555
- return {
556
- get: (key) => sessions.get(key),
557
- set: (key, id) => {
558
- sessions.set(key, id);
559
- },
560
- delete: (key) => {
561
- sessions.delete(key);
562
- },
563
- size: () => sessions.size
564
- };
565
- }
566
-
567
447
  // ../../../packages/cli/src/daemon/runners/claude-agents.ts
568
448
  var CLAUDE_ROY_AGENT_NAME = "roy";
569
449
  var ROY_AGENT_DESCRIPTION = "Roy — task-as-first-class-citizen agent. Uses the roy-agent task lifecycle " + "(task_tree → task_create → task_update → task_operation_create → task_complete) " + "so every piece of work is tracked in the local task store.";
@@ -631,13 +511,20 @@ Report progress as you go, not only at the end:
631
511
  If the scope changes, \`task_update\` the description/goals instead of silently
632
512
  doing something else.
633
513
 
634
- ### 4. Record milestones — \`task_operation_create\`
514
+ ### 4. Record milestones — \`task_operation_create\` — **as you work**
515
+ Call this tool the moment a stage is reached — **not after the fact**,
516
+ not in a batch at the end. Finished a chunk of code? A test just went
517
+ green? Hit a blocker? Made a decision? Record it **immediately**, then
518
+ keep working. The record is the running log of the work, written while
519
+ it happens.
520
+
635
521
  This tool has **two orthogonal dimensions** and you must keep them distinct:
636
522
  - **state / milestone dimension** — \`milestone_type\` + \`milestone_title\` +
637
523
  \`milestone_description\`: *what* was reached (e.g. "GREEN: all tests pass").
638
524
  - **process dimension** — \`process_description\`: *how* you got there —
639
- strategy + tool steps, strictly **100–150 characters**.
640
- Too short = rejected (no value); too long = rejected (use the session log).
525
+ the operations just performed and why, written in the moment,
526
+ **100–500 characters**. Too short = rejected (no value);
527
+ too long = rejected (that is a log, not a summary).
641
528
 
642
529
  Rules: do **not** use the process field to restate the milestone, and do not
643
530
  use milestones as a substitute for progress. Milestones mark *state
@@ -714,6 +601,159 @@ function buildClaudeAgentsJson(opts = {}) {
714
601
  return JSON.stringify({ [opts.name ?? CLAUDE_ROY_AGENT_NAME]: def });
715
602
  }
716
603
 
604
+ // ../../../packages/cli/src/daemon/runners/codex-stream.ts
605
+ var CODEX_ITEM_TYPES = Object.freeze({
606
+ AGENT_MESSAGE: "agent_message",
607
+ COMMAND_EXECUTION: "command_execution",
608
+ MCP_TOOL_CALL: "mcp_tool_call",
609
+ ERROR: "error"
610
+ });
611
+ function isCreationTool(tool) {
612
+ if (isTaskCreateTool(tool))
613
+ return true;
614
+ const bare = tool.includes("/") ? tool.slice(tool.lastIndexOf("/") + 1) : tool;
615
+ return isTaskCreateTool(bare);
616
+ }
617
+ function isSuccessfulMcpStatus(status) {
618
+ return status === undefined || status === "completed";
619
+ }
620
+ function isRoyTaskServer(server) {
621
+ return server === undefined || server === ROY_TASK_MCP_SERVER;
622
+ }
623
+ function mcpResultText(result) {
624
+ if (typeof result !== "object" || result === null)
625
+ return;
626
+ const content = result.content;
627
+ if (!Array.isArray(content))
628
+ return;
629
+ for (const block of content) {
630
+ if (typeof block === "object" && block !== null && block.type === "text" && typeof block.text === "string") {
631
+ return block.text;
632
+ }
633
+ }
634
+ return;
635
+ }
636
+
637
+ class CodexStreamDecoder {
638
+ lines = new LineSplitter;
639
+ state = { tools: [], errors: [], turnCompleted: false };
640
+ mcpSeen = new Set;
641
+ pushChunk(chunk) {
642
+ for (const line of this.lines.pushChunk(chunk))
643
+ this.consume(line);
644
+ }
645
+ finish() {
646
+ for (const line of this.lines.finish())
647
+ this.consume(line);
648
+ return this.toResult();
649
+ }
650
+ snapshot() {
651
+ return { ...this.state, tools: [...this.state.tools], errors: [...this.state.errors] };
652
+ }
653
+ consume(rawLine) {
654
+ const line = rawLine.trim();
655
+ if (!line.startsWith("{"))
656
+ return;
657
+ let event;
658
+ try {
659
+ event = JSON.parse(line);
660
+ } catch {
661
+ return;
662
+ }
663
+ if (typeof event !== "object" || event === null)
664
+ return;
665
+ const ev = event;
666
+ if (ev.type === "thread.started") {
667
+ const id = ev.thread_id;
668
+ if (typeof id === "string" && id)
669
+ this.state.sessionId = id;
670
+ return;
671
+ }
672
+ if (ev.type === "turn.completed") {
673
+ this.state.turnCompleted = true;
674
+ return;
675
+ }
676
+ if (ev.type === "item.started" || ev.type === "item.completed") {
677
+ this.consumeItem(ev.item, ev.type === "item.completed");
678
+ }
679
+ }
680
+ consumeItem(raw, completed) {
681
+ if (typeof raw !== "object" || raw === null)
682
+ return;
683
+ const item = raw;
684
+ if (item.type === CODEX_ITEM_TYPES.AGENT_MESSAGE) {
685
+ if (typeof item.text === "string" && item.text.length > 0) {
686
+ this.state.text = item.text;
687
+ }
688
+ return;
689
+ }
690
+ if (item.type === CODEX_ITEM_TYPES.ERROR) {
691
+ if (typeof item.message === "string" && item.message.length > 0) {
692
+ this.state.errors.push(item.message);
693
+ }
694
+ return;
695
+ }
696
+ if (item.type === CODEX_ITEM_TYPES.COMMAND_EXECUTION) {
697
+ const id = item.id;
698
+ if (typeof id === "string" && id && this.state.tools.includes(id)) {} else {
699
+ this.state.tools.push(typeof id === "string" ? id : `cmd-${this.state.tools.length}`);
700
+ }
701
+ if (completed && this.state.createdTask === undefined) {
702
+ this.state.createdTask = extractCreatedTask(item.aggregated_output);
703
+ }
704
+ return;
705
+ }
706
+ if (item.type === CODEX_ITEM_TYPES.MCP_TOOL_CALL) {
707
+ const id = item.id;
708
+ const seen = typeof id === "string" && id && this.mcpSeen.has(id);
709
+ if (typeof id === "string" && id)
710
+ this.mcpSeen.add(id);
711
+ if (!seen) {
712
+ const name = typeof item.tool === "string" && item.tool ? item.tool : undefined;
713
+ this.state.tools.push(name ?? (typeof id === "string" && id ? id : `mcp-${this.state.tools.length}`));
714
+ }
715
+ if (completed && this.state.createdTask === undefined && isSuccessfulMcpStatus(item.status) && typeof item.tool === "string" && isCreationTool(item.tool) && isRoyTaskServer(item.server)) {
716
+ const text = mcpResultText(item.result);
717
+ if (text !== undefined) {
718
+ const args = item.arguments;
719
+ const hint = typeof args?.title === "string" ? args.title : undefined;
720
+ this.state.createdTask = extractCreatedTask(text, hint);
721
+ }
722
+ }
723
+ return;
724
+ }
725
+ }
726
+ toResult() {
727
+ const result = {
728
+ text: this.state.text ?? ""
729
+ };
730
+ if (this.state.sessionId)
731
+ result.sessionId = this.state.sessionId;
732
+ if (this.state.tools.length > 0) {
733
+ result.toolCalls = this.state.tools.length;
734
+ result.tools = [...this.state.tools];
735
+ }
736
+ if (this.state.createdTask)
737
+ result.createdTask = this.state.createdTask;
738
+ return result;
739
+ }
740
+ }
741
+
742
+ // ../../../packages/cli/src/daemon/runners/codex-sessions.ts
743
+ function createCodexSessionRegistry() {
744
+ const sessions = new Map;
745
+ return {
746
+ get: (key) => sessions.get(key),
747
+ set: (key, id) => {
748
+ sessions.set(key, id);
749
+ },
750
+ delete: (key) => {
751
+ sessions.delete(key);
752
+ },
753
+ size: () => sessions.size
754
+ };
755
+ }
756
+
717
757
  // ../../../packages/cli/src/daemon/runners/claude.ts
718
758
  import { createHash } from "node:crypto";
719
759
  import { appendFileSync, existsSync } from "node:fs";
@@ -3230,7 +3270,7 @@ function formatStatus(report) {
3230
3270
  }
3231
3271
 
3232
3272
  // ../../../packages/cli/src/main.ts
3233
- var VERSION = "0.7.4";
3273
+ var VERSION = "0.7.6";
3234
3274
  async function main(argv) {
3235
3275
  const parsed = parseArgs(argv);
3236
3276
  switch (parsed.command) {