@mclawnet/task 0.1.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 +100 -0
  2. package/dist/__tests__/compute-lead-briefing.test.d.ts +2 -0
  3. package/dist/__tests__/compute-lead-briefing.test.d.ts.map +1 -0
  4. package/dist/__tests__/compute-lead-briefing.test.js +81 -0
  5. package/dist/__tests__/compute-lead-briefing.test.js.map +1 -0
  6. package/dist/__tests__/compute-member-briefing.test.d.ts +2 -0
  7. package/dist/__tests__/compute-member-briefing.test.d.ts.map +1 -0
  8. package/dist/__tests__/compute-member-briefing.test.js +36 -0
  9. package/dist/__tests__/compute-member-briefing.test.js.map +1 -0
  10. package/dist/__tests__/compute-task-briefing.test.d.ts +2 -0
  11. package/dist/__tests__/compute-task-briefing.test.d.ts.map +1 -0
  12. package/dist/__tests__/compute-task-briefing.test.js +72 -0
  13. package/dist/__tests__/compute-task-briefing.test.js.map +1 -0
  14. package/dist/__tests__/dag.test.d.ts +2 -0
  15. package/dist/__tests__/dag.test.d.ts.map +1 -0
  16. package/dist/__tests__/dag.test.js +81 -0
  17. package/dist/__tests__/dag.test.js.map +1 -0
  18. package/dist/__tests__/format-lead-briefing.test.d.ts +2 -0
  19. package/dist/__tests__/format-lead-briefing.test.d.ts.map +1 -0
  20. package/dist/__tests__/format-lead-briefing.test.js +70 -0
  21. package/dist/__tests__/format-lead-briefing.test.js.map +1 -0
  22. package/dist/__tests__/format-member-briefing.test.d.ts +2 -0
  23. package/dist/__tests__/format-member-briefing.test.d.ts.map +1 -0
  24. package/dist/__tests__/format-member-briefing.test.js +33 -0
  25. package/dist/__tests__/format-member-briefing.test.js.map +1 -0
  26. package/dist/__tests__/format-task-briefing.test.d.ts +2 -0
  27. package/dist/__tests__/format-task-briefing.test.d.ts.map +1 -0
  28. package/dist/__tests__/format-task-briefing.test.js +74 -0
  29. package/dist/__tests__/format-task-briefing.test.js.map +1 -0
  30. package/dist/__tests__/locking.test.d.ts +2 -0
  31. package/dist/__tests__/locking.test.d.ts.map +1 -0
  32. package/dist/__tests__/locking.test.js +38 -0
  33. package/dist/__tests__/locking.test.js.map +1 -0
  34. package/dist/__tests__/meta.test.d.ts +2 -0
  35. package/dist/__tests__/meta.test.d.ts.map +1 -0
  36. package/dist/__tests__/meta.test.js +48 -0
  37. package/dist/__tests__/meta.test.js.map +1 -0
  38. package/dist/__tests__/path.test.d.ts +2 -0
  39. package/dist/__tests__/path.test.d.ts.map +1 -0
  40. package/dist/__tests__/path.test.js +45 -0
  41. package/dist/__tests__/path.test.js.map +1 -0
  42. package/dist/__tests__/schema.test.d.ts +2 -0
  43. package/dist/__tests__/schema.test.d.ts.map +1 -0
  44. package/dist/__tests__/schema.test.js +49 -0
  45. package/dist/__tests__/schema.test.js.map +1 -0
  46. package/dist/__tests__/store-create-deps.test.d.ts +2 -0
  47. package/dist/__tests__/store-create-deps.test.d.ts.map +1 -0
  48. package/dist/__tests__/store-create-deps.test.js +23 -0
  49. package/dist/__tests__/store-create-deps.test.js.map +1 -0
  50. package/dist/__tests__/store-link.test.d.ts +2 -0
  51. package/dist/__tests__/store-link.test.d.ts.map +1 -0
  52. package/dist/__tests__/store-link.test.js +64 -0
  53. package/dist/__tests__/store-link.test.js.map +1 -0
  54. package/dist/__tests__/store-rebuild.test.d.ts +2 -0
  55. package/dist/__tests__/store-rebuild.test.d.ts.map +1 -0
  56. package/dist/__tests__/store-rebuild.test.js +47 -0
  57. package/dist/__tests__/store-rebuild.test.js.map +1 -0
  58. package/dist/__tests__/store.test.d.ts +2 -0
  59. package/dist/__tests__/store.test.d.ts.map +1 -0
  60. package/dist/__tests__/store.test.js +70 -0
  61. package/dist/__tests__/store.test.js.map +1 -0
  62. package/dist/briefings/compute-lead.d.ts +17 -0
  63. package/dist/briefings/compute-lead.d.ts.map +1 -0
  64. package/dist/briefings/compute-lead.js +52 -0
  65. package/dist/briefings/compute-lead.js.map +1 -0
  66. package/dist/briefings/compute-member.d.ts +12 -0
  67. package/dist/briefings/compute-member.d.ts.map +1 -0
  68. package/dist/briefings/compute-member.js +30 -0
  69. package/dist/briefings/compute-member.js.map +1 -0
  70. package/dist/briefings/compute-task.d.ts +17 -0
  71. package/dist/briefings/compute-task.d.ts.map +1 -0
  72. package/dist/briefings/compute-task.js +60 -0
  73. package/dist/briefings/compute-task.js.map +1 -0
  74. package/dist/briefings/format-lead.d.ts +19 -0
  75. package/dist/briefings/format-lead.d.ts.map +1 -0
  76. package/dist/briefings/format-lead.js +47 -0
  77. package/dist/briefings/format-lead.js.map +1 -0
  78. package/dist/briefings/format-member.d.ts +18 -0
  79. package/dist/briefings/format-member.d.ts.map +1 -0
  80. package/dist/briefings/format-member.js +24 -0
  81. package/dist/briefings/format-member.js.map +1 -0
  82. package/dist/briefings/format-task.d.ts +19 -0
  83. package/dist/briefings/format-task.d.ts.map +1 -0
  84. package/dist/briefings/format-task.js +48 -0
  85. package/dist/briefings/format-task.js.map +1 -0
  86. package/dist/dag.d.ts +10 -0
  87. package/dist/dag.d.ts.map +1 -0
  88. package/dist/dag.js +33 -0
  89. package/dist/dag.js.map +1 -0
  90. package/dist/index.d.ts +17 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +13 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/locking.d.ts +8 -0
  95. package/dist/locking.d.ts.map +1 -0
  96. package/dist/locking.js +19 -0
  97. package/dist/locking.js.map +1 -0
  98. package/dist/meta.d.ts +21 -0
  99. package/dist/meta.d.ts.map +1 -0
  100. package/dist/meta.js +37 -0
  101. package/dist/meta.js.map +1 -0
  102. package/dist/path.d.ts +7 -0
  103. package/dist/path.d.ts.map +1 -0
  104. package/dist/path.js +34 -0
  105. package/dist/path.js.map +1 -0
  106. package/dist/schema.d.ts +42 -0
  107. package/dist/schema.d.ts.map +1 -0
  108. package/dist/schema.js +41 -0
  109. package/dist/schema.js.map +1 -0
  110. package/dist/store.d.ts +47 -0
  111. package/dist/store.d.ts.map +1 -0
  112. package/dist/store.js +248 -0
  113. package/dist/store.js.map +1 -0
  114. package/package.json +33 -0
