supipowers 2.0.1 → 2.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 (80) hide show
  1. package/README.md +10 -6
  2. package/package.json +4 -2
  3. package/skills/harness/SKILL.md +1 -0
  4. package/src/bootstrap.ts +5 -133
  5. package/src/commands/clear.ts +6 -6
  6. package/src/commands/release.ts +3 -1
  7. package/src/commands/update.ts +1 -1
  8. package/src/config/defaults.ts +5 -5
  9. package/src/config/loader.ts +1 -0
  10. package/src/config/schema.ts +2 -6
  11. package/src/context/analyzer.ts +104 -35
  12. package/src/context-mode/knowledge/store.ts +381 -43
  13. package/src/context-mode/tools.ts +41 -3
  14. package/src/deps/registry.ts +1 -12
  15. package/src/fix-pr/assessment.ts +1 -0
  16. package/src/fix-pr/prompt-builder.ts +1 -0
  17. package/src/git/commit.ts +76 -18
  18. package/src/harness/command.ts +103 -6
  19. package/src/harness/default-agents/docs.md +39 -0
  20. package/src/harness/docs/config.ts +29 -0
  21. package/src/harness/docs/glob-match.ts +27 -0
  22. package/src/harness/docs/index-renderer.ts +82 -0
  23. package/src/harness/docs/provenance.ts +125 -0
  24. package/src/harness/docs/regen-decision.ts +167 -0
  25. package/src/harness/docs/representative-files.ts +175 -0
  26. package/src/harness/docs/source-hash.ts +106 -0
  27. package/src/harness/docs/validator.ts +233 -0
  28. package/src/harness/hooks/layer-context-inject.ts +35 -1
  29. package/src/harness/hooks/register.ts +24 -3
  30. package/src/harness/pipeline.ts +20 -5
  31. package/src/harness/pr-comment/baseline.ts +105 -0
  32. package/src/harness/pr-comment/ci-env.ts +120 -0
  33. package/src/harness/pr-comment/gh-poster.ts +227 -0
  34. package/src/harness/pr-comment/handler.ts +198 -0
  35. package/src/harness/pr-comment/render.ts +297 -0
  36. package/src/harness/pr-comment/status.ts +95 -0
  37. package/src/harness/pr-comment/types.ts +73 -0
  38. package/src/harness/pr-comment/workflow-summary.ts +47 -0
  39. package/src/harness/project-paths.ts +95 -0
  40. package/src/harness/stages/design.ts +1 -0
  41. package/src/harness/stages/discover.ts +1 -13
  42. package/src/harness/stages/docs.ts +708 -0
  43. package/src/harness/stages/implement-apply.ts +877 -0
  44. package/src/harness/stages/implement.ts +64 -51
  45. package/src/harness/stages/plan.ts +25 -16
  46. package/src/harness/stages/validate.ts +370 -0
  47. package/src/harness/storage.ts +142 -0
  48. package/src/harness/tools.ts +130 -0
  49. package/src/mempalace/bridge.ts +207 -41
  50. package/src/mempalace/config.ts +10 -4
  51. package/src/mempalace/format.ts +122 -6
  52. package/src/mempalace/hooks.ts +204 -56
  53. package/src/mempalace/installer-helper.ts +18 -4
  54. package/src/mempalace/python/mempalace_bridge.py +128 -3
  55. package/src/mempalace/runtime.ts +55 -18
  56. package/src/mempalace/schema.ts +151 -30
  57. package/src/mempalace/session-summary.ts +5 -0
  58. package/src/mempalace/tool.ts +17 -4
  59. package/src/mempalace/upstream-limits.ts +69 -0
  60. package/src/planning/approval-flow.ts +25 -2
  61. package/src/planning/planning-ask-tool.ts +34 -4
  62. package/src/planning/system-prompt.ts +1 -1
  63. package/src/tool-catalog/active-tool-controller.ts +0 -22
  64. package/src/tool-catalog/active-tool-planner.ts +0 -26
  65. package/src/tool-catalog/tool-groups.ts +1 -9
  66. package/src/types.ts +87 -8
  67. package/src/ui-design/session.ts +114 -10
  68. package/src/utils/executable.ts +10 -1
  69. package/src/workspace/state-paths.ts +1 -1
  70. package/src/commands/mcp.ts +0 -814
  71. package/src/mcp/activation.ts +0 -77
  72. package/src/mcp/config.ts +0 -223
  73. package/src/mcp/docs.ts +0 -154
  74. package/src/mcp/gateway.ts +0 -103
  75. package/src/mcp/lifecycle.ts +0 -79
  76. package/src/mcp/manager-tool.ts +0 -104
  77. package/src/mcp/mcpc.ts +0 -113
  78. package/src/mcp/registry.ts +0 -98
  79. package/src/mcp/triggers.ts +0 -62
  80. package/src/mcp/types.ts +0 -95
