superpowers-manager 0.4.0 → 0.5.1

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 (44) hide show
  1. package/README.md +76 -517
  2. package/dist/artifact-tree.js +111 -0
  3. package/dist/atomic.js +103 -7
  4. package/dist/cli-arguments.js +37 -0
  5. package/dist/cli.js +49 -12
  6. package/dist/commands/install.js +116 -17
  7. package/dist/commands/mutation.js +71 -0
  8. package/dist/commands/prepare.js +23 -17
  9. package/dist/commands/probe.js +164 -14
  10. package/dist/commands/uninstall.js +9 -5
  11. package/dist/commands/update.js +6 -2
  12. package/dist/domain/refs.js +4 -0
  13. package/dist/harness-compatibility.js +13 -0
  14. package/dist/{adapter.js → harnesses/codex/adapter.js} +17 -13
  15. package/dist/harnesses/codex/compatibility.js +126 -0
  16. package/dist/harnesses/codex/conflicts.js +99 -0
  17. package/dist/{generated-plugin.js → harnesses/codex/generated-plugin.js} +7 -73
  18. package/dist/{codex-harness.js → harnesses/codex/harness.js} +55 -5
  19. package/dist/{hooks.js → harnesses/codex/hooks.js} +6 -6
  20. package/dist/{codex-json.js → harnesses/codex/json.js} +9 -2
  21. package/dist/{lifecycle.js → harnesses/codex/lifecycle.js} +2 -2
  22. package/dist/{manifest-overlay.js → harnesses/codex/manifest-overlay.js} +5 -5
  23. package/dist/{codex-prepare.js → harnesses/codex/prepare.js} +72 -16
  24. package/dist/{codex-presentation.js → harnesses/codex/presentation.js} +27 -4
  25. package/dist/{codex-state.js → harnesses/codex/state.js} +3 -3
  26. package/dist/harnesses/pi/compatibility.js +73 -0
  27. package/dist/harnesses/pi/harness.js +63 -0
  28. package/dist/harnesses/pi/install.js +495 -0
  29. package/dist/harnesses/pi/native.js +81 -0
  30. package/dist/harnesses/pi/package.js +153 -0
  31. package/dist/harnesses/pi/paths.js +30 -0
  32. package/dist/harnesses/pi/prepare.js +111 -0
  33. package/dist/harnesses/pi/presentation.js +67 -0
  34. package/dist/harnesses/pi/settings.js +171 -0
  35. package/dist/harnesses/pi/shared-skills.js +413 -0
  36. package/dist/harnesses/pi/state.js +311 -0
  37. package/dist/python-text.js +16 -0
  38. package/dist/resource-lock.js +265 -0
  39. package/dist/safe-path.js +21 -5
  40. package/dist/skill-validation.js +52 -0
  41. package/dist/upstream-workspace.js +8 -0
  42. package/dist/validate-generated-plugin-cli.js +1 -1
  43. package/dist/validator.js +2 -1
  44. package/package.json +12 -8
