planpong 0.5.4 → 0.5.5
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.
- package/README.md +30 -3
- package/dist/bin/planpong.js +2 -0
- package/dist/bin/planpong.js.map +1 -1
- package/dist/src/cli/commands/config.d.ts +2 -0
- package/dist/src/cli/commands/config.js +89 -0
- package/dist/src/cli/commands/config.js.map +1 -0
- package/dist/src/config/loader.d.ts +5 -0
- package/dist/src/config/loader.js +11 -5
- package/dist/src/config/loader.js.map +1 -1
- package/dist/src/config/mutate.d.ts +15 -0
- package/dist/src/config/mutate.js +112 -0
- package/dist/src/config/mutate.js.map +1 -0
- package/dist/src/mcp/server.js +4 -0
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/get-config.d.ts +2 -0
- package/dist/src/mcp/tools/get-config.js +75 -0
- package/dist/src/mcp/tools/get-config.js.map +1 -0
- package/dist/src/mcp/tools/set-config.d.ts +2 -0
- package/dist/src/mcp/tools/set-config.js +81 -0
- package/dist/src/mcp/tools/set-config.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,18 +86,45 @@ Optional. Create `planpong.yaml` in your project root:
|
|
|
86
86
|
```yaml
|
|
87
87
|
planner:
|
|
88
88
|
provider: claude # claude or codex
|
|
89
|
-
model: opus # provider-specific model name
|
|
89
|
+
model: claude-opus-4-6 # provider-specific model name
|
|
90
90
|
effort: high # reasoning effort level
|
|
91
91
|
reviewer:
|
|
92
92
|
provider: codex
|
|
93
|
-
model:
|
|
94
|
-
effort:
|
|
93
|
+
model: gpt-5.3-codex
|
|
94
|
+
effort: xhigh
|
|
95
95
|
max_rounds: 10
|
|
96
96
|
plans_dir: docs/plans
|
|
97
|
+
revision_mode: full # full or edits
|
|
98
|
+
planner_mode: external # external or inline
|
|
97
99
|
```
|
|
98
100
|
|
|
99
101
|
All fields are optional. Defaults: claude (planner) + codex (reviewer), 10 rounds, `docs/plans/` directory.
|
|
100
102
|
|
|
103
|
+
### Viewing and changing config
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
planpong config # show resolved config with source annotations
|
|
107
|
+
planpong config path # print path to active config file
|
|
108
|
+
planpong config set <key> <value> # set a config value
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Examples:
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
planpong config set reviewer.model gpt-5.3-codex
|
|
115
|
+
planpong config set max_rounds 5
|
|
116
|
+
planpong config set planner_mode inline
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Valid keys: `planner.provider`, `planner.model`, `planner.effort`, `reviewer.provider`, `reviewer.model`, `reviewer.effort`, `plans_dir`, `max_rounds`, `human_in_loop`, `revision_mode`, `planner_mode`.
|
|
120
|
+
|
|
121
|
+
### Config via MCP
|
|
122
|
+
|
|
123
|
+
Two MCP tools are available for programmatic config access:
|
|
124
|
+
|
|
125
|
+
- **`planpong_get_config`** — returns resolved config, file path, version, and per-key source provenance
|
|
126
|
+
- **`planpong_set_config`** — dry-run by default (`confirm: false`); pass `confirm: true` to write
|
|
127
|
+
|
|
101
128
|
## What it produces
|
|
102
129
|
|
|
103
130
|
Planpong updates your plan file in-place and adds a status line tracking the review:
|
package/dist/bin/planpong.js
CHANGED
|
@@ -5,6 +5,7 @@ import { dirname, join } from "node:path";
|
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
import { registerPlanCommand } from "../src/cli/commands/plan.js";
|
|
7
7
|
import { registerReviewCommand } from "../src/cli/commands/review.js";
|
|
8
|
+
import { registerConfigCommand } from "../src/cli/commands/config.js";
|
|
8
9
|
// Read version from the installed package.json so `planpong --version`
|
|
9
10
|
// always reflects the actual installed version. Hardcoding it here
|
|
10
11
|
// drifts every time we cut a release.
|
|
@@ -45,5 +46,6 @@ program
|
|
|
45
46
|
.version(readPackageVersion());
|
|
46
47
|
registerPlanCommand(program);
|
|
47
48
|
registerReviewCommand(program);
|
|
49
|
+
registerConfigCommand(program);
|
|
48
50
|
program.parse();
|
|
49
51
|
//# sourceMappingURL=planpong.js.map
|
package/dist/bin/planpong.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planpong.js","sourceRoot":"","sources":["../../bin/planpong.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,uEAAuE;AACvE,mEAAmE;AACnE,sCAAsC;AACtC,EAAE;AACF,wEAAwE;AACxE,mEAAmE;AACnE,sEAAsE;AACtE,8BAA8B;AAC9B,SAAS,kBAAkB;IACzB,IAAI,CAAC;QACH,IAAI,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;YAC7C,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAGtD,CAAC;gBACF,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;oBAC/D,OAAO,GAAG,CAAC,OAAO,CAAC;gBACrB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,8DAA8D;YAChE,CAAC;YACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,MAAM,KAAK,IAAI;gBAAE,MAAM;YAC3B,IAAI,GAAG,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;IAC7B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CACV,sFAAsF,CACvF;KACA,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEjC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAE/B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"planpong.js","sourceRoot":"","sources":["../../bin/planpong.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,uEAAuE;AACvE,mEAAmE;AACnE,sCAAsC;AACtC,EAAE;AACF,wEAAwE;AACxE,mEAAmE;AACnE,sEAAsE;AACtE,8BAA8B;AAC9B,SAAS,kBAAkB;IACzB,IAAI,CAAC;QACH,IAAI,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;YAC7C,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAGtD,CAAC;gBACF,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;oBAC/D,OAAO,GAAG,CAAC,OAAO,CAAC;gBACrB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,8DAA8D;YAChE,CAAC;YACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,MAAM,KAAK,IAAI;gBAAE,MAAM;YAC3B,IAAI,GAAG,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;IAC7B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CACV,sFAAsF,CACvF;KACA,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEjC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAE/B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { parse as parseYaml } from "yaml";
|
|
3
|
+
import { loadConfig, findConfigPath } from "../../config/loader.js";
|
|
4
|
+
import { setConfigValue, getValidKeys } from "../../config/mutate.js";
|
|
5
|
+
export function registerConfigCommand(program) {
|
|
6
|
+
const configCmd = program
|
|
7
|
+
.command("config")
|
|
8
|
+
.description("View or modify planpong configuration");
|
|
9
|
+
configCmd
|
|
10
|
+
.command("path")
|
|
11
|
+
.description("Print the path to the active config file")
|
|
12
|
+
.action(() => {
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const path = findConfigPath(cwd);
|
|
15
|
+
if (path) {
|
|
16
|
+
console.log(path);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
console.log("No config file found");
|
|
20
|
+
process.exitCode = 1;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
configCmd
|
|
24
|
+
.command("set")
|
|
25
|
+
.description("Set a config value")
|
|
26
|
+
.argument("<key>", `Dotted config key (${getValidKeys().join(", ")})`)
|
|
27
|
+
.argument("<value>", "Value to set")
|
|
28
|
+
.action((key, value) => {
|
|
29
|
+
const cwd = process.cwd();
|
|
30
|
+
try {
|
|
31
|
+
const result = setConfigValue(cwd, key, value);
|
|
32
|
+
console.log(`${result.created ? "Created" : "Updated"} ${result.configPath}`);
|
|
33
|
+
console.log(` ${key}: ${String(result.before ?? "(unset)")} → ${String(result.after)}`);
|
|
34
|
+
// Check for shadow warnings
|
|
35
|
+
const effective = loadConfig({ cwd });
|
|
36
|
+
const parts = key.split(".");
|
|
37
|
+
let effectiveVal;
|
|
38
|
+
if (parts.length === 1) {
|
|
39
|
+
effectiveVal = effective[parts[0]];
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
effectiveVal = effective[parts[0]]?.[parts[1]];
|
|
43
|
+
}
|
|
44
|
+
if (String(effectiveVal) !== String(result.after)) {
|
|
45
|
+
console.log(`\n Warning: effective value is "${String(effectiveVal)}" (overridden by CLI flag)`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
console.error(`Error: ${err.message}`);
|
|
50
|
+
process.exitCode = 1;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
// Default action: show resolved config with source annotations
|
|
54
|
+
configCmd.action(() => {
|
|
55
|
+
const cwd = process.cwd();
|
|
56
|
+
const configPath = findConfigPath(cwd);
|
|
57
|
+
const resolved = loadConfig({ cwd });
|
|
58
|
+
if (configPath) {
|
|
59
|
+
console.log(`# Config file: ${configPath}`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.log("# No config file found (using defaults)");
|
|
63
|
+
}
|
|
64
|
+
console.log();
|
|
65
|
+
// Load file config for source detection
|
|
66
|
+
let fileConfig = {};
|
|
67
|
+
if (configPath) {
|
|
68
|
+
fileConfig = parseYaml(readFileSync(configPath, "utf-8")) ?? {};
|
|
69
|
+
}
|
|
70
|
+
// Print each key with source annotation
|
|
71
|
+
for (const key of getValidKeys()) {
|
|
72
|
+
const parts = key.split(".");
|
|
73
|
+
let fileVal;
|
|
74
|
+
let resolvedVal;
|
|
75
|
+
if (parts.length === 1) {
|
|
76
|
+
fileVal = fileConfig[parts[0]];
|
|
77
|
+
resolvedVal = resolved[parts[0]];
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
fileVal = fileConfig[parts[0]]?.[parts[1]];
|
|
81
|
+
resolvedVal = resolved[parts[0]]?.[parts[1]];
|
|
82
|
+
}
|
|
83
|
+
const source = fileVal !== undefined ? "file" : "default";
|
|
84
|
+
const displayVal = resolvedVal === undefined ? "(unset)" : String(resolvedVal);
|
|
85
|
+
console.log(` ${key}: ${displayVal} (${source})`);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../src/cli/commands/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { type PlanpongConfig } from "../schemas/config.js";
|
|
2
|
+
/**
|
|
3
|
+
* Search upward from `cwd` for a config file path.
|
|
4
|
+
* Returns the absolute path or null if no file is found.
|
|
5
|
+
*/
|
|
6
|
+
export declare function findConfigPath(cwd: string): string | null;
|
|
2
7
|
export interface LoadConfigOptions {
|
|
3
8
|
cwd: string;
|
|
4
9
|
/** CLI overrides — sparse, merged on top of file + defaults */
|
|
@@ -10,18 +10,17 @@ const CONFIG_FILENAMES = [
|
|
|
10
10
|
".planpong.yml",
|
|
11
11
|
];
|
|
12
12
|
/**
|
|
13
|
-
* Search upward from `cwd` for a config file.
|
|
14
|
-
*
|
|
13
|
+
* Search upward from `cwd` for a config file path.
|
|
14
|
+
* Returns the absolute path or null if no file is found.
|
|
15
15
|
*/
|
|
16
|
-
function
|
|
16
|
+
export function findConfigPath(cwd) {
|
|
17
17
|
let dir = cwd;
|
|
18
18
|
const root = "/";
|
|
19
19
|
while (true) {
|
|
20
20
|
for (const filename of CONFIG_FILENAMES) {
|
|
21
21
|
const candidate = join(dir, filename);
|
|
22
22
|
if (existsSync(candidate)) {
|
|
23
|
-
|
|
24
|
-
return parseYaml(raw);
|
|
23
|
+
return candidate;
|
|
25
24
|
}
|
|
26
25
|
}
|
|
27
26
|
const parent = join(dir, "..");
|
|
@@ -31,6 +30,13 @@ function findConfigFile(cwd) {
|
|
|
31
30
|
}
|
|
32
31
|
return null;
|
|
33
32
|
}
|
|
33
|
+
function findConfigFile(cwd) {
|
|
34
|
+
const path = findConfigPath(cwd);
|
|
35
|
+
if (!path)
|
|
36
|
+
return null;
|
|
37
|
+
const raw = readFileSync(path, "utf-8");
|
|
38
|
+
return parseYaml(raw);
|
|
39
|
+
}
|
|
34
40
|
export function loadConfig(options) {
|
|
35
41
|
const fileConfig = findConfigFile(options.cwd) ?? {};
|
|
36
42
|
const overrides = options.overrides ?? {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EACL,oBAAoB,GAErB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,gBAAgB,GAAG;IACvB,eAAe;IACf,cAAc;IACd,gBAAgB;IAChB,eAAe;CAChB,CAAC;AAEF;;;GAGG;AACH,
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/config/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare const VALID_KEYS: readonly ["planner.provider", "planner.model", "planner.effort", "reviewer.provider", "reviewer.model", "reviewer.effort", "plans_dir", "max_rounds", "human_in_loop", "revision_mode", "planner_mode"];
|
|
2
|
+
export type ValidKey = (typeof VALID_KEYS)[number];
|
|
3
|
+
export interface SetConfigResult {
|
|
4
|
+
configPath: string;
|
|
5
|
+
key: string;
|
|
6
|
+
before: unknown;
|
|
7
|
+
after: unknown;
|
|
8
|
+
created: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function isValidKey(key: string): key is ValidKey;
|
|
11
|
+
export declare function getValidKeys(): readonly string[];
|
|
12
|
+
export declare function setConfigValue(cwd: string, key: string, rawValue: string, opts?: {
|
|
13
|
+
dryRun?: boolean;
|
|
14
|
+
}): SetConfigResult;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, renameSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parseDocument } from "yaml";
|
|
4
|
+
import { ZodError } from "zod";
|
|
5
|
+
import { PlanpongConfigSchema } from "../schemas/config.js";
|
|
6
|
+
import { findConfigPath } from "./loader.js";
|
|
7
|
+
import { loadConfig } from "./loader.js";
|
|
8
|
+
const VALID_KEYS = [
|
|
9
|
+
"planner.provider",
|
|
10
|
+
"planner.model",
|
|
11
|
+
"planner.effort",
|
|
12
|
+
"reviewer.provider",
|
|
13
|
+
"reviewer.model",
|
|
14
|
+
"reviewer.effort",
|
|
15
|
+
"plans_dir",
|
|
16
|
+
"max_rounds",
|
|
17
|
+
"human_in_loop",
|
|
18
|
+
"revision_mode",
|
|
19
|
+
"planner_mode",
|
|
20
|
+
];
|
|
21
|
+
export function isValidKey(key) {
|
|
22
|
+
return VALID_KEYS.includes(key);
|
|
23
|
+
}
|
|
24
|
+
export function getValidKeys() {
|
|
25
|
+
return VALID_KEYS;
|
|
26
|
+
}
|
|
27
|
+
function coerceValue(key, raw) {
|
|
28
|
+
if (key === "max_rounds") {
|
|
29
|
+
const n = Number(raw);
|
|
30
|
+
if (Number.isNaN(n))
|
|
31
|
+
throw new Error(`Invalid number for ${key}: ${raw}`);
|
|
32
|
+
return n;
|
|
33
|
+
}
|
|
34
|
+
if (key === "human_in_loop") {
|
|
35
|
+
if (raw === "true")
|
|
36
|
+
return true;
|
|
37
|
+
if (raw === "false")
|
|
38
|
+
return false;
|
|
39
|
+
throw new Error(`Invalid boolean for ${key}: ${raw} (expected "true" or "false")`);
|
|
40
|
+
}
|
|
41
|
+
return raw;
|
|
42
|
+
}
|
|
43
|
+
function getNestedValue(obj, key) {
|
|
44
|
+
const parts = key.split(".");
|
|
45
|
+
let current = obj;
|
|
46
|
+
for (const part of parts) {
|
|
47
|
+
if (current == null || typeof current !== "object")
|
|
48
|
+
return undefined;
|
|
49
|
+
current = current[part];
|
|
50
|
+
}
|
|
51
|
+
return current;
|
|
52
|
+
}
|
|
53
|
+
export function setConfigValue(cwd, key, rawValue, opts) {
|
|
54
|
+
if (!isValidKey(key)) {
|
|
55
|
+
throw new Error(`Unknown config key: "${key}". Valid keys: ${VALID_KEYS.join(", ")}`);
|
|
56
|
+
}
|
|
57
|
+
const value = coerceValue(key, rawValue);
|
|
58
|
+
const existingPath = findConfigPath(cwd);
|
|
59
|
+
const configPath = existingPath ?? join(cwd, "planpong.yaml");
|
|
60
|
+
const created = !existingPath;
|
|
61
|
+
const raw = existingPath ? readFileSync(existingPath, "utf-8") : "";
|
|
62
|
+
const doc = parseDocument(raw);
|
|
63
|
+
const parts = key.split(".");
|
|
64
|
+
const before = getNestedValue(doc.toJSON() ?? {}, key);
|
|
65
|
+
if (parts.length === 1) {
|
|
66
|
+
doc.set(parts[0], value);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
let node = doc.get(parts[0], true);
|
|
70
|
+
if (node == null || typeof node !== "object" || !("set" in node)) {
|
|
71
|
+
doc.set(parts[0], { [parts[1]]: value });
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
node.set(parts[1], value);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Validate the full merged config would be valid
|
|
78
|
+
const merged = doc.toJSON();
|
|
79
|
+
const testConfig = { ...loadConfig({ cwd }).valueOf() };
|
|
80
|
+
if (parts.length === 1) {
|
|
81
|
+
testConfig[parts[0]] = value;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const section = testConfig[parts[0]] ?? {};
|
|
85
|
+
section[parts[1]] = value;
|
|
86
|
+
testConfig[parts[0]] = section;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
PlanpongConfigSchema.parse(testConfig);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
if (err instanceof ZodError) {
|
|
93
|
+
const msg = err.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
94
|
+
throw new Error(`Invalid value for "${key}": ${msg}`);
|
|
95
|
+
}
|
|
96
|
+
throw err;
|
|
97
|
+
}
|
|
98
|
+
if (!opts?.dryRun) {
|
|
99
|
+
const output = doc.toString();
|
|
100
|
+
const tmpPath = configPath + ".tmp." + process.pid;
|
|
101
|
+
writeFileSync(tmpPath, output, "utf-8");
|
|
102
|
+
renameSync(tmpPath, configPath);
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
configPath,
|
|
106
|
+
key,
|
|
107
|
+
before,
|
|
108
|
+
after: value,
|
|
109
|
+
created,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=mutate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutate.js","sourceRoot":"","sources":["../../../src/config/mutate.ts"],"names":[],"mappings":"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"}
|
package/dist/src/mcp/server.js
CHANGED
|
@@ -7,6 +7,8 @@ import { registerRecordRevision } from "./tools/record-revision.js";
|
|
|
7
7
|
import { registerStatus } from "./tools/status.js";
|
|
8
8
|
import { registerListSessions } from "./tools/list-sessions.js";
|
|
9
9
|
import { registerGetReport } from "./tools/get-report.js";
|
|
10
|
+
import { registerGetConfig } from "./tools/get-config.js";
|
|
11
|
+
import { registerSetConfig } from "./tools/set-config.js";
|
|
10
12
|
export function createPlanpongServer() {
|
|
11
13
|
const server = new McpServer({
|
|
12
14
|
name: "planpong",
|
|
@@ -52,6 +54,8 @@ Phase-specific feedback:
|
|
|
52
54
|
registerStatus(server);
|
|
53
55
|
registerListSessions(server);
|
|
54
56
|
registerGetReport(server);
|
|
57
|
+
registerGetConfig(server);
|
|
58
|
+
registerSetConfig(server);
|
|
55
59
|
// MCP prompts — become slash commands in Claude Code
|
|
56
60
|
server.registerPrompt("review", {
|
|
57
61
|
title: "Review a plan",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { parse as parseYaml } from "yaml";
|
|
6
|
+
import { loadConfig, findConfigPath } from "../../config/loader.js";
|
|
7
|
+
import { getValidKeys } from "../../config/mutate.js";
|
|
8
|
+
const inputSchema = {
|
|
9
|
+
cwd: z
|
|
10
|
+
.string()
|
|
11
|
+
.optional()
|
|
12
|
+
.describe("Working directory (defaults to process.cwd())"),
|
|
13
|
+
};
|
|
14
|
+
export function registerGetConfig(server) {
|
|
15
|
+
server.tool("planpong_get_config", "Get the resolved planpong configuration, including config file path, per-key source provenance, and version.", inputSchema, async (input) => {
|
|
16
|
+
const cwd = input.cwd ?? process.cwd();
|
|
17
|
+
const configPath = findConfigPath(cwd);
|
|
18
|
+
const resolved = loadConfig({ cwd });
|
|
19
|
+
// Load file config for source detection
|
|
20
|
+
let fileConfig = {};
|
|
21
|
+
if (configPath) {
|
|
22
|
+
fileConfig =
|
|
23
|
+
parseYaml(readFileSync(configPath, "utf-8")) ?? {};
|
|
24
|
+
}
|
|
25
|
+
// Build sources map
|
|
26
|
+
const sources = {};
|
|
27
|
+
for (const key of getValidKeys()) {
|
|
28
|
+
const parts = key.split(".");
|
|
29
|
+
let fileVal;
|
|
30
|
+
if (parts.length === 1) {
|
|
31
|
+
fileVal = fileConfig[parts[0]];
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
fileVal = fileConfig[parts[0]]?.[parts[1]];
|
|
35
|
+
}
|
|
36
|
+
sources[key] = fileVal !== undefined ? "file" : "default";
|
|
37
|
+
}
|
|
38
|
+
// Read version from package.json
|
|
39
|
+
let version = "unknown";
|
|
40
|
+
try {
|
|
41
|
+
let here = dirname(fileURLToPath(import.meta.url));
|
|
42
|
+
for (let i = 0; i < 5; i++) {
|
|
43
|
+
const candidate = join(here, "package.json");
|
|
44
|
+
try {
|
|
45
|
+
const pkg = JSON.parse(readFileSync(candidate, "utf-8"));
|
|
46
|
+
if (pkg.name === "planpong" && pkg.version) {
|
|
47
|
+
version = pkg.version;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// keep walking
|
|
53
|
+
}
|
|
54
|
+
here = dirname(here);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// fallback
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
63
|
+
type: "text",
|
|
64
|
+
text: JSON.stringify({
|
|
65
|
+
config: resolved,
|
|
66
|
+
config_path: configPath,
|
|
67
|
+
version,
|
|
68
|
+
sources,
|
|
69
|
+
}),
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=get-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-config.js","sourceRoot":"","sources":["../../../../src/mcp/tools/get-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { loadConfig } from "../../config/loader.js";
|
|
3
|
+
import { setConfigValue, getValidKeys } from "../../config/mutate.js";
|
|
4
|
+
const inputSchema = {
|
|
5
|
+
cwd: z
|
|
6
|
+
.string()
|
|
7
|
+
.optional()
|
|
8
|
+
.describe("Working directory (defaults to process.cwd())"),
|
|
9
|
+
key: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe(`Dotted config key. Valid keys: ${getValidKeys().join(", ")}`),
|
|
12
|
+
value: z
|
|
13
|
+
.string()
|
|
14
|
+
.describe("Value to set (coerced to number/boolean as schema requires)"),
|
|
15
|
+
confirm: z
|
|
16
|
+
.boolean()
|
|
17
|
+
.default(false)
|
|
18
|
+
.describe("If false (default), dry-run: returns what would change without writing. If true, performs the write."),
|
|
19
|
+
};
|
|
20
|
+
export function registerSetConfig(server) {
|
|
21
|
+
server.tool("planpong_set_config", "Set a planpong configuration value. Dry-run by default (confirm: false); pass confirm: true to write.", inputSchema, async (input) => {
|
|
22
|
+
const cwd = input.cwd ?? process.cwd();
|
|
23
|
+
try {
|
|
24
|
+
const result = setConfigValue(cwd, input.key, input.value, {
|
|
25
|
+
dryRun: !input.confirm,
|
|
26
|
+
});
|
|
27
|
+
// Check for shadow warnings
|
|
28
|
+
let shadowWarning;
|
|
29
|
+
if (input.confirm) {
|
|
30
|
+
const effective = loadConfig({ cwd });
|
|
31
|
+
const parts = input.key.split(".");
|
|
32
|
+
let effectiveVal;
|
|
33
|
+
if (parts.length === 1) {
|
|
34
|
+
effectiveVal = effective[parts[0]];
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
effectiveVal = effective[parts[0]]?.[parts[1]];
|
|
38
|
+
}
|
|
39
|
+
if (String(effectiveVal) !== String(result.after)) {
|
|
40
|
+
shadowWarning = `Effective value is "${String(effectiveVal)}" — a CLI override takes precedence over the file value.`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const response = {
|
|
44
|
+
mode: input.confirm ? "applied" : "dry_run",
|
|
45
|
+
config_path: result.configPath,
|
|
46
|
+
key: result.key,
|
|
47
|
+
before: result.before ?? null,
|
|
48
|
+
after: result.after,
|
|
49
|
+
created: result.created,
|
|
50
|
+
};
|
|
51
|
+
if (shadowWarning) {
|
|
52
|
+
response.shadow_warning = shadowWarning;
|
|
53
|
+
}
|
|
54
|
+
if (input.confirm) {
|
|
55
|
+
response.resolved_config = loadConfig({ cwd });
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
content: [
|
|
59
|
+
{
|
|
60
|
+
type: "text",
|
|
61
|
+
text: JSON.stringify(response),
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
return {
|
|
68
|
+
content: [
|
|
69
|
+
{
|
|
70
|
+
type: "text",
|
|
71
|
+
text: JSON.stringify({
|
|
72
|
+
error: err.message,
|
|
73
|
+
}),
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
isError: true,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=set-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-config.js","sourceRoot":"","sources":["../../../../src/mcp/tools/set-config.ts"],"names":[],"mappings":"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"}
|