@@ -108,15 +108,19 @@ function snapshotSessionProgress(sessionDir: string): string | null {
108
108
  for (const entry of entries) {
109
109
  const absolutePath = path.join(currentDir, entry.name);
110
110
  const relativePath = path.relative(sessionDir, absolutePath);
111
- const stats = fs.statSync(absolutePath);
112
-
113
111
  if (entry.isDirectory()) {
114
- hash.update(`dir:${relativePath}:${stats.mtimeMs}\n`);
112
+ hash.update("dir\0");
113
+ hash.update(relativePath);
114
+ hash.update("\0");
115
115
  visit(absolutePath);
116
116
  continue;
117
117
  }
118
118
 
119
- hash.update(`file:${relativePath}:${stats.size}:${stats.mtimeMs}\n`);
119
+ hash.update("file\0");
120
+ hash.update(relativePath);
121
+ hash.update("\0");
122
+ hash.update(fs.readFileSync(absolutePath));
123
+ hash.update("\0");
120
124
  }
121
125
  };
122
126
 
@@ -765,6 +769,106 @@ function discardSessionDir(sessionDir: string): void {
765
769
  }
766
770
  }
767
771
 
772
+ function buildCompletionRepairSteer(
773
+ sessionDir: string,
774
+ manifest: Manifest,
775
+ completionIssues: string[],
776
+ ): string {
777
+ return manifest.backend === "pencil-mcp"
778
+ ? REPAIR_COMPLETE_STEER_TEMPLATE_PENCIL(sessionDir, manifest.penFilePath, completionIssues)
779
+ : REPAIR_COMPLETE_STEER_TEMPLATE(sessionDir, completionIssues);
780
+ }
781
+
782
+ function sendNoUiPauseMessage(
783
+ platform: Platform,
784
+ sessionDir: string,
785
+ status: ManifestStatus,
786
+ ): void {
787
+ const message = [
788
+ `ui-design session paused with status \`${status}\` in a no-UI runtime.`,
789
+ `Artifacts were preserved at \`${sessionDir}\`.`,
790
+ "Interactive review is unavailable here. Continue manually by inspecting that directory or rerun `/supi:ui-design` in an interactive TUI.",
791
+ ].join("\n");
792
+ platform.sendMessage(
793
+ {
794
+ customType: "supi-ui-design-paused-no-ui",
795
+ content: [{ type: "text", text: message }],
796
+ display: true,
797
+ },
798
+ { deliverAs: "steer", triggerTurn: false },
799
+ );
800
+ }
801
+
802
+ async function handleNoUiUiDesignAgentEnd(
803
+ platform: Platform,
804
+ ctx: any,
805
+ session: UiDesignSession,
806
+ manifest: Manifest | null,
807
+ ): Promise<void> {
808
+ const sessionDir = session.dir;
809
+
810
+ if (!manifest) {
811
+ await runCleanup();
812
+ ctx?.ui?.notify?.(
813
+ `ui-design session state is unreadable; artifacts preserved at ${sessionDir}.`,
814
+ "warning",
815
+ );
816
+ cancelUiDesignTracking("manifest_missing_no_ui");
817
+ return;
818
+ }
819
+
820
+ if (manifest.status === "complete") {
821
+ const completion = validateCompletionProof(sessionDir, manifest);
822
+ const validatedManifest = completion.validatedManifest;
823
+ if (
824
+ !sameCritiqueSummary(manifest.critique, validatedManifest.critique) ||
825
+ manifest.approvedAt !== validatedManifest.approvedAt
826
+ ) {
827
+ writeManifest(sessionDir, validatedManifest);
828
+ }
829
+
830
+ if (completion.issues.length > 0) {
831
+ await resumeSession(
832
+ platform,
833
+ ctx,
834
+ session,
835
+ buildCompletionRepairSteer(sessionDir, manifest, completion.issues),
836
+ );
837
+ return;
838
+ }
839
+
840
+ writeManifest(sessionDir, { ...validatedManifest, acknowledged: true });
841
+ await runCleanup();
842
+ ctx?.ui?.notify?.(`ui-design complete; artifacts kept at ${sessionDir}.`, "info");
843
+ cancelUiDesignTracking("complete_no_ui");
844
+ return;
845
+ }
846
+
847
+ if (manifest.status === "discarded") {
848
+ await runCleanup();
849
+ discardSessionDir(sessionDir);
850
+ cancelUiDesignTracking("discarded_no_ui");
851
+ return;
852
+ }
853
+
854
+ if (
855
+ manifest.status === "in-progress" ||
856
+ manifest.status === "critiquing" ||
857
+ manifest.status === "awaiting-review"
858
+ ) {
859
+ if (sessionMadeProgress(sessionDir)) {
860
+ await resumeSession(platform, ctx, session, RESUME_STEER_TEMPLATE(sessionDir));
861
+ return;
862
+ }
863
+
864
+ sendNoUiPauseMessage(platform, sessionDir, manifest.status);
865
+ ctx?.ui?.notify?.(`ui-design paused; artifacts preserved at ${sessionDir}.`, "warning");
866
+ await runCleanup();
867
+ cancelUiDesignTracking("paused_no_ui");
868
+ }
869
+ }
870
+
871
+
768
872
  function getUiDesignWritePaths(toolName: string, input: Record<string, unknown>): string[] | undefined {
769
873
  switch (toolName) {
770
874
  case "write":
@@ -784,8 +888,6 @@ function getUiDesignWritePaths(toolName: string, input: Record<string, unknown>)
784
888
  : "",
785
889
  );
786
890
  }