@@ -0,0 +1,17 @@
1
+ import type { TaskStore } from "../store.js";
2
+ import type { LeadBriefingBody } from "./format-lead.js";
3
+ /**
4
+ * Compute the queen-facing situation summary body for a swarm.
5
+ *
6
+ * Pure-ish: reads from TaskStore, no mutations. Mirrors the bucket logic that
7
+ * previously lived inline in `handleLeadBriefing` (mcp-server). Caller is
8
+ * responsible for resolving `queenInstanceId` (e.g. via recovery.json on the
9
+ * MCP side, or via the live coordinator on the swarm side); pass `null` when
10
+ * the queen cannot be identified — `lead_owned` will then be empty.
11
+ *
12
+ * Phase-1 simplifications retained:
13
+ * - `assign_reviewer` is always [] (no reviewer field in schema).
14
+ * - `clarify` uses the "?" heuristic on the latest comment.
15
+ */
16
+ export declare function computeLeadBriefing(store: TaskStore, swarmId: string, queenInstanceId: string | null): LeadBriefingBody;
17
+ //# sourceMappingURL=compute-lead.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-lead.d.ts","sourceRoot":"","sources":["../../src/briefings/compute-lead.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,IAAI,GAC7B,gBAAgB,CA0ClB"}
@@ -0,0 +1,52 @@
1
+ import { classifyBlockers } from "../dag.js";
2
+ /**
3
+ * Compute the queen-facing situation summary body for a swarm.
4
+ *
5
+ * Pure-ish: reads from TaskStore, no mutations. Mirrors the bucket logic that
6
+ * previously lived inline in `handleLeadBriefing` (mcp-server). Caller is
7
+ * responsible for resolving `queenInstanceId` (e.g. via recovery.json on the
8
+ * MCP side, or via the live coordinator on the swarm side); pass `null` when
9
+ * the queen cannot be identified — `lead_owned` will then be empty.
10
+ *
11
+ * Phase-1 simplifications retained:
12
+ * - `assign_reviewer` is always [] (no reviewer field in schema).
13
+ * - `clarify` uses the "?" heuristic on the latest comment.
14
+ */
15
+ export function computeLeadBriefing(store, swarmId, queenInstanceId) {
16
+ const tasks = store
17
+ .list()
18
+ .map((e) => store.tryGet(e.id))
19
+ .filter((t) => t !== null)
20
+ .filter((t) => t.swarmId === swarmId);
21
+ const assignOwner = [];
22
+ const assignReviewer = []; // Phase 1: always empty.
23
+ const clarify = [];
24
+ const repairDependencies = [];
25
+ const leadOwned = [];
26
+ for (const t of tasks) {
27
+ if (t.status === "pending" && t.owner === null) {
28
+ assignOwner.push(t);
29
+ }
30
+ if (t.comments.length > 0) {
31
+ const latest = t.comments[t.comments.length - 1];
32
+ if (latest.body.includes("?")) {
33
+ clarify.push(t);
34
+ }
35
+ }
36
+ const classification = classifyBlockers(t, store);
37
+ if (classification.broken.length > 0) {
38
+ repairDependencies.push(t);
39
+ }
40
+ if (queenInstanceId !== null && t.owner === queenInstanceId) {
41
+ leadOwned.push(t);
42
+ }
43
+ }
44
+ return {
45
+ assign_owner: assignOwner,
46
+ assign_reviewer: assignReviewer,
47
+ clarify,
48
+ repair_dependencies: repairDependencies,
49
+ lead_owned: leadOwned,
50
+ };
51
+ }
52
+ //# sourceMappingURL=compute-lead.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-lead.js","sourceRoot":"","sources":["../../src/briefings/compute-lead.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAG7C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAgB,EAChB,OAAe,EACf,eAA8B;IAE9B,MAAM,KAAK,GAAG,KAAK;SAChB,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC9B,MAAM,CAAC,CAAC,CAAC,EAAa,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;SACpC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;IAExC,MAAM,WAAW,GAAW,EAAE,CAAC;IAC/B,MAAM,cAAc,GAAW,EAAE,CAAC,CAAC,yBAAyB;IAC5D,MAAM,OAAO,GAAW,EAAE,CAAC;IAC3B,MAAM,kBAAkB,GAAW,EAAE,CAAC;IACtC,MAAM,SAAS,GAAW,EAAE,CAAC;IAE7B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC/C,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;QAED,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACjD,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,MAAM,cAAc,GAAG,gBAAgB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAClD,IAAI,cAAc,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,IAAI,eAAe,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,KAAK,eAAe,EAAE,CAAC;YAC5D,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO;QACL,YAAY,EAAE,WAAW;QACzB,eAAe,EAAE,cAAc;QAC/B,OAAO;QACP,mBAAmB,EAAE,kBAAkB;QACvC,UAAU,EAAE,SAAS;KACtB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { MemberBriefingBody } from "./format-member.js";
2
+ export interface ComputeMemberBriefingArgs {
3
+ swarmId: string;
4
+ instanceId: string;
5
+ /** "queen" produces queen-flavoured rules; anything else is treated as a worker. */
6
+ roleType: string;
7
+ }
8
+ /**
9
+ * Build the member briefing body. Pure: no I/O, no side effects.
10
+ */
11
+ export declare function computeMemberBriefing(args: ComputeMemberBriefingArgs): MemberBriefingBody;
12
+ //# sourceMappingURL=compute-member.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-member.d.ts","sourceRoot":"","sources":["../../src/briefings/compute-member.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC;CAClB;AAsBD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,yBAAyB,GAAG,kBAAkB,CAOzF"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Hardcoded boot rules for queen vs. worker. Verbatim from the previous
3
+ * `handleMemberBriefing` body so the JSON shape is byte-identical.
4
+ */
5
+ const QUEEN_RULES = [
6
+ "每次开始一项工作前先调用 lead_briefing 查看 assign_owner / repair_dependencies / clarify 等桶。",
7
+ "通过 task_set_owner 给 pending 任务分配 owner,通过 task_link/task_unlink 维护依赖图。",
8
+ "状态变更必须用 task_set_status,不要直接 mutate task 文件。",
9
+ "需要补充上下文或决策时,使用 task_add_comment 记录。",
10
+ "跨角色沟通走 message_send,不要直接 mutate 别人的 task。",
11
+ ];
12
+ const WORKER_RULES = [
13
+ "每次开始一项工作前先调用 task_briefing 查看 actionable 列表。",
14
+ "接到 inbox 消息后,必要时通过 task_create_from_message 派生新 task。",
15
+ "状态变更必须用 task_set_status,不要直接 mutate task 文件。",
16
+ "完成或进展评论使用 task_add_comment 记录。",
17
+ "跨角色沟通走 message_send,不要直接 mutate 别人的 task。",
18
+ ];
19
+ /**
20
+ * Build the member briefing body. Pure: no I/O, no side effects.
21
+ */
22
+ export function computeMemberBriefing(args) {
23
+ const { swarmId, instanceId, roleType } = args;
24
+ const rules = roleType === "queen" ? [...QUEEN_RULES] : [...WORKER_RULES];
25
+ return {
26
+ rules,
27
+ bootstrap: { swarmId, instanceId, roleType },
28
+ };
29
+ }
30
+ //# sourceMappingURL=compute-member.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-member.js","sourceRoot":"","sources":["../../src/briefings/compute-member.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,MAAM,WAAW,GAAsB;IACrC,gFAAgF;IAChF,wEAAwE;IACxE,8CAA8C;IAC9C,qCAAqC;IACrC,2CAA2C;CACnC,CAAC;AAEX,MAAM,YAAY,GAAsB;IACtC,8CAA8C;IAC9C,uDAAuD;IACvD,8CAA8C;IAC9C,gCAAgC;IAChC,2CAA2C;CACnC,CAAC;AAEX;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAA+B;IACnE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC/C,MAAM,KAAK,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC;IAC1E,OAAO;QACL,KAAK;QACL,SAAS,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE;KAC7C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { TaskStore } from "../store.js";
2
+ import type { TaskBriefingBody } from "./format-task.js";
3
+ /**
4
+ * Compute the per-instance task briefing body for a swarm.
5
+ *
6
+ * Pure-ish: reads from the TaskStore (filesystem-backed) but performs no
7
+ * mutations. Mirrors the bucket-classification logic that previously lived
8
+ * inline in `handleTaskBriefing` (mcp-server). Used by both the MCP handler
9
+ * and `SwarmCoordinator.spawnRole` boot-time injection.
10
+ *
11
+ * Simplifications inherited from Phase 1 schema:
12
+ * - No `priority` field, so actionable is sorted by createdAt asc only.
13
+ * - No `reviewer` field, so awareness only checks waiting-deps.
14
+ * - Warnings cover broken deps + orphaned in_progress.
15
+ */
16
+ export declare function computeTaskBriefing(store: TaskStore, swarmId: string, instanceId: string): TaskBriefingBody;
17
+ //# sourceMappingURL=compute-task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-task.d.ts","sourceRoot":"","sources":["../../src/briefings/compute-task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,gBAAgB,CAoDlB"}
@@ -0,0 +1,60 @@
1
+ import { classifyBlockers } from "../dag.js";
2
+ /**
3
+ * Compute the per-instance task briefing body for a swarm.
4
+ *
5
+ * Pure-ish: reads from the TaskStore (filesystem-backed) but performs no
6
+ * mutations. Mirrors the bucket-classification logic that previously lived
7
+ * inline in `handleTaskBriefing` (mcp-server). Used by both the MCP handler
8
+ * and `SwarmCoordinator.spawnRole` boot-time injection.
9
+ *
10
+ * Simplifications inherited from Phase 1 schema:
11
+ * - No `priority` field, so actionable is sorted by createdAt asc only.
12
+ * - No `reviewer` field, so awareness only checks waiting-deps.
13
+ * - Warnings cover broken deps + orphaned in_progress.
14
+ */
15
+ export function computeTaskBriefing(store, swarmId, instanceId) {
16
+ const all = store
17
+ .list()
18
+ .map((e) => store.tryGet(e.id))
19
+ .filter((t) => t !== null)
20
+ .filter((t) => t.swarmId === swarmId);
21
+ const actionable = [];
22
+ const awareness = [];
23
+ let blocked = 0;
24
+ let waitingOnUser = 0;
25
+ const warnings = [];
26
+ for (const t of all) {
27
+ const classification = classifyBlockers(t, store);
28
+ if (classification.broken.length > 0) {
29
+ warnings.push(`broken-deps: task ${t.id} has cancelled/missing dependencies [${classification.broken.join(", ")}]`);
30
+ }
31
+ if (t.status === "in_progress" && t.owner === null) {
32
+ warnings.push(`orphaned in_progress: task ${t.id} is in_progress but has no owner`);
33
+ }
34
+ if (classification.isBlocked)
35
+ blocked++;
36
+ if (t.owner !== instanceId)
37
+ continue;
38
+ const ownedActive = t.status === "pending" || t.status === "in_progress";
39
+ if (ownedActive && !classification.isBlocked) {
40
+ actionable.push(t);
41
+ }
42
+ if (classification.waiting.length > 0) {
43
+ awareness.push(t);
44
+ waitingOnUser++;
45
+ }
46
+ }
47
+ actionable.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
48
+ return {
49
+ actionable,
50
+ awareness,
51
+ counters: {
52
+ actionable: actionable.length,
53
+ awareness: awareness.length,
54
+ blocked,
55
+ waitingOnUser,
56
+ },
57
+ warnings,
58
+ };
59
+ }
60
+ //# sourceMappingURL=compute-task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-task.js","sourceRoot":"","sources":["../../src/briefings/compute-task.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAG7C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAgB,EAChB,OAAe,EACf,UAAkB;IAElB,MAAM,GAAG,GAAG,KAAK;SACd,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC9B,MAAM,CAAC,CAAC,CAAC,EAAa,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;SACpC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;IAExC,MAAM,UAAU,GAAW,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAW,EAAE,CAAC;IAC7B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,cAAc,GAAG,gBAAgB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAElD,IAAI,cAAc,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,QAAQ,CAAC,IAAI,CACX,qBAAqB,CAAC,CAAC,EAAE,wCAAwC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACrG,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,KAAK,aAAa,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACnD,QAAQ,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,EAAE,kCAAkC,CAAC,CAAC;QACtF,CAAC;QAED,IAAI,cAAc,CAAC,SAAS;YAAE,OAAO,EAAE,CAAC;QAExC,IAAI,CAAC,CAAC,KAAK,KAAK,UAAU;YAAE,SAAS;QAErC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC;QACzE,IAAI,WAAW,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;YAC7C,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,cAAc,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,aAAa,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAElE,OAAO;QACL,UAAU;QACV,SAAS;QACT,QAAQ,EAAE;YACR,UAAU,EAAE,UAAU,CAAC,MAAM;YAC7B,SAAS,EAAE,SAAS,CAAC,MAAM;YAC3B,OAAO;YACP,aAAa;SACd;QACD,QAAQ;KACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { Task } from "../schema.js";
2
+ export interface LeadBriefingBody {
3
+ assign_owner: Task[];
4
+ /**
5
+ * v1: always [] from handleLeadBriefing (reviewer field does not exist yet).
6
+ * Kept in the type for forward compatibility, but intentionally NOT rendered
7
+ * even if populated — see renderer below.
8
+ */
9
+ assign_reviewer: Task[];
10
+ clarify: Task[];
11
+ repair_dependencies: Task[];
12
+ lead_owned: Task[];
13
+ }
14
+ export interface FormatLeadBriefingOpts {
15
+ /** Max items per bucket. Default 10. */
16
+ maxItems?: number;
17
+ }
18
+ export declare function formatLeadBriefing(body: LeadBriefingBody, opts?: FormatLeadBriefingOpts): string;
19
+ //# sourceMappingURL=format-lead.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-lead.d.ts","sourceRoot":"","sources":["../../src/briefings/format-lead.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;IACrB;;;;OAIG;IACH,eAAe,EAAE,IAAI,EAAE,CAAC;IACxB,OAAO,EAAE,IAAI,EAAE,CAAC;IAChB,mBAAmB,EAAE,IAAI,EAAE,CAAC;IAC5B,UAAU,EAAE,IAAI,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAwChG"}
@@ -0,0 +1,47 @@
1
+ const DEFAULT_MAX = 10;
2
+ export function formatLeadBriefing(body, opts) {
3
+ const maxItems = opts?.maxItems ?? DEFAULT_MAX;
4
+ const { assign_owner, clarify, repair_dependencies, lead_owned } = body;
5
+ // assign_reviewer is intentionally excluded from emptiness check & rendering:
6
+ // v1 has no reviewer concept, so the bucket is always empty in practice.
7
+ // Skipping it (rather than rendering an empty bucket) keeps the briefing tight.
8
+ const isEmpty = assign_owner.length === 0 &&
9
+ clarify.length === 0 &&
10
+ repair_dependencies.length === 0 &&
11
+ lead_owned.length === 0;
12
+ if (isEmpty) {
13
+ return "### Queen 简报: 当前无待处理事项";
14
+ }
15
+ const lines = [];
16
+ lines.push("### Queen 简报");
17
+ lines.push("");
18
+ if (assign_owner.length > 0) {
19
+ renderBucket(lines, "待指派 owner", assign_owner, maxItems);
20
+ }
21
+ if (clarify.length > 0) {
22
+ renderBucket(lines, "待澄清", clarify, maxItems);
23
+ }
24
+ if (repair_dependencies.length > 0) {
25
+ renderBucket(lines, "待修复依赖", repair_dependencies, maxItems);
26
+ }
27
+ if (lead_owned.length > 0) {
28
+ renderBucket(lines, "Queen 自持", lead_owned, maxItems);
29
+ }
30
+ // Trailing blank line from last renderBucket — trim it.
31
+ while (lines.length > 0 && lines[lines.length - 1] === "") {
32
+ lines.pop();
33
+ }
34
+ return lines.join("\n");
35
+ }
36
+ function renderBucket(out, title, items, maxItems) {
37
+ out.push(`**${title} (${items.length})**`);
38
+ const shown = items.slice(0, maxItems);
39
+ for (const t of shown) {
40
+ out.push(`- ${t.id} ${t.subject}`);
41
+ }
42
+ if (items.length > maxItems) {
43
+ out.push(`- (还有 ${items.length - maxItems} 项被截断)`);
44
+ }
45
+ out.push("");
46
+ }
47
+ //# sourceMappingURL=format-lead.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-lead.js","sourceRoot":"","sources":["../../src/briefings/format-lead.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB,MAAM,UAAU,kBAAkB,CAAC,IAAsB,EAAE,IAA6B;IACtF,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,WAAW,CAAC;IAC/C,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAExE,8EAA8E;IAC9E,yEAAyE;IACzE,gFAAgF;IAChF,MAAM,OAAO,GACX,YAAY,CAAC,MAAM,KAAK,CAAC;QACzB,OAAO,CAAC,MAAM,KAAK,CAAC;QACpB,mBAAmB,CAAC,MAAM,KAAK,CAAC;QAChC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC;IAE1B,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,wBAAwB,CAAC;IAClC,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC;IAED,wDAAwD;IACxD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QAC1D,KAAK,CAAC,GAAG,EAAE,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,GAAa,EAAE,KAAa,EAAE,KAAa,EAAE,QAAgB;IACjF,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC5B,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,GAAG,QAAQ,QAAQ,CAAC,CAAC;IACrD,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,18 @@
1
+ export interface MemberBriefingBody {
2
+ rules: string[];
3
+ bootstrap: {
4
+ swarmId: string;
5
+ instanceId: string;
6
+ /** "queen" | "worker" today; left as string for forward-compat. */
7
+ roleType: string;
8
+ };
9
+ }
10
+ /**
11
+ * Render a member briefing as markdown. Pure, no I/O.
12
+ *
13
+ * Note: bootstrap.swarmId is intentionally NOT rendered — instanceId + roleType
14
+ * in the header is sufficient context for a per-role prompt; swarmId would just
15
+ * be noise.
16
+ */
17
+ export declare function formatMemberBriefing(body: MemberBriefingBody): string;
18
+ //# sourceMappingURL=format-member.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-member.d.ts","sourceRoot":"","sources":["../../src/briefings/format-member.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,mEAAmE;QACnE,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAcrE"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Render a member briefing as markdown. Pure, no I/O.
3
+ *
4
+ * Note: bootstrap.swarmId is intentionally NOT rendered — instanceId + roleType
5
+ * in the header is sufficient context for a per-role prompt; swarmId would just
6
+ * be noise.
7
+ */
8
+ export function formatMemberBriefing(body) {
9
+ const { rules, bootstrap } = body;
10
+ const lines = [];
11
+ lines.push(`### 成员引导 (${bootstrap.instanceId} · ${bootstrap.roleType})`);
12
+ lines.push("");
13
+ lines.push("**启动规则**");
14
+ if (rules.length === 0) {
15
+ lines.push("_(无)_");
16
+ }
17
+ else {
18
+ rules.forEach((rule, idx) => {
19
+ lines.push(`${idx + 1}. ${rule}`);
20
+ });
21
+ }
22
+ return lines.join("\n");
23
+ }
24
+ //# sourceMappingURL=format-member.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-member.js","sourceRoot":"","sources":["../../src/briefings/format-member.ts"],"names":[],"mappings":"AAUA;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAwB;IAC3D,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAClC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,aAAa,SAAS,CAAC,UAAU,MAAM,SAAS,CAAC,QAAQ,GAAG,CAAC,CAAC;IACzE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;YAC1B,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { Task } from "../schema.js";
2
+ export interface TaskBriefingBody {
3
+ actionable: Task[];
4
+ awareness: Task[];
5
+ counters: {
6
+ actionable: number;
7
+ awareness: number;
8
+ blocked: number;
9
+ waitingOnUser: number;
10
+ };
11
+ warnings: string[];
12
+ }
13
+ export interface FormatTaskBriefingOpts {
14
+ instanceId?: string;
15
+ /** Max items per bucket. Default 10. */
16
+ maxItems?: number;
17
+ }
18
+ export declare function formatTaskBriefing(body: TaskBriefingBody, opts?: FormatTaskBriefingOpts): string;
19
+ //# sourceMappingURL=format-task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-task.d.ts","sourceRoot":"","sources":["../../src/briefings/format-task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,IAAI,EAAE,CAAC;IACnB,SAAS,EAAE,IAAI,EAAE,CAAC;IAClB,QAAQ,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5F,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,sBAAsB,GAAG,MAAM,CA6ChG"}
@@ -0,0 +1,48 @@
1
+ const DEFAULT_MAX = 10;
2
+ export function formatTaskBriefing(body, opts) {
3
+ const maxItems = opts?.maxItems ?? DEFAULT_MAX;
4
+ const { actionable, awareness, counters, warnings } = body;
5
+ const isEmpty = actionable.length === 0 &&
6
+ awareness.length === 0 &&
7
+ counters.actionable === 0 &&
8
+ counters.awareness === 0 &&
9
+ counters.blocked === 0 &&
10
+ counters.waitingOnUser === 0 &&
11
+ warnings.length === 0;
12
+ if (isEmpty) {
13
+ return "### 你的任务简报: 暂无任务";
14
+ }
15
+ const lines = [];
16
+ const headerSuffix = opts?.instanceId ? ` (${opts.instanceId})` : "";
17
+ lines.push(`### 你的任务简报${headerSuffix}`);
18
+ lines.push("");
19
+ if (actionable.length > 0) {
20
+ renderBucket(lines, "可执行", actionable, maxItems, (t) => `- ${t.id} [${t.status}] ${t.subject}`);
21
+ }
22
+ if (awareness.length > 0) {
23
+ // NOTE: kept pure (no store). A richer "waiting on {ids}" rendering can be
24
+ // added later once a store handle is plumbed through.
25
+ renderBucket(lines, "需关注", awareness, maxItems, (t) => `- ${t.id} ${t.subject}`);
26
+ }
27
+ lines.push(`**计数**: actionable=${counters.actionable} awareness=${counters.awareness} blocked=${counters.blocked} waitingOnUser=${counters.waitingOnUser}`);
28
+ if (warnings.length > 0) {
29
+ lines.push("");
30
+ lines.push("**警告**:");
31
+ for (const w of warnings) {
32
+ lines.push(`- ${w}`);
33
+ }
34
+ }
35
+ return lines.join("\n");
36
+ }
37
+ function renderBucket(out, title, items, maxItems, render) {
38
+ out.push(`**${title} (${items.length})**`);
39
+ const shown = items.slice(0, maxItems);
40
+ for (const t of shown) {
41
+ out.push(render(t));
42
+ }
43
+ if (items.length > maxItems) {
44
+ out.push(`- (还有 ${items.length - maxItems} 项被截断)`);
45
+ }
46
+ out.push("");
47
+ }
48
+ //# sourceMappingURL=format-task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-task.js","sourceRoot":"","sources":["../../src/briefings/format-task.ts"],"names":[],"mappings":"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"}
package/dist/dag.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { Task } from "./schema.js";
2
+ import { TaskStore } from "./store.js";
3
+ export interface BlockerClassification {
4
+ broken: string[];
5
+ waiting: string[];
6
+ isBlocked: boolean;
7
+ }
8
+ export declare function classifyBlockers(task: Task, store: TaskStore): BlockerClassification;
9
+ export declare function wouldCreateCycle(store: TaskStore, fromId: string, toId: string): boolean;
10
+ //# sourceMappingURL=dag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag.d.ts","sourceRoot":"","sources":["../src/dag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,GAAG,qBAAqB,CAYpF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAaxF"}
package/dist/dag.js ADDED
@@ -0,0 +1,33 @@
1
+ export function classifyBlockers(task, store) {
2
+ const broken = [];
3
+ const waiting = [];
4
+ for (const depId of task.blockedBy) {
5
+ const dep = store.tryGet(depId);
6
+ if (!dep || dep.status === "cancelled") {
7
+ broken.push(depId);
8
+ }
9
+ else if (dep.status !== "completed") {
10
+ waiting.push(depId);
11
+ }
12
+ }
13
+ return { broken, waiting, isBlocked: broken.length + waiting.length > 0 };
14
+ }
15
+ export function wouldCreateCycle(store, fromId, toId) {
16
+ if (fromId === toId)
17
+ return true;
18
+ const visited = new Set();
19
+ const stack = [toId];
20
+ while (stack.length) {
21
+ const cur = stack.pop();
22
+ if (cur === fromId)
23
+ return true;
24
+ if (visited.has(cur))
25
+ continue;
26
+ visited.add(cur);
27
+ const t = store.tryGet(cur);
28
+ if (t)
29
+ stack.push(...t.blocks);
30
+ }
31
+ return false;
32
+ }
33
+ //# sourceMappingURL=dag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag.js","sourceRoot":"","sources":["../src/dag.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,gBAAgB,CAAC,IAAU,EAAE,KAAgB;IAC3D,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;aAAM,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAgB,EAAE,MAAc,EAAE,IAAY;IAC7E,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAa,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QACzB,IAAI,GAAG,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QAChC,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC/B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,17 @@
1
+ export * from "./schema.js";
2
+ export * from "./path.js";
3
+ export * from "./meta.js";
4
+ export * from "./locking.js";
5
+ export * from "./store.js";
6
+ export * from "./dag.js";
7
+ export { formatTaskBriefing } from "./briefings/format-task.js";
8
+ export type { TaskBriefingBody, FormatTaskBriefingOpts } from "./briefings/format-task.js";
9
+ export { formatLeadBriefing } from "./briefings/format-lead.js";
10
+ export type { LeadBriefingBody, FormatLeadBriefingOpts } from "./briefings/format-lead.js";
11
+ export { formatMemberBriefing } from "./briefings/format-member.js";
12
+ export type { MemberBriefingBody } from "./briefings/format-member.js";
13
+ export { computeTaskBriefing } from "./briefings/compute-task.js";
14
+ export { computeLeadBriefing } from "./briefings/compute-lead.js";
15
+ export { computeMemberBriefing } from "./briefings/compute-member.js";
16
+ export type { ComputeMemberBriefingArgs } from "./briefings/compute-member.js";
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,YAAY,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,YAAY,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAC3F,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,YAAY,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ export * from "./schema.js";
2
+ export * from "./path.js";
3
+ export * from "./meta.js";
4
+ export * from "./locking.js";
5
+ export * from "./store.js";
6
+ export * from "./dag.js";
7
+ export { formatTaskBriefing } from "./briefings/format-task.js";
8
+ export { formatLeadBriefing } from "./briefings/format-lead.js";
9
+ export { formatMemberBriefing } from "./briefings/format-member.js";
10
+ export { computeTaskBriefing } from "./briefings/compute-task.js";
11
+ export { computeLeadBriefing } from "./briefings/compute-lead.js";
12
+ export { computeMemberBriefing } from "./briefings/compute-member.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface WithLockOptions {
2
+ retries?: number;
3
+ minTimeout?: number;
4
+ maxTimeout?: number;
5
+ staleMs?: number;
6
+ }
7
+ export declare function withLock<T>(filePath: string, fn: () => Promise<T>, opts?: WithLockOptions): Promise<T>;
8
+ //# sourceMappingURL=locking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locking.d.ts","sourceRoot":"","sources":["../src/locking.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,CAAC,CAAC,CAeZ"}
@@ -0,0 +1,19 @@
1
+ import lockfile from "proper-lockfile";
2
+ export async function withLock(filePath, fn, opts = {}) {
3
+ const release = await lockfile.lock(filePath, {
4
+ retries: {
5
+ retries: opts.retries ?? 20,
6
+ minTimeout: opts.minTimeout ?? 20,
7
+ maxTimeout: opts.maxTimeout ?? 200,
8
+ },
9
+ stale: opts.staleMs ?? 10_000,
10
+ realpath: false,
11
+ });
12
+ try {
13
+ return await fn();
14
+ }
15
+ finally {
16
+ await release();
17
+ }
18
+ }
19
+ //# sourceMappingURL=locking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locking.js","sourceRoot":"","sources":["../src/locking.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AASvC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,QAAgB,EAChB,EAAoB,EACpB,OAAwB,EAAE;IAE1B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE;QAC5C,OAAO,EAAE;YACP,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;YAC3B,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE;YACjC,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,GAAG;SACnC;QACD,KAAK,EAAE,IAAI,CAAC,OAAO,IAAI,MAAM;QAC7B,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC;IACH,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,EAAE,CAAC;IAClB,CAAC;AACH,CAAC"}
package/dist/meta.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ export interface ProjectMeta {
2
+ version: 1;
3
+ workDir: string;
4
+ createdAt: string;
5
+ [extra: string]: unknown;
6
+ }
7
+ /**
8
+ * Ensure `<projectRoot>/meta.json` exists for the given workDir.
9
+ *
10
+ * - Idempotent: if the file already exists and parses as JSON, it is left
11
+ * untouched (preserves `createdAt` and any unrelated fields written by
12
+ * other tools).
13
+ * - On a fresh project, writes `{version: 1, workDir, createdAt: <ISO now>}`.
14
+ * - On a parse failure, the corrupt file is overwritten with a fresh meta —
15
+ * we prefer "project visible to hub" over preserving unreadable garbage.
16
+ *
17
+ * Safe to call from constructors / hot paths: a single `existsSync` short-circuit
18
+ * avoids any disk write on the steady-state path.
19
+ */
20
+ export declare function ensureProjectMeta(workDir: string, home?: string): void;
21
+ //# sourceMappingURL=meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAmBtE"}
package/dist/meta.js ADDED
@@ -0,0 +1,37 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
2
+ import { projectRoot, metaFile } from "./path.js";
3
+ /**
4
+ * Ensure `<projectRoot>/meta.json` exists for the given workDir.
5
+ *
6
+ * - Idempotent: if the file already exists and parses as JSON, it is left
7
+ * untouched (preserves `createdAt` and any unrelated fields written by
8
+ * other tools).
9
+ * - On a fresh project, writes `{version: 1, workDir, createdAt: <ISO now>}`.
10
+ * - On a parse failure, the corrupt file is overwritten with a fresh meta —
11
+ * we prefer "project visible to hub" over preserving unreadable garbage.
12
+ *
13
+ * Safe to call from constructors / hot paths: a single `existsSync` short-circuit
14
+ * avoids any disk write on the steady-state path.
15
+ */
16
+ export function ensureProjectMeta(workDir, home) {
17
+ const path = metaFile(workDir, home);
18
+ if (existsSync(path)) {
19
+ try {
20
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
21
+ if (parsed && typeof parsed === "object" && typeof parsed.createdAt === "string") {
22
+ return;
23
+ }
24
+ }
25
+ catch {
26
+ // fall through and overwrite
27
+ }
28
+ }
29
+ mkdirSync(projectRoot(workDir, home), { recursive: true });
30
+ const meta = {
31
+ version: 1,
32
+ workDir,
33
+ createdAt: new Date().toISOString(),
34
+ };
35
+ writeFileSync(path, JSON.stringify(meta, null, 2));
36
+ }
37
+ //# sourceMappingURL=meta.js.map