@@ -0,0 +1,52 @@
1
+ import { lstat, readdir, readFile, readlink, stat } from "node:fs/promises";
2
+ import { pythonSplitlines, pythonStrip } from "./python-text.js";
3
+ export const DEFAULT_FS_DEPS = {
4
+ lstat,
5
+ stat,
6
+ readdir,
7
+ readlink,
8
+ readFile,
9
+ };
10
+ const STRICT_DECODER = new TextDecoder("utf-8", {
11
+ fatal: true,
12
+ ignoreBOM: true,
13
+ });
14
+ export async function validateSkillFrontmatter(skillMd, skillName, errors, deps) {
15
+ let contents;
16
+ try {
17
+ contents = STRICT_DECODER.decode(await deps.readFile(skillMd));
18
+ }
19
+ catch {
20
+ errors.push(`skill \`${skillName}\` has unreadable UTF-8 \`SKILL.md\``);
21
+ return;
22
+ }
23
+ if (contents === "") {
24
+ errors.push(`skill \`${skillName}\` has empty \`SKILL.md\``);
25
+ return;
26
+ }
27
+ const lines = pythonSplitlines(contents);
28
+ if (lines.length === 0 || lines[0] !== "---") {
29
+ errors.push(`skill \`${skillName}\` must start with \`---\``);
30
+ return;
31
+ }
32
+ const closingIndex = lines.indexOf("---", 1);
33
+ if (closingIndex === -1) {
34
+ errors.push(`skill \`${skillName}\` frontmatter is not closed`);
35
+ return;
36
+ }
37
+ const frontmatter = lines.slice(1, closingIndex);
38
+ for (const key of ["name", "description"]) {
39
+ const matches = frontmatter.filter((line) => line.startsWith(`${key}:`));
40
+ if (matches.length !== 1) {
41
+ errors.push(`skill \`${skillName}\` frontmatter must contain exactly one top-level \`${key}:\``);
42
+ continue;
43
+ }
44
+ const value = pythonStrip(matches[0].slice(matches[0].indexOf(":") + 1));
45
+ if (value === "" ||
46
+ value === "''" ||
47
+ value === '""' ||
48
+ value.startsWith("#")) {
49
+ errors.push(`skill \`${skillName}\` frontmatter field \`${key}\` must be non-empty`);
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,8 @@
1
+ import { isAbsolute, join, resolve } from "node:path";
2
+ export function upstreamCacheRoot(root, env, cwd) {
3
+ const configured = env.SUPERPOWERS_CACHE_DIR || join(root, ".cache", "upstream");
4
+ const cacheParent = isAbsolute(configured)
5
+ ? configured
6
+ : resolve(cwd, configured);
7
+ return join(cacheParent, "superpowers");
8
+ }
@@ -1,6 +1,6 @@
1
1
  import { realpathSync } from "node:fs";
2
2
  import { oneLine, parseFlags, UsageError } from "./cli-arguments.js";
3
- import { validateGeneratedPlugin, } from "./generated-plugin.js";
3
+ import { validateGeneratedPlugin, } from "./harnesses/codex/generated-plugin.js";
4
4
  const FLAGS = [
5
5
  "plugin-root",
6
6
  "source",
package/dist/validator.js CHANGED
@@ -68,7 +68,7 @@ function signalGroup(child, signal) {
68
68
  /* the group exited between the timer firing and this call */
69
69
  }
70
70
  }
71
- export function runValidator(argv, policy, env, workspace) {
71
+ export function runValidator(argv, policy, env, workspace, cwd) {
72
72
  return new Promise((resolveRun) => {
73
73
  const [command, ...args] = argv;
74
74
  const limit = policy.kind === "bounded" ? policy.maxBytesPerStream : null;
@@ -111,6 +111,7 @@ export function runValidator(argv, policy, env, workspace) {
111
111
  try {
112
112
  child = spawn(command, args, {
113
113
  env: { ...process.env, ...env, TMPDIR: workspace },
114
+ cwd,
114
115
  stdio: ["ignore", "pipe", "pipe"],
115
116
  // D4: under the BOUNDED policy only, the child leads its own process group
116
117
  // so a timeout can signal the GROUP -- signalling the process alone leaves
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "superpowers-manager",
3
- "version": "0.4.0",
4
- "description": "Install and update the latest stable obra/superpowers release directly from upstream, without waiting for agent marketplaces to catch up. Codex supported today.",
3
+ "version": "0.5.1",
4
+ "description": "Install obra/superpowers directly from upstream for Codex and Pi. Stay on a known-good release or commit, try a branch, and upgrade when you choose.",
5
5
  "keywords": [
6
6
  "superpowers",
7
7
  "obra-superpowers",
@@ -14,19 +14,23 @@
14
14
  "plugin-manager",
15
15
  "cli",
16
16
  "installer",
17
- "updater"
17
+ "updater",
18
+ "pi",
19
+ "pi-coding-agent",
20
+ "version-pinning"
18
21
  ],
19
22
  "license": "MIT",
20
23
  "type": "module",
21
- "packageManager": "pnpm@11.25.0",
24
+ "packageManager": "pnpm@12.3.4",
22
25
  "scripts": {
23
- "lint": "oxlint src/ tests/bin/ tests/unit/ tests/baseline/ tests/lib/ tests/tools/ tests/run-node-suites.ts tests/assert-matcher-gate.ts",
24
- "format": "prettier --write src/ tests/bin/ tests/unit/ tests/baseline/ tests/lib/ tests/tools/ tests/run-node-suites.ts tests/assert-matcher-gate.ts",
25
- "format:check": "prettier --check src/ tests/bin/ tests/unit/ tests/baseline/ tests/lib/ tests/tools/ tests/run-node-suites.ts tests/assert-matcher-gate.ts",
26
+ "lint": "oxlint src/ tests/bin/ tests/unit/ tests/baseline/ tests/lib/ tests/tools/ tests/container/ tests/run-node-suites.ts tests/assert-matcher-gate.ts",
27
+ "format": "prettier --write src/ tests/bin/ tests/unit/ tests/baseline/ tests/lib/ tests/tools/ tests/container/ tests/run-node-suites.ts tests/assert-matcher-gate.ts",
28
+ "format:check": "prettier --check src/ tests/bin/ tests/unit/ tests/baseline/ tests/lib/ tests/tools/ tests/container/ tests/run-node-suites.ts tests/assert-matcher-gate.ts",
26
29
  "test": "node tests/run-node-suites.ts",
27
30
  "test:unit": "node tests/run-node-suites.ts --group unit",
28
31
  "test:integration": "node tests/run-node-suites.ts --group integration",
29
- "test:harness:codex": "sh tests/container.sh codex-spike",
32
+ "test:harness:codex": "sh tests/container.sh harness-codex",
33
+ "test:harness:pi": "sh tests/container.sh harness-pi",
30
34
  "test:acceptance": "sh tests/acceptance.sh",
31
35
  "check:static": "pnpm run format:check && pnpm run lint && pnpm run typecheck",
32
36
  "check": "pnpm run check:static && pnpm run test",