@brainervirus/workit-core 0.11.0 → 1.0.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 (150) hide show
  1. package/README.md +5 -3
  2. package/package.json +8 -3
  3. package/scripts/analyze-release-scope.ts +4 -1
  4. package/scripts/doctor-check.ts +3 -1
  5. package/scripts/install-codex-plugin.sh +28 -0
  6. package/scripts/install-cursor-plugin.sh +1 -0
  7. package/scripts/install-opencode-plugin.sh +1 -0
  8. package/scripts/install-pi-package.sh +56 -0
  9. package/scripts/rewrite-workspace-deps.ts +22 -5
  10. package/scripts/sync-release-manifests.ts +8 -5
  11. package/scripts/sync-runtime.sh +7 -3
  12. package/scripts/validate-cursor-marketplace.ts +16 -62
  13. package/skills/workit-babysit/SKILL.md +33 -0
  14. package/skills/workit-behavioral-tdd/SKILL.md +53 -0
  15. package/skills/workit-blast-radius/SKILL.md +31 -0
  16. package/skills/workit-challenge/SKILL.md +62 -0
  17. package/skills/workit-debug/SKILL.md +61 -0
  18. package/skills/workit-deslop/SKILL.md +36 -0
  19. package/skills/workit-diagram/SKILL.md +32 -0
  20. package/skills/workit-green-run/SKILL.md +29 -0
  21. package/skills/workit-handoff/SKILL.md +43 -0
  22. package/skills/workit-implement/SKILL.md +46 -0
  23. package/skills/workit-mockup/SKILL.md +28 -0
  24. package/skills/workit-plan/SKILL.md +66 -0
  25. package/skills/workit-review/SKILL.md +60 -0
  26. package/skills/workit-steer/SKILL.md +32 -0
  27. package/src/core/authority.ts +918 -0
  28. package/src/core/boundary.ts +29 -0
  29. package/src/core/branch.ts +26 -255
  30. package/src/core/changelog.ts +95 -18
  31. package/src/core/commit-flavors.ts +65 -0
  32. package/src/core/config-conversion.ts +183 -0
  33. package/src/core/config.ts +42 -0
  34. package/src/core/cutover.ts +721 -0
  35. package/src/core/detect-hosts.ts +107 -0
  36. package/src/core/doctor.ts +428 -18
  37. package/src/core/external-action-effects.ts +1171 -0
  38. package/src/core/external-action.ts +541 -0
  39. package/src/core/init.ts +83 -32
  40. package/src/core/methods.ts +125 -0
  41. package/src/core/policy-resolver.ts +523 -0
  42. package/src/core/pr-create.ts +7 -1
  43. package/src/core/registration.ts +69 -4
  44. package/src/core/repo-context.ts +59 -1
  45. package/src/core/setup.ts +28 -0
  46. package/src/core/skill-manifests.ts +40 -42
  47. package/src/core/support-matrix.ts +8 -3
  48. package/src/core/sync-runtime.ts +15 -3
  49. package/src/core/task-context.ts +179 -0
  50. package/src/core/task-contract.ts +1136 -0
  51. package/src/core/task-engine.ts +2562 -0
  52. package/src/core/task-evaluation.ts +679 -0
  53. package/src/core/task-store.ts +1071 -0
  54. package/src/core/tracker-issues.ts +237 -0
  55. package/src/core/uninstall.ts +67 -3
  56. package/src/core/vcs-config.ts +53 -22
  57. package/src/core/workers.ts +166 -0
  58. package/src/core/workspaces.ts +3 -1
  59. package/src/core/youtrack-tools.ts +2 -0
  60. package/src/core/youtrack.ts +145 -10
  61. package/src/core.ts +126 -0
  62. package/templates/execution-contract.md +17 -50
  63. package/templates/plan-template.md +3 -3
  64. package/templates/spec-template.md +15 -3
  65. package/templates/workit-contract.md +12 -0
  66. package/commands/wk-changelog.md +0 -2
  67. package/commands/wk-commit.md +0 -2
  68. package/commands/wk-docs-refresh.md +0 -2
  69. package/commands/wk-handoff.md +0 -2
  70. package/commands/wk-implement.md +0 -2
  71. package/commands/wk-init.md +0 -2
  72. package/commands/wk-issue-update.md +0 -2
  73. package/commands/wk-meetings.md +0 -2
  74. package/commands/wk-pr.md +0 -2
  75. package/commands/wk-release-notes.md +0 -2
  76. package/commands/wk-status.md +0 -2
  77. package/commands/wk-verify.md +0 -2
  78. package/scripts/update-superpowers.sh +0 -82
  79. package/scripts/vendor-assets.ts +0 -37
  80. package/skills/wk-changelog/SKILL.md +0 -15
  81. package/skills/wk-commit/SKILL.md +0 -16
  82. package/skills/wk-docs-refresh/SKILL.md +0 -15
  83. package/skills/wk-handoff/SKILL.md +0 -20
  84. package/skills/wk-implement/SKILL.md +0 -47
  85. package/skills/wk-init/SKILL.md +0 -31
  86. package/skills/wk-issue-update/SKILL.md +0 -27
  87. package/skills/wk-issue-update/references/youtrack-update-style.md +0 -81
  88. package/skills/wk-meetings/SKILL.md +0 -17
  89. package/skills/wk-pr/SKILL.md +0 -27
  90. package/skills/wk-release-notes/SKILL.md +0 -15
  91. package/skills/wk-status/SKILL.md +0 -16
  92. package/skills/wk-verify/SKILL.md +0 -16
  93. package/src/core/detector.ts +0 -239
  94. package/src/core/flow-state.ts +0 -3308
  95. package/src/core/handoff-context.ts +0 -136
  96. package/src/core/handoff-tools.ts +0 -133
  97. package/src/core/menu.ts +0 -70
  98. package/src/core/plan-tasks.ts +0 -43
  99. package/src/core/reminder.ts +0 -124
  100. package/src/core/sdd.ts +0 -353
  101. package/src/state.ts +0 -22
  102. package/templates/superpowers-doc-contract.md +0 -75
  103. package/vendor/superpowers/skills/brainstorming/SKILL.md +0 -159
  104. package/vendor/superpowers/skills/brainstorming/scripts/frame-template.html +0 -213
  105. package/vendor/superpowers/skills/brainstorming/scripts/helper.js +0 -167
  106. package/vendor/superpowers/skills/brainstorming/scripts/server.cjs +0 -723
  107. package/vendor/superpowers/skills/brainstorming/scripts/start-server.sh +0 -209
  108. package/vendor/superpowers/skills/brainstorming/scripts/stop-server.sh +0 -120
  109. package/vendor/superpowers/skills/brainstorming/spec-document-reviewer-prompt.md +0 -49
  110. package/vendor/superpowers/skills/brainstorming/visual-companion.md +0 -291
  111. package/vendor/superpowers/skills/dispatching-parallel-agents/SKILL.md +0 -185
  112. package/vendor/superpowers/skills/executing-plans/SKILL.md +0 -70
  113. package/vendor/superpowers/skills/finishing-a-development-branch/SKILL.md +0 -241
  114. package/vendor/superpowers/skills/receiving-code-review/SKILL.md +0 -213
  115. package/vendor/superpowers/skills/requesting-code-review/SKILL.md +0 -103
  116. package/vendor/superpowers/skills/requesting-code-review/code-reviewer.md +0 -172
  117. package/vendor/superpowers/skills/subagent-driven-development/SKILL.md +0 -428
  118. package/vendor/superpowers/skills/subagent-driven-development/implementer-prompt.md +0 -139
  119. package/vendor/superpowers/skills/subagent-driven-development/scripts/review-package +0 -44
  120. package/vendor/superpowers/skills/subagent-driven-development/scripts/sdd-workspace +0 -22
  121. package/vendor/superpowers/skills/subagent-driven-development/scripts/task-brief +0 -40
  122. package/vendor/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md +0 -188
  123. package/vendor/superpowers/skills/systematic-debugging/CREATION-LOG.md +0 -119
  124. package/vendor/superpowers/skills/systematic-debugging/SKILL.md +0 -296
  125. package/vendor/superpowers/skills/systematic-debugging/condition-based-waiting-example.ts +0 -158
  126. package/vendor/superpowers/skills/systematic-debugging/condition-based-waiting.md +0 -115
  127. package/vendor/superpowers/skills/systematic-debugging/defense-in-depth.md +0 -122
  128. package/vendor/superpowers/skills/systematic-debugging/find-polluter.sh +0 -63
  129. package/vendor/superpowers/skills/systematic-debugging/root-cause-tracing.md +0 -169
  130. package/vendor/superpowers/skills/systematic-debugging/test-academic.md +0 -14
  131. package/vendor/superpowers/skills/systematic-debugging/test-pressure-1.md +0 -58
  132. package/vendor/superpowers/skills/systematic-debugging/test-pressure-2.md +0 -68
  133. package/vendor/superpowers/skills/systematic-debugging/test-pressure-3.md +0 -69
  134. package/vendor/superpowers/skills/test-driven-development/SKILL.md +0 -371
  135. package/vendor/superpowers/skills/test-driven-development/testing-anti-patterns.md +0 -299
  136. package/vendor/superpowers/skills/using-git-worktrees/SKILL.md +0 -202
  137. package/vendor/superpowers/skills/using-superpowers/SKILL.md +0 -62
  138. package/vendor/superpowers/skills/using-superpowers/references/antigravity-tools.md +0 -23
  139. package/vendor/superpowers/skills/using-superpowers/references/codex-tools.md +0 -39
  140. package/vendor/superpowers/skills/using-superpowers/references/pi-tools.md +0 -16
  141. package/vendor/superpowers/skills/verification-before-completion/SKILL.md +0 -139
  142. package/vendor/superpowers/skills/writing-plans/SKILL.md +0 -174
  143. package/vendor/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +0 -49
  144. package/vendor/superpowers/skills/writing-skills/SKILL.md +0 -689
  145. package/vendor/superpowers/skills/writing-skills/anthropic-best-practices.md +0 -1150
  146. package/vendor/superpowers/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +0 -189
  147. package/vendor/superpowers/skills/writing-skills/graphviz-conventions.dot +0 -172
  148. package/vendor/superpowers/skills/writing-skills/persuasion-principles.md +0 -187
  149. package/vendor/superpowers/skills/writing-skills/render-graphs.js +0 -168
  150. package/vendor/superpowers/skills/writing-skills/testing-skills-with-subagents.md +0 -384
