superpowers-manager 0.5.2 → 0.7.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 (83) hide show
  1. package/README.md +44 -26
  2. package/dist/adapter-result.js +5 -9
  3. package/dist/atomic.js +4 -14
  4. package/dist/cli-arguments.js +1 -27
  5. package/dist/cli.js +32 -52
  6. package/dist/commands/adapter-call.js +28 -0
  7. package/dist/commands/install.js +26 -107
  8. package/dist/commands/mutation.js +7 -0
  9. package/dist/commands/pin.js +1 -1
  10. package/dist/commands/prepare.js +39 -129
  11. package/dist/commands/probe.js +35 -264
  12. package/dist/commands/track-latest.js +1 -1
  13. package/dist/commands/uninstall.js +16 -92
  14. package/dist/commands/update.js +5 -25
  15. package/dist/effective-selection.js +7 -9
  16. package/dist/git-tree.js +85 -0
  17. package/dist/harness-command-result.js +47 -0
  18. package/dist/harnesses/codex/adapter.js +231 -510
  19. package/dist/harnesses/codex/compatibility.js +2 -17
  20. package/dist/harnesses/codex/conflicts.js +2 -3
  21. package/dist/harnesses/codex/harness.js +18 -263
  22. package/dist/harnesses/codex/hooks.js +1 -1
  23. package/dist/harnesses/codex/json.js +1 -11
  24. package/dist/harnesses/codex/lifecycle.js +80 -72
  25. package/dist/harnesses/codex/manifest-overlay.js +23 -18
  26. package/dist/harnesses/codex/paths.js +14 -29
  27. package/dist/harnesses/codex/presentation.js +8 -37
  28. package/dist/harnesses/codex/publication.js +13 -37
  29. package/dist/harnesses/codex/recovery.js +5 -5
  30. package/dist/harnesses/codex/stored-state.js +1 -1
  31. package/dist/harnesses/opencode/config.js +256 -0
  32. package/dist/harnesses/opencode/discovery.js +587 -0
  33. package/dist/harnesses/opencode/harness.js +37 -0
  34. package/dist/harnesses/opencode/install.js +601 -0
  35. package/dist/harnesses/opencode/native.js +57 -0
  36. package/dist/harnesses/opencode/package.js +89 -0
  37. package/dist/harnesses/opencode/paths.js +38 -0
  38. package/dist/harnesses/opencode/prepare.js +30 -0
  39. package/dist/harnesses/opencode/presentation.js +28 -0
  40. package/dist/harnesses/opencode/state.js +174 -0
  41. package/dist/harnesses/pi/compatibility.js +5 -37
  42. package/dist/harnesses/pi/install.js +7 -5
  43. package/dist/harnesses/pi/native.js +3 -47
  44. package/dist/harnesses/pi/package.js +5 -107
  45. package/dist/harnesses/pi/prepare.js +13 -104
  46. package/dist/harnesses/pi/presentation.js +23 -66
  47. package/dist/harnesses/pi/shared-skills.js +28 -39
  48. package/dist/harnesses/pi/state.js +7 -27
  49. package/dist/provenance.js +2 -2
  50. package/dist/python-json-format.js +0 -69
  51. package/dist/python-json.js +2 -27
  52. package/dist/python-text.js +9 -69
  53. package/dist/safe-path.js +2 -2
  54. package/dist/selection-store.js +2 -22
  55. package/dist/snapshot-package.js +78 -0
  56. package/dist/snapshot-prepare.js +99 -0
  57. package/dist/snapshot-presentation.js +44 -0
  58. package/dist/validator.js +39 -73
  59. package/node_modules/jsonc-parser/CHANGELOG.md +76 -0
  60. package/node_modules/jsonc-parser/LICENSE.md +21 -0
  61. package/node_modules/jsonc-parser/README.md +364 -0
  62. package/node_modules/jsonc-parser/SECURITY.md +41 -0
  63. package/node_modules/jsonc-parser/lib/esm/impl/edit.js +185 -0
  64. package/node_modules/jsonc-parser/lib/esm/impl/format.js +261 -0
  65. package/node_modules/jsonc-parser/lib/esm/impl/parser.js +659 -0
  66. package/node_modules/jsonc-parser/lib/esm/impl/scanner.js +443 -0
  67. package/node_modules/jsonc-parser/lib/esm/impl/string-intern.js +29 -0
  68. package/node_modules/jsonc-parser/lib/esm/main.d.ts +351 -0
  69. package/node_modules/jsonc-parser/lib/esm/main.js +178 -0
  70. package/node_modules/jsonc-parser/lib/umd/impl/edit.js +201 -0
  71. package/node_modules/jsonc-parser/lib/umd/impl/format.js +275 -0
  72. package/node_modules/jsonc-parser/lib/umd/impl/parser.js +682 -0
  73. package/node_modules/jsonc-parser/lib/umd/impl/scanner.js +456 -0
  74. package/node_modules/jsonc-parser/lib/umd/impl/string-intern.js +42 -0
  75. package/node_modules/jsonc-parser/lib/umd/main.d.ts +351 -0
  76. package/node_modules/jsonc-parser/lib/umd/main.js +194 -0
  77. package/node_modules/jsonc-parser/package.json +37 -0
  78. package/package.json +8 -4
  79. package/dist/domain/fingerprint.js +0 -4
  80. package/dist/selection-state-cli.js +0 -85
  81. package/dist/status.js +0 -24
  82. package/dist/upstream-cli.js +0 -110
  83. package/dist/validate-generated-plugin-cli.js +0 -118