787
- case "notebook":
788
- return [typeof input.notebook_path === "string" ? input.notebook_path : ""];
789
891
  default:
790
892
  return undefined;
791
893
  }
@@ -852,11 +954,15 @@ export function registerUiDesignToolGuard(platform: Platform): void {
852
954
  export function registerUiDesignApprovalHook(platform: Platform): void {
853
955
  platform.on("agent_end", async (_event: any, ctx: any) => {
854
956
  const session = activeSession;
855
- if (!session || !ctx?.hasUI) return;
957
+ if (!session) return;
856
958
 
857
959
  const sessionDir = session.dir;
858
960
  const manifest = readManifest(sessionDir);
859
961
 
962
+ if (!ctx?.hasUI) {
963
+ await handleNoUiUiDesignAgentEnd(platform, ctx, session, manifest);
964
+ return;
965
+ }
860
966
  // Missing / unparseable manifest — unsafe to resume
861
967
  if (!manifest) {
862
968
  const choice = await ctx.ui.select(
@@ -890,9 +996,7 @@ export function registerUiDesignApprovalHook(platform: Platform): void {
890
996
  // Pencil manifests always cite pencil artifacts in their repair steer,
891
997
  // even when `penFilePath` is missing — the HTML template would point
892
998
  // at files pencil sessions never produce.
893
- const repairSteer = manifest.backend === "pencil-mcp"
894
- ? REPAIR_COMPLETE_STEER_TEMPLATE_PENCIL(sessionDir, manifest.penFilePath, completion.issues)
895
- : REPAIR_COMPLETE_STEER_TEMPLATE(sessionDir, completion.issues);
999
+ const repairSteer = buildCompletionRepairSteer(sessionDir, manifest, completion.issues);
896
1000
  await resumeSession(
897
1001
  platform,
898
1002
  ctx,
@@ -36,8 +36,17 @@ function isFile(filePath: string): boolean {
36
36
  }
37
37
  }
38
38
 
39
+ function defaultSearchPath(): string {
40
+ if (process.env.PATH !== undefined) {
41
+ return process.env.PATH;
42
+ }
43
+
44
+ const pathKey = Object.keys(process.env).find((key) => key.toLowerCase() === "path");
45
+ return pathKey ? process.env[pathKey] ?? "" : "";
46
+ }
47
+
39
48
  function resolveSearchDirectories(options: ExecutableSearchOptions): string[] {
40
- const pathDirs = (options.searchPath ?? process.env.PATH ?? "")
49
+ const pathDirs = (options.searchPath ?? defaultSearchPath())
41
50
  .split(path.delimiter)
42
51
  .filter(Boolean);
43
52
  const localDirs = (options.localDirs ?? []).map((dir) =>
@@ -17,7 +17,7 @@ function splitWorkspacePath(relativeDir: string): string[] {
17
17
  // Team-shared (local) state: <cwd-or-repoRoot>/.omp/supipowers/<...>
18
18
  //
19
19
  // These paths are committed (or at least shareable) across a team clone. Used for
20
- // config.json, model.json, review-agents/config.yml, mcpc manifests, etc.
20
+ // config.json, model.json, review-agents/config.yml, etc.
21
21
  // ──────────────────────────────────────────────────────────────────────────
22
22
 
23
23
  export function getRootStateDir(paths: PlatformPaths, repoRoot: string): string {