@@ -2,7 +2,8 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { readTemplate } from "./templates";
4
4
  import { resolveWorkspaceRoot } from "./scripts";
5
- import { configDir, isConfigObject } from "./config";
5
+ import { configDir, isConfigObject, resolveConfigDir } from "./config";
6
+ import { resolveInside } from "../core";
6
7
 
7
8
  const ISSUE_RE = /^[A-Z]+-\d+$/;
8
9
  const TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
@@ -12,6 +13,11 @@ const TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
12
13
  export const youTrackConfigPath = (): string =>
13
14
  process.env.WORKFLOW_YOUTRACK_CONFIG ?? path.join(configDir(), "youtrack.json");
14
15
 
16
+ /** Config path for read-only context. Unlike youTrackConfigPath(), this never
17
+ * calls configDir() and therefore cannot trigger legacy-config migration. */
18
+ export const youTrackReadOnlyConfigPath = (): string =>
19
+ process.env.WORKFLOW_YOUTRACK_CONFIG ?? path.join(resolveConfigDir(), "youtrack.json");
20
+
15
21
  const youTrackTokenModeOk = (p: string): boolean => {
16
22
  if (process.platform === "win32") return true;
17
23
  const mode = fs.statSync(p).mode & 0o777;
@@ -42,6 +48,19 @@ function readYouTrackConfig(
42
48
  return { config: parsed as Record<string, any>, path: cfgPath };
43
49
  }
44
50
 
51
+ const readYouTrackContextConfig = (): { data: Record<string, any> } | { error: string } => {
52
+ const cfgPath = youTrackReadOnlyConfigPath();
53
+ if (!fs.existsSync(cfgPath)) return { data: {} };
54
+ let parsed: unknown;
55
+ try {
56
+ parsed = JSON.parse(fs.readFileSync(cfgPath, "utf8"));
57
+ } catch {
58
+ return { error: "YouTrack configuration is unavailable" };
59
+ }
60
+ if (!isConfigObject(parsed)) return { error: "YouTrack configuration is unavailable" };
61
+ return { data: readOnlyYouTrackConfig(parsed as Record<string, any>) };
62
+ };
63
+
45
64
  // RL-01: typed load result — malformed carries {ok:false, error, configPath}
46
65
  // mirroring vcsConfig, so risky consumers stop on the exact path.
47
66
  export type YouTrackConfigResult =
@@ -211,7 +230,7 @@ export function youTrackWorkDateMs(
211
230
  }
212
231
  }