@@ -1,85 +0,0 @@
1
- import { realpathSync } from "node:fs";
2
- import { writeFile } from "node:fs/promises";
3
- import { displaySource, normalizePinnedArguments, normalizeSaved, validateSource, } from "./selection.js";
4
- import { readSelectionState, writeSelectionState } from "./selection-store.js";
5
- import { oneLine, parseFlags, UsageError } from "./cli-arguments.js";
6
- const COMMAND_FLAGS = {
7
- read: ["path", "output"],
8
- "write-pinned": ["path", "source", "requested-ref", "resolved-ref", "commit"],
9
- "write-track-latest": ["path", "source"],
10
- "validate-source": ["source"],
11
- "display-source": ["source"],
12
- };
13
- function parseCommand(argv) {
14
- const [name, ...rest] = argv;
15
- if (name === undefined)
16
- throw new UsageError("a subcommand is required");
17
- if (!Object.hasOwn(COMMAND_FLAGS, name)) {
18
- throw new UsageError(`unknown subcommand: ${name}`);
19
- }
20
- const command = name;
21
- return { name: command, flags: parseFlags(rest, COMMAND_FLAGS[command]) };
22
- }
23
- async function dispatch({ name, flags }) {
24
- if (name === "read") {
25
- const normalized = normalizeSaved(await readSelectionState(flags.path));
26
- try {
27
- await writeFile(flags.output, `${JSON.stringify(normalized, null, 2)}\n`, "utf8");
28
- }
29
- catch (cause) {
30
- const message = cause instanceof Error ? cause.message : String(cause);
31
- throw new Error(`cannot write normalized selection output ${flags.output}: ${message}`, { cause });
32
- }
33
- return;
34
- }
35
- if (name === "write-pinned") {
36
- await writeSelectionState(flags.path, normalizePinnedArguments({
37
- source: flags.source,
38
- requestedRef: flags["requested-ref"],
39
- resolvedRef: flags["resolved-ref"],
40
- commit: flags.commit,
41
- }));
42
- return;
43
- }
44
- if (name === "write-track-latest") {
45
- await writeSelectionState(flags.path, {
46
- schema_version: 1,
47
- mode: "track-latest",
48
- source: flags.source,
49
- });
50
- return;
51
- }
52
- if (name === "validate-source") {
53
- validateSource(flags.source);
54
- return;
55
- }
56
- if (name === "display-source") {
57
- process.stdout.write(`${displaySource(flags.source)}\n`);
58
- return;
59
- }
60
- const unreachable = name;
61
- throw new Error(`unhandled subcommand: ${String(unreachable)}`);
62
- }
63
- export async function runSelectionStateCli(argv) {
64
- let command;
65
- try {
66
- command = parseCommand(argv);
67
- }
68
- catch (cause) {
69
- process.stderr.write(`usage: selection-state-cli <subcommand> [options]\n`);
70
- process.stderr.write(`error: ${oneLine(cause)}\n`);
71
- return 2;
72
- }
73
- try {
74
- await dispatch(command);
75
- return 0;
76
- }
77
- catch (cause) {
78
- process.stderr.write(`error: ${oneLine(cause)}\n`);
79
- return 1;
80
- }
81
- }
82
- const entry = process.argv[1];
83
- if (entry !== undefined && import.meta.filename === realpathSync(entry)) {
84
- process.exitCode = await runSelectionStateCli(process.argv.slice(2));
85
- }
package/dist/status.js DELETED
@@ -1,24 +0,0 @@
1
- // Ports scripts/core/status.sh in full. Both functions are pure: no I/O, no
2
- // environment. The three status strings are operator-facing and frozen.
3
- // `git show ad56569a4c161e7b122967442e2b026eeb6395f6:scripts/core/status.sh:4-9::spw_commit_matches(`.
4
- // The `[ -n "$observed" ]` guard comes first and is load-bearing: an empty
5
- // observed commit must never match, or an absent generated tree reads as
6
- // current.
7
- export function commitMatches(desired, observed) {
8
- if (observed.length === 0)
9
- return false;
10
- return observed === desired || observed === desired.slice(0, 7);
11
- }
12
- // `git show ad56569a4c161e7b122967442e2b026eeb6395f6:scripts/core/status.sh:11-27::spw_status_for_commits`.
13
- // Branch order is part of the contract: a stale generated tree outranks a null
14
- // installed fingerprint, so the operator is told to prepare before being told
15
- // to install.
16
- export function statusForCommits(desired, generated, installed) {
17
- if (generated.length === 0 || !commitMatches(desired, generated)) {
18
- return "needs prepare";
19
- }
20
- if (installed.length === 0 || !commitMatches(desired, installed)) {
21
- return "needs install";
22
- }
23
- return "current";
24
- }
@@ -1,110 +0,0 @@
1
- import { realpathSync } from "node:fs";
2
- import { oneLine, parseFlags, UsageError } from "./cli-arguments.js";
3
- import { COMMIT_INPUT_RE, TAG_RE } from "./domain/refs.js";
4
- import { fetchExactCommit, gitSafeSource, resolveExactTag, resolveRef, verifyRawCommit, } from "./upstream.js";
5
- import { manifestVersionForRef } from "./upstream-version.js";
6
- const COMMAND_FLAGS = {
7
- "resolve-ref": ["source", "ref"],
8
- "resolve-exact-tag": ["source", "ref"],
9
- "verify-raw-commit": ["source", "commit", "workspace-parent"],
10
- "fetch-exact-commit": ["source", "commit", "repository", "workspace-parent"],
11
- "manifest-version": [
12
- "requested-ref",
13
- "resolution-kind",
14
- "resolved-ref",
15
- "commit",
16
- ],
17
- "pin-kind": ["ref"],
18
- "safe-source": ["source"],
19
- };
20
- const RESOLUTION_KINDS = [
21
- "latest-release",
22
- "tag",
23
- "ref",
24
- "raw-commit",
25
- ];
26
- function parseResolutionKind(value) {
27
- const found = RESOLUTION_KINDS.find((kind) => kind === value);
28
- if (found === undefined) {
29
- throw new UsageError(`unknown resolution kind: ${value}`);
30
- }
31
- return found;
32
- }
33
- function parseCommand(argv) {
34
- const [name, ...rest] = argv;
35
- if (name === undefined)
36
- throw new UsageError("a subcommand is required");
37
- if (!Object.hasOwn(COMMAND_FLAGS, name)) {
38
- throw new UsageError(`unknown subcommand: ${name}`);
39
- }
40
- const command = name;
41
- return { name: command, flags: parseFlags(rest, COMMAND_FLAGS[command]) };
42
- }
43
- async function dispatch({ name, flags }) {
44
- if (name === "resolve-ref") {
45
- const resolution = await resolveRef(flags.source, flags.ref);
46
- process.stdout.write(`${resolution.kind} ${resolution.ref} ${resolution.commit}\n`);
47
- return;
48
- }
49
- if (name === "resolve-exact-tag") {
50
- process.stdout.write(`${await resolveExactTag(flags.source, flags.ref)}\n`);
51
- return;
52
- }
53
- if (name === "verify-raw-commit") {
54
- const commit = await verifyRawCommit(flags.source, flags.commit, flags["workspace-parent"]);
55
- process.stdout.write(`${commit}\n`);
56
- return;
57
- }
58
- if (name === "fetch-exact-commit") {
59
- await fetchExactCommit(flags.source, flags.commit, flags.repository, flags["workspace-parent"]);
60
- return;
61
- }
62
- if (name === "manifest-version") {
63
- const version = manifestVersionForRef({
64
- requestedRef: flags["requested-ref"],
65
- resolutionKind: parseResolutionKind(flags["resolution-kind"]),
66
- resolvedRef: flags["resolved-ref"],
67
- commit: flags.commit,
68
- });
69
- process.stdout.write(`${version}\n`);
70
- return;
71
- }
72
- if (name === "pin-kind") {
73
- const kind = TAG_RE.test(flags.ref)
74
- ? "tag"
75
- : COMMIT_INPUT_RE.test(flags.ref)
76
- ? "raw-commit"
77
- : "none";
78
- process.stdout.write(`${kind}\n`);
79
- return;
80
- }
81
- if (name === "safe-source") {
82
- process.stdout.write(`${gitSafeSource(flags.source)}\n`);
83
- return;
84
- }
85
- const unreachable = name;
86
- throw new Error(`unhandled subcommand: ${String(unreachable)}`);
87
- }
88
- export async function runUpstreamCli(argv) {
89
- let command;
90
- try {
91
- command = parseCommand(argv);
92
- }
93
- catch (cause) {
94
- process.stderr.write(`usage: upstream-cli <subcommand> [options]\n`);
95
- process.stderr.write(`error: ${oneLine(cause)}\n`);
96
- return 2;
97
- }
98
- try {
99
- await dispatch(command);
100
- return 0;
101
- }
102
- catch (cause) {
103
- process.stderr.write(`error: ${oneLine(cause)}\n`);
104
- return cause instanceof UsageError ? 2 : 1;
105
- }
106
- }
107
- const entry = process.argv[1];
108
- if (entry !== undefined && import.meta.filename === realpathSync(entry)) {
109
- process.exitCode = await runUpstreamCli(process.argv.slice(2));
110
- }
@@ -1,118 +0,0 @@
1
- import { realpathSync } from "node:fs";
2
- import { oneLine, parseFlags, UsageError } from "./cli-arguments.js";
3
- import { validateGeneratedPlugin, } from "./harnesses/codex/generated-plugin.js";
4
- const FLAGS = [
5
- "plugin-root",
6
- "source",
7
- "requested-ref",
8
- "resolved-ref",
9
- "commit",
10
- "manifest-version",
11
- "manifest-source",
12
- "upstream-manifest-version",
13
- ];
14
- // `argparse` accepts a lone `-` and a bare negative number as a split value;
15
- // every other dash-leading split value is treated as an option and rejected.
16
- // CPython's `_negative_number_matcher` is `^-\d+$|^-\d*\.\d+$`, and `re` `\d` on
17
- // a `str` pattern matches every character in Unicode category Nd. JavaScript
18
- // `\d` is `[0-9]` whatever the flags, so `\p{Nd}` plus `u` is what mirrors it.
19
- // The `\.` stays a literal ASCII period: `argparse` accepts no other separator.
20
- const NEGATIVE_NUMBER_RE = /^-\p{Nd}+$|^-\p{Nd}*\.\p{Nd}+$/u;
21
- /** True when `argparse` would accept `value` in `--flag value` form. */
22
- export function isAcceptedSplitValue(value) {
23
- if (!value.startsWith("-"))
24
- return true;
25
- return value === "-" || NEGATIVE_NUMBER_RE.test(value);
26
- }
27
- /**
28
- * Node replaces an undecodable argv byte with U+FFFD before any JavaScript
29
- * runs, so the original byte is unrecoverable. Rejecting at the boundary is
30
- * the only portable fail-closed option.
31
- */
32
- export function hasReplacementCharacter(value) {
33
- return value.includes("�");
34
- }
35
- /** Pre-scan argv for split-form values the dash rule rejects. */
36
- function findRejectedSplitFlag(argv) {
37
- for (let index = 0; index < argv.length; index += 1) {
38
- const token = argv[index];
39
- if (!token.startsWith("--") || token.includes("="))
40
- continue;
41
- const value = argv[index + 1];
42
- if (value === undefined)
43
- continue;
44
- if (!isAcceptedSplitValue(value))
45
- return token;
46
- index += 1;
47
- }
48
- return undefined;
49
- }
50
- function parseOptions(argv) {
51
- const rejected = findRejectedSplitFlag(argv);
52
- if (rejected !== undefined) {
53
- throw new UsageError(`option ${rejected} rejects a dash-leading value`);
54
- }
55
- const flags = parseFlags(argv, FLAGS);
56
- if (hasReplacementCharacter(flags["plugin-root"])) {
57
- throw new UsageError("option --plugin-root contains an undecodable character");
58
- }
59
- const manifestSource = flags["manifest-source"];
60
- if (manifestSource !== "upstream" && manifestSource !== "fallback") {
61
- throw new UsageError("option --manifest-source must be `upstream` or `fallback`");
62
- }
63
- return {
64
- pluginRoot: flags["plugin-root"],
65
- source: flags.source,
66
- requestedRef: flags["requested-ref"],
67
- resolvedRef: flags["resolved-ref"],
68
- commit: flags.commit,
69
- manifestVersion: flags["manifest-version"],
70
- manifestSource,
71
- upstreamManifestVersion: flags["upstream-manifest-version"],
72
- };
73
- }
74
- export async function runValidateGeneratedPluginCli(argv) {
75
- let options;
76
- try {
77
- options = parseOptions(argv);
78
- }
79
- catch (cause) {
80
- process.stderr.write("usage: validate-generated-plugin-cli --plugin-root <path> --source <url> " +
81
- "--requested-ref <ref> --resolved-ref <ref> --commit <sha> " +
82
- "--manifest-version <version> --manifest-source <upstream|fallback> " +
83
- "--upstream-manifest-version <version>\n");
84
- process.stderr.write(`error: ${oneLine(cause)}\n`);
85
- return 2;
86
- }
87
- let errors;
88
- try {
89
- errors = await validateGeneratedPlugin(options);
90
- }
91
- catch (cause) {
92
- // A rejection must never escape as a traceback-shaped crash.
93
- process.stderr.write(`error: ${oneLine(cause)}\n`);
94
- return 2;
95
- }
96
- if (errors.length > 0) {
97
- process.stderr.write("Generated plugin validation failed:\n");
98
- for (const error of errors)
99
- process.stderr.write(`- ${error}\n`);
100
- return 1;
101
- }
102
- process.stdout.write(`generated plugin validation passed: ${options.pluginRoot}\n`);
103
- return 0;
104
- }
105
- const entry = process.argv[1];
106
- let entryRealpath;
107
- if (entry !== undefined) {
108
- try {
109
- entryRealpath = realpathSync(entry);
110
- }
111
- catch {
112
- // An unresolvable argv[1] means "not the entry point", not a crash.
113
- entryRealpath = undefined;
114
- }
115
- }
116
- if (entryRealpath !== undefined && import.meta.filename === entryRealpath) {
117
- process.exitCode = await runValidateGeneratedPluginCli(process.argv.slice(2));
118
- }