213
232
 
214
- const youTrackToken = (): { token: string; base: string } | { error: string } => {
233
+ export const youTrackToken = (): { token: string; base: string } | { error: string } => {
215
234
  const loaded = readYouTrackConfig(true);
216
235
  if ("error" in loaded) return loaded;
217
236
  const tokenFile = String(loaded.config.tokenFile ?? "");
@@ -237,7 +256,7 @@ const youTrackToken = (): { token: string; base: string } | { error: string } =>
237
256
 
238
257
  // fetch replaces the previous curl -fsS request helper: check res.ok,
239
258
  // surface HTTP errors without a token-bearing body, parse JSON on success.
240
- async function youTrackRequest(
259
+ export async function youTrackRequest(
241
260
  url: string,
242
261
  init: { method: string; token: string; body?: unknown },
243
262
  ): Promise<{ status: number; stdout: string; stderr: string }> {
@@ -462,6 +481,13 @@ const defaultScripts: YouTrackScripts = {
462
481
  api: (args) => youTrackApi(args, process.env.WORKFLOW_YT_WRITE ?? ""),
463
482
  };
464
483
 
484
+ const contextScripts: YouTrackScripts = {
485
+ config: readYouTrackContextConfig,
486
+ greeting: () => youTrackGreeting(youTrackReadOnlyConfigPath()),
487
+ parseDuration: (text) => youTrackParseDuration(text),
488
+ api: () => ({ error: "YouTrack context is read-only" }),
489
+ };
490
+
465
491
  export function verifyYouTrackToken(
466
492
  scripts: YouTrackScripts = defaultScripts,
467
493
  ): Record<string, any> {
@@ -475,7 +501,12 @@ function resolveYouTrackFromPaths(
475
501
  ): string | null {
476
502
  const root = resolveWorkspaceRoot(workspace_root);
477
503
  for (const rel of [spec_path, plan_path].filter(Boolean) as string[]) {
478
- const full = path.isAbsolute(rel) ? rel : path.join(root, rel);
504
+ let full: string;
505
+ try {
506
+ full = resolveInside(root, rel);
507
+ } catch {
508
+ continue;
509
+ }
479
510
  if (!fs.existsSync(full)) continue;
480
511
  const text = fs.readFileSync(full, "utf8");
481
512
  const m = text.match(/^\*\*YouTrack:\*\*\s*`?([A-Z]+-\d+)`?/m);
@@ -507,6 +538,50 @@ function meetingOptionsFromConfig(cfg: any): Record<string, any>[] {
507
538
  ];
508
539
  }
509
540
 
541
+ const readOnlyYouTrackConfig = (cfg: Record<string, any>): Record<string, any> => {
542
+ const publicUrl = (value: unknown): string | undefined => {
543
+ if (typeof value !== "string") return undefined;
544
+ try {
545
+ const url = new URL(value);
546
+ if (url.username || url.password)
547
+ return `${url.protocol}//${url.host}${url.pathname}${url.search}${url.hash}`;
548
+ return value;
549
+ } catch {
550
+ return undefined;
551
+ }
552
+ };
553
+ const safe: Record<string, any> = {};
554
+ const baseUrl = publicUrl(cfg.baseUrl);
555
+ if (baseUrl) safe.baseUrl = baseUrl;
556
+ for (const key of ["timezone", "greetingCutoff", "defaultMention", "meetingIssue"])
557
+ if (typeof cfg[key] === "string") safe[key] = cfg[key];
558
+ if (cfg.greetings && typeof cfg.greetings === "object" && !Array.isArray(cfg.greetings)) {
559
+ const greetings: Record<string, string> = {};
560
+ for (const key of ["morning", "afternoon"])
561
+ if (typeof cfg.greetings[key] === "string") greetings[key] = cfg.greetings[key];
562
+ if (Object.keys(greetings).length) safe.greetings = greetings;
563
+ }
564
+ if (
565
+ cfg.meetingIssues &&
566
+ typeof cfg.meetingIssues === "object" &&
567
+ !Array.isArray(cfg.meetingIssues)
568
+ ) {
569
+ safe.meetingIssues = Object.fromEntries(
570
+ Object.entries(cfg.meetingIssues).flatMap(([key, value]) => {
571
+ if (!value || typeof value !== "object" || Array.isArray(value)) return [];
572
+ const item = value as Record<string, any>;
573
+ const safeItem: Record<string, string> = {};
574
+ for (const field of ["issue", "label", "workItemText"])
575
+ if (typeof item[field] === "string") safeItem[field] = item[field];
576
+ const url = publicUrl(item.url);
577
+ if (url) safeItem.url = url;
578
+ return [[key, safeItem]] as const;
579
+ }),
580
+ );
581
+ }
582
+ return safe;
583
+ };
584
+
510
585
  export function context(
511
586
  {
512
587
  spec_path,
@@ -525,7 +600,7 @@ export function context(
525
600
  mode?: string;
526
601
  workspace_root: string;
527
602
  },
528
- scripts: YouTrackScripts = defaultScripts,
603
+ scripts: YouTrackScripts = contextScripts,
529
604
  ): Record<string, any> {
530
605
  const cfg = scripts.config();
531
606
  if (cfg.error) return { error: cfg.error };
@@ -535,11 +610,12 @@ export function context(
535
610
  return { error: (greeting.stderr || greeting.stdout || "greeting failed").trim() };
536
611
  }
537
612
 
538
- const meetingOptions = meetingOptionsFromConfig(cfg.data);
613
+ const safeConfig = readOnlyYouTrackConfig(cfg.data);
614
+ const meetingOptions = meetingOptionsFromConfig(safeConfig);
539
615
 
540
616
  if (mode === "meetings" && !issue_id && !issue_url && !issue_ref) {
541
617
  return {
542
- config: cfg.data,
618
+ config: safeConfig,
543
619
  greeting: greeting.stdout.trim(),
544
620
  mode: "meetings",
545
621
  requiresMeetingChoice: true,
@@ -554,7 +630,7 @@ export function context(
554
630
  if ("error" in parsed) return { error: parsed.error };
555
631
  issue = parsed.issueId;
556
632
  }
557
- if (!issue && mode === "meetings") issue = meetingOptions[0]?.issue ?? cfg.data.meetingIssue;
633
+ if (!issue && mode === "meetings") issue = meetingOptions[0]?.issue ?? safeConfig.meetingIssue;
558
634
  if (!issue) issue = resolveYouTrackFromPaths(spec_path, plan_path, workspace_root) ?? undefined;
559
635
  if (!issue || !ISSUE_RE.test(issue)) {
560
636
  return {
@@ -564,13 +640,13 @@ export function context(
564
640
  };
565
641
  }
566
642
 
567
- const base = (cfg.data.baseUrl || "").replace(/\/$/, "");
643
+ const base = (safeConfig.baseUrl || "").replace(/\/$/, "");
568
644
  const issueUrl = base ? `${base}/issue/${issue}` : null;
569
645
 
570
646
  const selectedMeeting = meetingOptions.find((m) => m.issue === issue);
571
647
 
572
648
  return {
573
- config: cfg.data,
649
+ config: safeConfig,
574
650
  greeting: greeting.stdout.trim(),
575
651
  issueId: issue,
576
652
  issueUrl,
@@ -580,6 +656,65 @@ export function context(
580
656
  };
581
657
  }
582
658
 
659
+ /** Fetch a YouTrack issue body for context.read (titles alone mislead).
660
+ * Creds failure degrades (offline keeps the link shape); request failure
661
+ * with creds fails closed so sessions never mistake titles for bodies. */
662
+ export const fetchYouTrackIssueBody = async (
663
+ issue: string,
664
+ creds: () => { token: string; base: string } | { error: string } = youTrackToken,
665
+ request: typeof youTrackRequest = youTrackRequest,
666
+ ): Promise<
667
+ | {
668
+ data: {
669
+ idReadable: string;
670
+ summary: string;
671
+ description: string | null;
672
+ state: string | null;
673
+ };
674
+ }
675
+ | { error: string; kind: "creds" | "request" }
676
+ > => {
677
+ const credentials = creds();
678
+ if ("error" in credentials) return { error: credentials.error, kind: "creds" };
679
+ const { token, base } = credentials;
680
+ const out = await request(
681
+ `${base}/api/issues/${encodeURIComponent(issue)}?fields=idReadable,summary,description,customFields(name,value(name))`,
682
+ { method: "GET", token },
683
+ );
684
+ if (out.status !== 0)
685
+ return { error: out.stderr || "YouTrack issue fetch failed", kind: "request" };
686
+ try {
687
+ const parsed = JSON.parse(out.stdout) as Record<string, unknown>;
688
+ const customFields = Array.isArray(parsed.customFields) ? parsed.customFields : [];
689
+ const stateField = customFields.find(
690
+ (field): field is { name: unknown; value: unknown } =>
691
+ typeof field === "object" &&
692
+ field !== null &&
693
+ (field as { name: unknown }).name === "State",
694
+ );
695
+ const stateValue = stateField?.value;
696
+ const stateName =
697
+ typeof stateValue === "object" && stateValue !== null
698
+ ? (stateValue as { name?: unknown }).name
699
+ : undefined;
700
+ return {
701
+ data: {
702
+ idReadable: String(parsed.idReadable ?? issue),
703
+ summary: String(parsed.summary ?? ""),
704
+ description: typeof parsed.description === "string" ? parsed.description : null,
705
+ state:
706
+ typeof stateValue === "string"
707
+ ? stateValue
708
+ : typeof stateName === "string" && stateName
709
+ ? stateName
710
+ : null,
711
+ },
712
+ };
713
+ } catch {
714
+ return { error: "invalid JSON from YouTrack API", kind: "request" };
715
+ }
716
+ };
717
+
583
718
  export function parseDuration(
584
719
  text: string,
585
720
  _workspace_root: string,
package/src/core.ts CHANGED
@@ -2,6 +2,132 @@ import { spawnSync } from "node:child_process";
2
2
  import { existsSync, realpathSync } from "node:fs";
3
3
  import path from "node:path";
4
4
 
5
+ export {
6
+ SCHEMA_VERSION,
7
+ POLICY_VERSION,
8
+ OPERATION_FAMILIES,
9
+ operationSchemas,
10
+ operationJsonSchema,
11
+ boundedOperationJsonSchema,
12
+ OPERATION_SCHEMA_DEPTH,
13
+ OPERATION_SCHEMA_MAX_DEPTH,
14
+ canonicalFieldsDescription,
15
+ parseOperation,
16
+ success,
17
+ failure,
18
+ canonicalJson,
19
+ sha256,
20
+ newId,
21
+ newRevision,
22
+ decisionDigest,
23
+ candidateDigest,
24
+ requirementId,
25
+ } from "./core/task-contract";
26
+ export type {
27
+ OperationFamily,
28
+ OperationRequest,
29
+ TaskStartRequest,
30
+ Caller,
31
+ Scope,
32
+ Ref,
33
+ Assessment,
34
+ Dimension,
35
+ Requirement,
36
+ Constraint,
37
+ Intent,
38
+ Progress,
39
+ Policy,
40
+ Candidate,
41
+ Capability,
42
+ Entry,
43
+ EvidenceEvaluation,
44
+ Evidence,
45
+ Outcome,
46
+ Decision,
47
+ Finding,
48
+ Assignment,
49
+ WorkerReport,
50
+ Worker,
51
+ TaskRecord,
52
+ WorkspaceRecord,
53
+ TaskView,
54
+ TaskSummary,
55
+ ExportBundle,
56
+ Result as ContractResult,
57
+ } from "./core/task-contract";
58
+ export { TaskStore } from "./core/task-store";
59
+ export type { MetadataLock, ProcessEvidence, RecoveryInput } from "./core/task-store";
60
+ export { compactTaskContext, reconcileResume } from "./core/task-context";
61
+ export type {
62
+ CompactTaskContext,
63
+ ResumeObservation,
64
+ ResumeObservationInput,
65
+ ResumeReconciliation,
66
+ } from "./core/task-context";
67
+ export { METHODS, invariantBootstrap, selectMethods } from "./core/methods";
68
+ export type { MethodId, SelectedMethod } from "./core/methods";
69
+ export { applicableDecision, reserveAction, settleAction, reconcileAction } from "./core/authority";
70
+ export {
71
+ createAuthorizedExternalActionRunner,
72
+ runAuthorizedExternalAction,
73
+ } from "./core/external-action";
74
+ export type {
75
+ AuthorizedActionInput,
76
+ ExternalActionResult,
77
+ ExternalActionRunner,
78
+ ExternalActionEffect,
79
+ ExternalActionBinding,
80
+ NativeExternalActionObservation,
81
+ ExternalActionRequest,
82
+ ExternalActionOperation,
83
+ } from "./core/external-action";
84
+ export {
85
+ approvedExternalAction,
86
+ externalActionState,
87
+ priorExternalAction,
88
+ externalActionRef,
89
+ externalActionDescriptor,
90
+ externalActionHelp,
91
+ externalActionRequest,
92
+ matchesNativeExternalAction,
93
+ nativeExternalActionObservation,
94
+ readNativeExternalActionObservation,
95
+ } from "./core/external-action";
96
+ export type {
97
+ ActionReservation,
98
+ NativeAuthorityContext,
99
+ NativeAuthorityVerifier,
100
+ NativeActionVerification,
101
+ NativeReconciliationVerification,
102
+ NativeDecisionVerification,
103
+ ReserveActionInput,
104
+ SettleActionInput,
105
+ ReconcileActionInput,
106
+ } from "./core/authority";
107
+ export {
108
+ captureCandidate,
109
+ evaluateEvidence,
110
+ evaluateRequirements,
111
+ evaluateClosure,
112
+ } from "./core/task-evaluation";
113
+ export type { CandidateEnvironment, ClosureEvaluation } from "./core/task-evaluation";
114
+ export { WorkitCore } from "./core/task-engine";
115
+ export type { OperationContext } from "./core/task-engine";
116
+ export { assertProductWriteAllowed } from "./core/workers";
117
+ export type {
118
+ CallerContext,
119
+ HostSession,
120
+ NativeWorkerDispatchVerification,
121
+ NativeWorkerObservation,
122
+ NativeWorkerVerification,
123
+ NativeWorkerVerifier,
124
+ ProductWriteInput,
125
+ WorkerDispatch,
126
+ WorkerDispatchCommit,
127
+ WorkerDispatchRequest,
128
+ WorkerDispatchStage,
129
+ } from "./core/workers";
130
+
5
131
  export type Result<T> =
6
132
  | { ok: true; data: T; error: null }
7
133
  | { ok: false; data: T | null; error: string };
@@ -1,73 +1,40 @@
1
- Load `using-superpowers`, `subagent-driven-development`, `test-driven-development`, and `verification-before-completion` through OpenCode's `skill` tool. Implement the existing plan; do not re-plan.
1
+ Load resolved method skills through the host skill loader when policy selects them. Implement the existing plan; do not re-plan.
2
2
 
3
3
  **Spec:** <SPEC_PATH>
4
4
  **Plan:** <PLAN_PATH>
5
5
  **Branch:** <BRANCH>
6
- **SDD:** `<SDD_DIR>`
7
-
8
- ## Handoff destination
9
-
10
- This session is a handoff destination for a continued plan. The originating session already recorded the post-plan menu choice; present exactly these four choices plus model deferral and never re-offer the originating handoff option:
11
-
12
- - Subagent-driven
13
- - Inline
14
- - Review spec first
15
- - Review plan first
16
- - Change model first
17
-
18
- <workflow-handoff-destination>true</workflow-handoff-destination>
19
6
 
20
7
  ## Hard gates
21
8
 
22
- - The parent is coordinator-only: it does not edit product code or perform delegated exploration.
23
- - Never use a worktree. Branch changes are in-place through `workit_branch_setup` on `feature/*` or `bugfix/*`; never commit on protected branches.
24
- - Working state, briefs, ledgers, and review diffs live only under gitignored `<SDD_DIR>` in `docs/<slug>/sdd/` and use `workit_sdd_*` tools.
25
- - Use native `todowrite` for visible task state as well as the gitignored ledger.
26
- - Use native `question` for branch/stash choices and guarded external mutations; call mutation tools only after approval with `confirmed: true` (grounded in the recorded NativeChoiceEvidence).
27
- - Flow-tool confirmations are never agent-typed booleans and never caller-supplied evidence objects: on OpenCode the plugin records the user's native-`question` answer as a host-observed one-use receipt (`attested: true`, `callID`, `selectedLabel`, `recordedAt`) consumed by `workit_spec_approve` / `workit_plan_approve` / `workit_plan_menu` — no evidence argument exists, and delegated worker status comes from host session parentage (`parentID`), never a caller `role` field. On Cursor, confirmations are policy-only (`attested: false`), Subagent-driven execution is supported through the one-time `coordinator_lease` and per-task `delegation_token` minted by `workit_delegate` (fail-closed validation; no `parentID` identity exists on Cursor), and Inline runs single-agent in the current session.
28
- - Delegated authority is direct-child-only: a worker is the session whose host `parentID` exactly equals the activating coordinator's recorded `coordinator_session_id`; missing, mismatched, or multi-owner lineage fails closed with `delegation_lineage_denied`, and nested `opencode` launches are denied during active delegated work. An authorized child receives only the compact worker contract (execute the supplied brief, follow TDD, land one contiguous non-empty commit range, report results) — never coordinator guidance, `wk-implement`, or ledger management; coordinator bookkeeping via `workit_sdd_*` stays with the coordinator session.
29
- - On Cursor, for every repository-scoped `workit_*` call, pass the active Cursor workspace as `workspace_root`; never rely on the MCP process default.
30
- - Use native `task` with only the built-in `explore` and `general` agents (OpenCode); on Cursor, Subagent-driven dispatches Cursor-native subagents with a task `delegation_token`, Inline runs single-agent in the current session.
31
-
32
- ## Flow gates (HARD)
33
-
34
- - `wk-implement` refuses to run unless the plan is `approved` (flow.json) and the post-plan menu was presented.
35
- - `wk-handoff` refuses to run unless both spec and plan are `approved`.
36
- - Sequence is enforced by tools: `workit_spec_approve`, `workit_plan_approve`, `workit_plan_menu` — never skip a step (the spec/plan self-review runs automatically inside the transition; only the final approval asks for your confirmation).
9
+ - Inspect task state before acting. On OpenCode, Cursor, Codex, and Pi use the eight shared `workit_*` families (`workit_task`, `workit_policy`, `workit_evidence`, `workit_finding`, `workit_decision`, `workit_worker`, `workit_writer`, `workit_state`). On the CLI host use `workit <family> <action>` with the same actions (hyphenated on the CLI).
10
+ - Never use a worktree. Branch changes are in-place through the approved `git.branch_setup` external action (CLI: `workit action git.branch_setup --payload …`).
11
+ - Task metadata lives under `.workit/`; never edit it directly. Record progress, evidence, findings, decisions, and worker state only through the shared operations.
12
+ - Helpers cannot widen scope, record binding decisions, close or pause the task, assign further helpers, or resolve blockers for the lead.
13
+ - On Cursor, pass the active workspace as `workspace_root` on every repository-scoped call.
37
14
 
38
15
  ## Setup
39
16
 
40
- 0. Call `workit_docs_validate` with the linked spec/plan paths. Hard-fail on any error before todos or branch setup.
41
- 1. Call `workit_sdd_context` with `<PLAN_PATH>` and initialize `todowrite` from returned tasks.
42
- 2. Call `workit_plan_tasks`; cache each top-level task's `section_text`.
43
- 3. Mark IDs in `completed_task_ids` completed and never redispatch them.
44
- 4. Call `workit_resolve_branch`, then show the current branch, target branch, and stash behavior before any in-place checkout/setup mutation.
45
- 5. Always use `question`: for a clean tree ask whether to proceed or cancel; for a dirty tree add the stash choice and describe what will be stashed.
46
- 6. Call `workit_branch_setup` with `confirmed: true` only after approval.
17
+ 1. If there is no active or paused task, call `workit_task` with `action: "start"` then `workit_policy` with `action: "assess"` (CLI: `workit task start …` then `workit policy assess …`).
18
+ 2. Load `workit-plan`, list tasks with `workit_task` `action: "list"`, and mirror visible todo state to the host UI.
19
+ 3. When policy requires a feature branch, resolve it with read-only `context.read` and apply `git.branch_setup` only after native approval.
47
20
 
48
21
  ## Remaining-task loop
49
22
 
50
- For each top-level task absent from `completed_task_ids`:
23
+ For each bounded plan task:
51
24
 
52
- 1. Mark it `in_progress` with `todowrite`.
53
- 2. Create a working-state brief with `workit_sdd_task_brief` and `confirmed: true`.
54
- 3. Route by the approved execution mode: **Subagent-driven** delegates read-only discovery to an `explore` (OpenCode) agent, delegates implementation to a fresh `general` (OpenCode) agent (on Cursor, the coordinator mints a `delegation_token` with `workit_delegate` and the subagent prompt carries the raw token the worker passes it as `delegation_token` on its mutation calls, and appending progress revokes it), and the coordinator never edits product code; **Inline** executes every task in the current agent with no dispatch and no token minting. Product changes follow TDD.
55
- 4. Create a working-state diff with `workit_sdd_review_package` and `confirmed: true`.
56
- 5. Delegate spec-compliance review and code-quality review to separate `general` agents.
57
- 6. **Blocking** findings (Critical, Important, or spec-compliance) may trigger at most **two** fix+re-review rounds per task. **Advisory** findings (Minor, style, YAGNI, taste) never pause the loop — append them with `workit_sdd_append_advisory` (`--task <id> --text <text>`, `confirmed: true`) instead of an unrestricted file edit.
58
- 7. Append the validated ledger entry with `workit_sdd_append_progress` and `confirmed: true`; mark the todo completed.
25
+ 1. Mark the item in progress in the host todo UI and record boundary progress with `workit_task` `action: "progress"`.
26
+ 2. Route by policy: assign bounded workers with `workit_worker` `action: "assign"` when delegation is available; otherwise implement inline. Acquire product-write ownership with `workit_writer` `action: "acquire"` before repository mutations; release it when done.
27
+ 3. Record checks and artifacts with `workit_evidence` `action: "record"`. Record review concerns with `workit_finding` `action: "record"`; resolve or defer them with `finding.resolve`. Blocking findings may trigger at most **two** fix+re-review rounds per task; advisory taste/YAGNI items still use `finding.record` and never pause the loop by direct file edit.
28
+ 4. Never advance while a foreign writer is active or blocking findings remain open for the current candidate.
59
29
 
60
30
  ## Final gate
61
31
 
62
- Run a separate full-branch code review, then `workit_verify`. Present the full `<SDD_DIR>/advisories.md` roll-up once, then use native `question` so the user can choose which advisory items to fix, discuss, or discard. Report exact check results and never infer success. Use `workit_git_context` for a commit preview and load `wk-commit` through `skill` for an approved commit. If working state contains a stash reference, preview reapplication through `question`, then call `workit_branch_setup` with `confirmed: true` after approval.
63
-
64
- **Mandatory:** end the run by calling `workit_plan_complete` (OpenCode/Cursor) or the CLI `workit flow complete` (CLI host) after the final task once the SDD ledger is complete (all task IDs appended) and `workit_verify` passes — a complete ledger and green verification are the tool's gates. Never finish the run while the plan is still `active`.
32
+ Run repository verification (CLI: `workit doctor`; hosts: approved project verify when policy requires it). **Mandatory:** close the lead task with `workit_task` `action: "close"` (CLI: `workit task close --payload [--confirm]`) once requirements are satisfied and verification passes never finish while the task is still `active` or `paused`.
65
33
 
66
34
  ## Task order
67
35
 
68
36
  <TASK_LIST>
69
37
 
70
- ## Quality gate (HARD)
38
+ ## Quality gate
71
39
 
72
- - Specs/plans are written from `templates/spec-template.md` / `templates/plan-template.md`.
73
- - After `workit_docs_validate`, surface `quality` findings (spec scan). Hard findings (missing required section, missing CA-XX) block task start unless the user explicitly waives them. Warnings are advisory.
40
+ - Specs/plans follow `templates/spec-template.md` / `templates/plan-template.md`.
@@ -1,6 +1,6 @@
1
1
  # <Feature> Implementation Plan
2
2
 
3
- > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. On Cursor the two paths are: **Subagent-driven** — Cursor-native subagents dispatched by the coordinator, each carrying a task-scoped `delegation_token` minted with `workit_delegate` from the one-time `coordinator_lease`; **Inline** `executing-plans` in the current session, single-agent, no dispatch, no token minting. Steps use checkbox (`- [ ]`) syntax for tracking.
3
+ > **For agentic workers:** Load `workit-implement` when policy selects implementation. Use bounded `workit_worker` delegation when the host supports it; otherwise execute inline within writer scope. Steps use checkbox (`- [ ]`) syntax for tracking.
4
4
 
5
5
  **Spec:** `docs/<slug>/spec.md`
6
6
  **Branch:** `feature/<slug>`
@@ -9,8 +9,8 @@
9
9
 
10
10
  ## Global Constraints
11
11
 
12
- - Each task lands exactly one contiguous non-empty commit range (`base..head`): fix rounds append commits to that range and never rewrite/amend an active review range; each progress line records the task's real base..head shas.
13
- - The final task ends execution with `workit_plan_complete` (or the CLI `workit flow complete`) once the SDD ledger is complete and repository verification passes — a run never finishes while the plan is still `active`.
12
+ - Each task lands exactly one contiguous non-empty commit range (`base..head`): fix rounds append commits to that range and never rewrite/amend an active review range; record the real base..head shas in task progress.
13
+ - The final task closes the lead Workit task with `workit_task` `action: "close"` (CLI: `workit task close --payload … [--confirm]`) once requirements are satisfied and repository verification passes — never finish while the task is still `active` or `paused`.
14
14
  - <project-wide requirements, one line each>
15
15
 
16
16
  ---
@@ -2,6 +2,9 @@
2
2
 
3
3
  **Branch:** `feature/<slug>`
4
4
 
5
+ **Change:** ADDED|MODIFIED|REMOVED — <one-sentence intent>. (Small work with
6
+ no durable agreement: `Spec: none (<reason>)`, no file.)
7
+
5
8
  ## Context
6
9
 
7
10
  <!-- Why does this exist? What problem does it solve? 1-3 sentences. -->
@@ -16,13 +19,14 @@
16
19
 
17
20
  ## Architecture
18
21
 
19
- <!-- REQUIRED if this spec has flows or architecture: render a mermaid diagram (workit_present_flow). -->
22
+ <!-- May be `N/A (<reason>)` when the change has no flows or architecture. -->
23
+ <!-- Otherwise REQUIRED: render a mermaid diagram (workit-diagram skill). -->
20
24
  ```mermaid
21
25
  flowchart TD
22
26
  A[Start] --> B[Step]
23
27
  ```
24
28
 
25
- <!-- REQUIRED if this spec touches UI: render an ASCII wireframe (workit_present_ascii). -->
29
+ <!-- REQUIRED if this spec touches UI: render an ASCII wireframe (workit-mockup skill). -->
26
30
  ```text
27
31
  ┌──────────────┐
28
32
  │ Header │
@@ -39,8 +43,16 @@ flowchart TD
39
43
  ## Acceptance criteria
40
44
 
41
45
  <!-- REQUIRED: enumerable, each verifiable. Numbered CA-01, CA-02, ... -->
46
+ <!-- Requirements use SHALL/MUST (one per bullet, observable, no HOW); each
47
+ carries at least one GIVEN/WHEN/THEN, including the most-regretted edge. -->
42
48
  - CA-01 …
43
- - CA-02 …
49
+
50
+ ## Review checklist
51
+
52
+ <!-- Before implementation: intent matches; nothing extra; each requirement
53
+ testable with an exercising scenario; most-cared case covered;
54
+ tasks trace to requirements; you would sign if built exactly as written. -->
55
+ - [ ] …
44
56
 
45
57
  ## Decisions
46
58
 
@@ -0,0 +1,12 @@
1
+ # Workit contract
2
+
3
+ Workit keeps one accountable lead and one shared task state. Inspect current
4
+ task state before acting; use only the shared operations for task, policy,
5
+ evidence, finding, decision, worker, writer, and state changes. Authority is
6
+ bounded by the requested scope, current revision, caller/session provenance, and
7
+ observed capabilities. Never claim host enforcement or evidence that the host
8
+ cannot provide. Preserve unresolved requirements, gaps, and uncertain workers.
9
+
10
+ Focused methods are loaded only when the resolved policy requires them. A method
11
+ must call the shared operations and must not create a second lifecycle, approval
12
+ chain, or task-state representation.
@@ -1,2 +0,0 @@
1
- Load the wk-changelog skill and follow it.
2
- $ARGUMENTS
@@ -1,2 +0,0 @@
1
- Load the wk-commit skill and follow it.
2
- $ARGUMENTS
@@ -1,2 +0,0 @@
1
- Load the wk-docs-refresh skill and follow it.
2
- $ARGUMENTS
@@ -1,2 +0,0 @@
1
- Load the wk-handoff skill and follow it.
2
- $ARGUMENTS
@@ -1,2 +0,0 @@
1
- Load the wk-implement skill and follow it.
2
- $ARGUMENTS
@@ -1,2 +0,0 @@
1
- Load the wk-init skill and follow it.
2
- $ARGUMENTS
@@ -1,2 +0,0 @@
1
- Load the wk-issue-update skill and follow it.
2
- $ARGUMENTS
@@ -1,2 +0,0 @@
1
- Load the wk-meetings skill and follow it.
2
- $ARGUMENTS
package/commands/wk-pr.md DELETED
@@ -1,2 +0,0 @@
1
- Load the wk-pr skill and follow it.
2
- $ARGUMENTS
@@ -1,2 +0,0 @@
1
- Load the wk-release-notes skill and follow it.
2
- $ARGUMENTS
@@ -1,2 +0,0 @@
1
- Load the wk-status skill and follow it.
2
- $ARGUMENTS
@@ -1,2 +0,0 @@
1
- Load the wk-verify skill and follow it.
2
- $ARGUMENTS