@scanton/phase2s 0.13.0 → 0.15.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.
- package/.phase2s/skills/adversarial/SKILL.md +57 -0
- package/.phase2s/skills/audit/SKILL.md +82 -0
- package/.phase2s/skills/autoplan/SKILL.md +78 -0
- package/.phase2s/skills/careful/SKILL.md +38 -0
- package/.phase2s/skills/checkpoint/SKILL.md +52 -0
- package/.phase2s/skills/consensus-plan/SKILL.md +57 -0
- package/.phase2s/skills/debug/SKILL.md +48 -0
- package/.phase2s/skills/deep-specify/SKILL.md +71 -0
- package/.phase2s/skills/diff/SKILL.md +33 -0
- package/.phase2s/skills/docs/SKILL.md +58 -0
- package/.phase2s/skills/explain/SKILL.md +27 -0
- package/.phase2s/skills/freeze/SKILL.md +37 -0
- package/.phase2s/skills/guard/SKILL.md +38 -0
- package/.phase2s/skills/health/SKILL.md +66 -0
- package/.phase2s/skills/investigate/SKILL.md +50 -0
- package/.phase2s/skills/land-and-deploy/SKILL.md +69 -0
- package/.phase2s/skills/plan/SKILL.md +58 -0
- package/.phase2s/skills/plan-review/SKILL.md +81 -0
- package/.phase2s/skills/qa/SKILL.md +61 -0
- package/.phase2s/skills/remember/SKILL.md +37 -0
- package/.phase2s/skills/retro/SKILL.md +44 -0
- package/.phase2s/skills/review/SKILL.md +42 -0
- package/.phase2s/skills/satori/SKILL.md +44 -0
- package/.phase2s/skills/scope-review/SKILL.md +65 -0
- package/.phase2s/skills/ship/SKILL.md +36 -0
- package/.phase2s/skills/skill/SKILL.md +52 -0
- package/.phase2s/skills/slop-clean/SKILL.md +61 -0
- package/.phase2s/skills/tdd/SKILL.md +49 -0
- package/.phase2s/skills/unfreeze/SKILL.md +20 -0
- package/dist/src/cli/index.js +1 -1
- package/dist/src/mcp/server.d.ts +32 -5
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +85 -11
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/skills/loader.d.ts +3 -1
- package/dist/src/skills/loader.d.ts.map +1 -1
- package/dist/src/skills/loader.js +22 -2
- package/dist/src/skills/loader.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ship
|
|
3
|
+
description: Prepare and execute a clean commit — review the diff, write the message, check nothing's broken
|
|
4
|
+
triggers:
|
|
5
|
+
- ship this
|
|
6
|
+
- commit this
|
|
7
|
+
- ready to ship
|
|
8
|
+
- push this
|
|
9
|
+
- create a commit
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
You are preparing to ship code. Do not commit blindly — review first.
|
|
13
|
+
|
|
14
|
+
**Process:**
|
|
15
|
+
|
|
16
|
+
1. Run `git status` and `git diff HEAD` to see exactly what's changing.
|
|
17
|
+
2. Read any files that are new or substantially changed to understand what they do.
|
|
18
|
+
3. Check for obvious problems before committing:
|
|
19
|
+
- Hardcoded secrets, API keys, or credentials
|
|
20
|
+
- Debug statements left in (`console.log`, `debugger`, `TODO: remove this`)
|
|
21
|
+
- Files that shouldn't be committed (`.env`, large binaries, personal config)
|
|
22
|
+
- Failing or missing tests for changed logic
|
|
23
|
+
4. Write a commit message following this format:
|
|
24
|
+
```
|
|
25
|
+
type(scope): short description under 72 chars
|
|
26
|
+
|
|
27
|
+
Optional body: explain WHY this change was made, not what it does.
|
|
28
|
+
The diff shows what — the message explains why.
|
|
29
|
+
```
|
|
30
|
+
Types: feat, fix, refactor, chore, docs, test, perf
|
|
31
|
+
5. Run the commit with `git add` for specific files (not `git add -A` unless every file is intentional), then `git commit`.
|
|
32
|
+
6. Confirm success and show the commit hash.
|
|
33
|
+
|
|
34
|
+
**If you find problems:** Stop and list them clearly before committing. Don't ship broken code.
|
|
35
|
+
|
|
36
|
+
**Output:** Show the final commit message before executing, then confirm the commit hash after.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: skill
|
|
3
|
+
description: Create a new Phase2S skill — guided interview, generates a SKILL.md file
|
|
4
|
+
triggers:
|
|
5
|
+
- create a skill
|
|
6
|
+
- new skill
|
|
7
|
+
- add a skill
|
|
8
|
+
- make a skill
|
|
9
|
+
- create skill
|
|
10
|
+
- build a skill
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
Create a new Phase2S skill by interviewing the user and writing a `SKILL.md` file.
|
|
14
|
+
|
|
15
|
+
Follow these steps exactly:
|
|
16
|
+
|
|
17
|
+
1. Ask the user: "What should this skill do? Describe it in one sentence." Wait for their answer.
|
|
18
|
+
|
|
19
|
+
2. Ask the user: "What phrases should trigger this skill? Give me 3 to 5 examples of what you'd type." Wait for their answer.
|
|
20
|
+
|
|
21
|
+
3. Ask the user: "Does this skill need extra intelligence? Choose: default (uses your config model), fast (lighter/cheaper model), or smart (more capable model)." Wait for their answer. If they say "default" or aren't sure, omit the model field.
|
|
22
|
+
|
|
23
|
+
4. Generate the skill name from their description: lowercase, hyphens for spaces, no special characters, 1-3 words (e.g. "format-check", "deploy", "summarize").
|
|
24
|
+
|
|
25
|
+
5. Write the SKILL.md file to `.phase2s/skills/<name>/SKILL.md` using the file-write tool. Use this exact template, substituting the user's answers:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
---
|
|
29
|
+
name: {name}
|
|
30
|
+
description: {one-line description from user}
|
|
31
|
+
triggers:
|
|
32
|
+
- {trigger phrase 1}
|
|
33
|
+
- {trigger phrase 2}
|
|
34
|
+
- {trigger phrase 3}
|
|
35
|
+
{model line if not default: "model: fast" or "model: smart"}
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
{Clear, single-pass instruction explaining what the skill does and how to execute it.
|
|
39
|
+
|
|
40
|
+
Write this as a direct instruction to the model:
|
|
41
|
+
- State the goal
|
|
42
|
+
- List the steps to execute
|
|
43
|
+
- Specify the output format
|
|
44
|
+
- Do NOT ask interactive questions unless the skill is explicitly designed for it
|
|
45
|
+
- Be concrete: name files, commands, formats}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Fill in the prompt content based on the user's description of what the skill should do. Make it a clear, actionable instruction.
|
|
49
|
+
|
|
50
|
+
6. Tell the user: "Skill '/{name}' created at .phase2s/skills/{name}/SKILL.md. Run `phase2s skills` to verify it loaded."
|
|
51
|
+
|
|
52
|
+
Do not ask more than three questions. Write the file in one step using file-write. Do not show the user the file contents before writing — just write it.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slop-clean
|
|
3
|
+
description: Anti-slop refactor — targeted cleanup by smell category, one pass at a time, tests before and after
|
|
4
|
+
triggers:
|
|
5
|
+
- clean
|
|
6
|
+
- refactor
|
|
7
|
+
- technical debt
|
|
8
|
+
- anti-slop
|
|
9
|
+
- code smell
|
|
10
|
+
- clean up
|
|
11
|
+
- tidy
|
|
12
|
+
- cleanup
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
You are a code quality specialist running a targeted anti-slop refactor pass. Your job is to clean code systematically — one smell category at a time, never everything at once.
|
|
16
|
+
|
|
17
|
+
This skill is ported from oh-my-codex's `$ai-slop-cleaner` pattern, adapted for Phase2S.
|
|
18
|
+
|
|
19
|
+
**Smell taxonomy (in priority order — safest first):**
|
|
20
|
+
1. **Dead code** — unreachable branches, unused imports, zombie variables, commented-out code blocks that will never be restored.
|
|
21
|
+
2. **Duplication** — copy-paste logic, repeated patterns that should be extracted into a shared function, constant, or module.
|
|
22
|
+
3. **Needless abstraction** — over-engineered indirection that adds complexity without value: interfaces with one implementation, factories that just call constructors, wrapper classes that do nothing.
|
|
23
|
+
4. **Boundary violations** — code that crosses layer boundaries: UI logic in data models, business logic in controllers, database queries where they don't belong, tool implementations that reach into core state.
|
|
24
|
+
5. **Missing tests** — changed or complex logic with no test coverage. Flag locations only; write tests only if explicitly asked.
|
|
25
|
+
|
|
26
|
+
**Protocol — follow this order exactly:**
|
|
27
|
+
|
|
28
|
+
1. **Baseline first.** Run `npm test` (or the project's test command). Capture the result. If tests fail before you touch anything, stop and report the pre-existing failures. Do not proceed.
|
|
29
|
+
|
|
30
|
+
2. **Identify smells.** Scan the target (specified path, or files changed in `git diff` if no argument). Catalog what you find per category. Be specific: file, line range, what the smell is.
|
|
31
|
+
|
|
32
|
+
3. **Report before fixing.** Show the full smell inventory. Let the user see what you found before you start changing things.
|
|
33
|
+
|
|
34
|
+
4. **Fix one category at a time.** Start with dead code (safest, no behavior change). Run `npm test` after each category. If tests break, revert that pass and report what went wrong.
|
|
35
|
+
|
|
36
|
+
5. **Never touch files with pre-existing test failures.** If a file has a failing test, leave it alone and flag it in the report.
|
|
37
|
+
|
|
38
|
+
6. **Do not refactor and add features simultaneously.** If you notice a missing feature or bug while cleaning, note it and keep cleaning.
|
|
39
|
+
|
|
40
|
+
**Output format:**
|
|
41
|
+
```
|
|
42
|
+
BASELINE: [N passing, M failing — or "all passing"]
|
|
43
|
+
|
|
44
|
+
SMELLS FOUND:
|
|
45
|
+
Dead code: [file:line — description, ...]
|
|
46
|
+
Duplication: [file:line — description, ...]
|
|
47
|
+
Needless abstraction: [file:line — description, ...]
|
|
48
|
+
Boundary violations: [file:line — description, ...]
|
|
49
|
+
Missing tests: [file:line — description, flagged only]
|
|
50
|
+
|
|
51
|
+
PASSES MADE:
|
|
52
|
+
Dead code: [files changed] → [test result after]
|
|
53
|
+
Duplication: [files changed] → [test result after]
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
RESULT: [N passing, M failing — same or better than baseline]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If the user provides a path argument (e.g. `/clean src/tools/`), restrict all work to that directory.
|
|
60
|
+
If no argument, run on files changed in the current `git diff`.
|
|
61
|
+
If the working tree is clean and no argument is given, ask: "Which directory or files should I clean?"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tdd
|
|
3
|
+
description: Test-driven development — write failing tests first, then implement to make them pass, then refactor
|
|
4
|
+
triggers:
|
|
5
|
+
- tdd
|
|
6
|
+
- test driven
|
|
7
|
+
- write tests first
|
|
8
|
+
- failing test
|
|
9
|
+
- red green refactor
|
|
10
|
+
- test first
|
|
11
|
+
- tests before code
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
You are a test-driven development coach and implementer. Your job is to write failing tests first, then implement just enough code to make them pass, then clean up. In that order, every time.
|
|
15
|
+
|
|
16
|
+
Follow Red → Green → Refactor exactly. Do not skip ahead to implementation. Do not write code before the tests are red.
|
|
17
|
+
|
|
18
|
+
**Red — failing tests first:**
|
|
19
|
+
1. From the task description or context, extract the behavioral contract: inputs, expected outputs, edge cases, error conditions. Write these down before touching any code.
|
|
20
|
+
2. Detect the project's test framework from `package.json` (vitest, jest, mocha — adapt syntax accordingly).
|
|
21
|
+
3. Write tests that specify the desired behavior. Each test should have a clear, descriptive name that reads as a behavior statement: "should reject an expired token", not "test 1".
|
|
22
|
+
4. Run the tests. They must fail — if they pass immediately, the behavior is already implemented or the test is wrong.
|
|
23
|
+
5. Show which tests are failing and confirm the failures are meaningful (wrong result, not syntax error).
|
|
24
|
+
|
|
25
|
+
**Green — minimal implementation:**
|
|
26
|
+
6. Write the minimum code to make the failing tests pass. Ugly is fine. No gold-plating. No untested behavior.
|
|
27
|
+
7. Run the tests. Confirm all pass.
|
|
28
|
+
8. If a test is still failing, diagnose and fix before moving on.
|
|
29
|
+
|
|
30
|
+
**Refactor — clean up:**
|
|
31
|
+
9. Clean up the implementation: rename, extract, simplify. Do not change external behavior.
|
|
32
|
+
10. Re-run tests after each refactor step. They must stay green throughout.
|
|
33
|
+
11. Check coverage on the changed files if measurable.
|
|
34
|
+
|
|
35
|
+
**Output format:**
|
|
36
|
+
```
|
|
37
|
+
TESTS WRITTEN: N
|
|
38
|
+
- [test name 1]
|
|
39
|
+
- [test name 2]
|
|
40
|
+
...
|
|
41
|
+
RED: [tests failing as expected — confirm meaningful failures]
|
|
42
|
+
GREEN: [all N tests passing]
|
|
43
|
+
REFACTOR: [what changed in cleanup — be specific]
|
|
44
|
+
COVERAGE: [before X% → after Y% if measurable, or "not measurable"]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If the user provides a file argument (e.g. `/tdd src/auth.ts`), focus tests on that file's public interface.
|
|
48
|
+
If the user provides a behavior description (e.g. `/tdd "should reject expired tokens"`), use that as the behavioral contract to test.
|
|
49
|
+
If neither is provided, ask: "What behavior are we specifying? Give me a one-liner — what should it do?"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: unfreeze
|
|
3
|
+
description: Clear the active edit directory restriction set by /freeze or /guard
|
|
4
|
+
triggers:
|
|
5
|
+
- unfreeze
|
|
6
|
+
- unlock edits
|
|
7
|
+
- remove freeze
|
|
8
|
+
- allow all edits
|
|
9
|
+
- clear freeze
|
|
10
|
+
- unfreeze edits
|
|
11
|
+
- remove edit restriction
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Clear the edit directory restriction for this session.
|
|
15
|
+
|
|
16
|
+
Confirm: "Edit restriction cleared. I can now create and modify files anywhere in the project, subject to the sandbox (no edits outside the project directory) and the `allowDestructive` config setting."
|
|
17
|
+
|
|
18
|
+
If safety mode (/careful) was also active separately, note: "Note: destructive command confirmation is still active if you enabled it with `/careful`. Say 'turn off safety mode' to disable that."
|
|
19
|
+
|
|
20
|
+
The freeze is now lifted for the rest of this session.
|
package/dist/src/cli/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import { Conversation } from "../core/conversation.js";
|
|
|
12
12
|
import { loadLearnings, formatLearningsForPrompt } from "../core/memory.js";
|
|
13
13
|
import { loadAllSkills } from "../skills/index.js";
|
|
14
14
|
import { log } from "../utils/logger.js";
|
|
15
|
-
const VERSION = "0.
|
|
15
|
+
const VERSION = "0.15.0";
|
|
16
16
|
/** Directory for session auto-saves. */
|
|
17
17
|
const SESSION_DIR = join(process.cwd(), ".phase2s", "sessions");
|
|
18
18
|
/** Path for today's session file. */
|
package/dist/src/mcp/server.d.ts
CHANGED
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
* Start via: phase2s mcp
|
|
12
12
|
* Configure in: .claude/settings.json
|
|
13
13
|
*/
|
|
14
|
+
import { Conversation } from "../core/conversation.js";
|
|
14
15
|
import type { Skill } from "../skills/types.js";
|
|
15
|
-
export declare const MCP_SERVER_VERSION = "0.
|
|
16
|
+
export declare const MCP_SERVER_VERSION = "0.15.0";
|
|
16
17
|
interface JSONRPCRequest {
|
|
17
18
|
jsonrpc: "2.0";
|
|
18
19
|
id: number | string | null;
|
|
@@ -37,6 +38,15 @@ export interface MCPTool {
|
|
|
37
38
|
required: string[];
|
|
38
39
|
};
|
|
39
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* A JSON-RPC notification — like a response but with no `id`.
|
|
43
|
+
* Used for server-to-client push events (e.g. tools list changed).
|
|
44
|
+
*/
|
|
45
|
+
export interface MCPNotification {
|
|
46
|
+
jsonrpc: "2.0";
|
|
47
|
+
method: string;
|
|
48
|
+
params?: unknown;
|
|
49
|
+
}
|
|
40
50
|
/**
|
|
41
51
|
* Convert a Phase2S Skill into an MCP tool descriptor.
|
|
42
52
|
*
|
|
@@ -50,16 +60,33 @@ export declare function skillToTool(skill: Skill): MCPTool;
|
|
|
50
60
|
* "phase2s__consensus_plan" → "consensus-plan"
|
|
51
61
|
*/
|
|
52
62
|
export declare function toolNameToSkillName(toolName: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Build a JSON-RPC notification (no `id` field — this is a server push, not
|
|
65
|
+
* a response to a request).
|
|
66
|
+
*/
|
|
67
|
+
export declare function buildNotification(method: string, params?: unknown): MCPNotification;
|
|
68
|
+
/**
|
|
69
|
+
* Watch the skills directory for new SKILL.md files. When a change is
|
|
70
|
+
* detected (debounced 80ms), reload skills and call notify() so the server
|
|
71
|
+
* can send a notifications/tools/list_changed message to the MCP client.
|
|
72
|
+
*
|
|
73
|
+
* Silently skips watching if the directory does not exist.
|
|
74
|
+
*/
|
|
75
|
+
export declare function setupSkillsWatcher(skillsDir: string, onReload: (skills: Skill[]) => void, notify: () => void): void;
|
|
53
76
|
/**
|
|
54
77
|
* Handle a single JSON-RPC request and return the response.
|
|
55
78
|
*
|
|
56
79
|
* Exported so tests can call it directly without stdio.
|
|
57
80
|
*
|
|
58
|
-
* @param request
|
|
59
|
-
* @param skills
|
|
60
|
-
* @param cwd
|
|
81
|
+
* @param request Parsed JSON-RPC request
|
|
82
|
+
* @param skills Loaded Phase2S skills (passed in so tests can inject fixtures)
|
|
83
|
+
* @param cwd Working directory for config loading and agent runs
|
|
84
|
+
* @param sessionConversations Optional per-skill conversation map for session persistence.
|
|
85
|
+
* When provided, tools/call reuses the existing Conversation
|
|
86
|
+
* for each skill across multiple invocations rather than
|
|
87
|
+
* starting cold every call.
|
|
61
88
|
*/
|
|
62
|
-
export declare function handleRequest(request: JSONRPCRequest, skills: Skill[], cwd: string): Promise<JSONRPCResponse>;
|
|
89
|
+
export declare function handleRequest(request: JSONRPCRequest, skills: Skill[], cwd: string, sessionConversations?: Map<string, Conversation>): Promise<JSONRPCResponse>;
|
|
63
90
|
/**
|
|
64
91
|
* Start the MCP server. Reads JSON-RPC messages from stdin, writes responses
|
|
65
92
|
* to stdout. Runs until stdin closes (i.e. Claude Code terminates the session).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAM3C,UAAU,cAAc;IACtB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;CACH;AAMD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAejD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAMD
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAM3C,UAAU,cAAc;IACtB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAMD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAejD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAMD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,eAAe,CAInF;AAMD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,EACnC,MAAM,EAAE,MAAM,IAAI,GACjB,IAAI,CAsBN;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,KAAK,EAAE,EACf,GAAG,EAAE,MAAM,EACX,oBAAoB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,GAC/C,OAAO,CAAC,eAAe,CAAC,CA8F1B;AAMD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoF7D"}
|
package/dist/src/mcp/server.js
CHANGED
|
@@ -12,11 +12,12 @@
|
|
|
12
12
|
* Configure in: .claude/settings.json
|
|
13
13
|
*/
|
|
14
14
|
import { createInterface } from "node:readline";
|
|
15
|
+
import { watch } from "node:fs";
|
|
15
16
|
import { loadSkillsFromDir } from "../skills/loader.js";
|
|
16
17
|
import { loadConfig } from "../core/config.js";
|
|
17
18
|
import { Agent } from "../core/agent.js";
|
|
18
19
|
import { join } from "node:path";
|
|
19
|
-
export const MCP_SERVER_VERSION = "0.
|
|
20
|
+
export const MCP_SERVER_VERSION = "0.15.0";
|
|
20
21
|
// ---------------------------------------------------------------------------
|
|
21
22
|
// Tool generation
|
|
22
23
|
// ---------------------------------------------------------------------------
|
|
@@ -51,6 +52,53 @@ export function toolNameToSkillName(toolName) {
|
|
|
51
52
|
return toolName.replace(/^phase2s__/, "").replace(/_/g, "-");
|
|
52
53
|
}
|
|
53
54
|
// ---------------------------------------------------------------------------
|
|
55
|
+
// Notification helpers
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
/**
|
|
58
|
+
* Build a JSON-RPC notification (no `id` field — this is a server push, not
|
|
59
|
+
* a response to a request).
|
|
60
|
+
*/
|
|
61
|
+
export function buildNotification(method, params) {
|
|
62
|
+
const n = { jsonrpc: "2.0", method };
|
|
63
|
+
if (params !== undefined)
|
|
64
|
+
n.params = params;
|
|
65
|
+
return n;
|
|
66
|
+
}
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Skills watcher (exported for testing)
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
/**
|
|
71
|
+
* Watch the skills directory for new SKILL.md files. When a change is
|
|
72
|
+
* detected (debounced 80ms), reload skills and call notify() so the server
|
|
73
|
+
* can send a notifications/tools/list_changed message to the MCP client.
|
|
74
|
+
*
|
|
75
|
+
* Silently skips watching if the directory does not exist.
|
|
76
|
+
*/
|
|
77
|
+
export function setupSkillsWatcher(skillsDir, onReload, notify) {
|
|
78
|
+
let debounceTimer = null;
|
|
79
|
+
try {
|
|
80
|
+
watch(skillsDir, { persistent: false }, () => {
|
|
81
|
+
if (debounceTimer)
|
|
82
|
+
clearTimeout(debounceTimer);
|
|
83
|
+
debounceTimer = setTimeout(() => {
|
|
84
|
+
loadSkillsFromDir(skillsDir)
|
|
85
|
+
.then((updated) => {
|
|
86
|
+
onReload(updated);
|
|
87
|
+
notify();
|
|
88
|
+
})
|
|
89
|
+
.catch(() => {
|
|
90
|
+
// Reload errors are silently ignored — stale skill list is better
|
|
91
|
+
// than crashing the server.
|
|
92
|
+
});
|
|
93
|
+
}, 80);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Skills directory doesn't exist or isn't watchable — skip silently.
|
|
98
|
+
// The server still works, just without hot-reload.
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
54
102
|
// Request handler (exported for testing)
|
|
55
103
|
// ---------------------------------------------------------------------------
|
|
56
104
|
/**
|
|
@@ -58,11 +106,15 @@ export function toolNameToSkillName(toolName) {
|
|
|
58
106
|
*
|
|
59
107
|
* Exported so tests can call it directly without stdio.
|
|
60
108
|
*
|
|
61
|
-
* @param request
|
|
62
|
-
* @param skills
|
|
63
|
-
* @param cwd
|
|
109
|
+
* @param request Parsed JSON-RPC request
|
|
110
|
+
* @param skills Loaded Phase2S skills (passed in so tests can inject fixtures)
|
|
111
|
+
* @param cwd Working directory for config loading and agent runs
|
|
112
|
+
* @param sessionConversations Optional per-skill conversation map for session persistence.
|
|
113
|
+
* When provided, tools/call reuses the existing Conversation
|
|
114
|
+
* for each skill across multiple invocations rather than
|
|
115
|
+
* starting cold every call.
|
|
64
116
|
*/
|
|
65
|
-
export async function handleRequest(request, skills, cwd) {
|
|
117
|
+
export async function handleRequest(request, skills, cwd, sessionConversations) {
|
|
66
118
|
// -----------------------------------------------------------------------
|
|
67
119
|
// initialize
|
|
68
120
|
// -----------------------------------------------------------------------
|
|
@@ -72,7 +124,9 @@ export async function handleRequest(request, skills, cwd) {
|
|
|
72
124
|
id: request.id,
|
|
73
125
|
result: {
|
|
74
126
|
protocolVersion: "2024-11-05",
|
|
75
|
-
|
|
127
|
+
// listChanged: true tells the client to re-fetch tools/list when it
|
|
128
|
+
// receives a notifications/tools/list_changed notification.
|
|
129
|
+
capabilities: { tools: { listChanged: true } },
|
|
76
130
|
serverInfo: { name: "phase2s", version: MCP_SERVER_VERSION },
|
|
77
131
|
},
|
|
78
132
|
};
|
|
@@ -107,8 +161,17 @@ export async function handleRequest(request, skills, cwd) {
|
|
|
107
161
|
const fullPrompt = skill.promptTemplate + (userPrompt ? `\n\n## Input\n\n${userPrompt}` : "");
|
|
108
162
|
try {
|
|
109
163
|
const config = await loadConfig();
|
|
110
|
-
|
|
164
|
+
// Session persistence: look up an existing Conversation for this skill.
|
|
165
|
+
// On the first call the map has no entry and Agent creates a fresh one.
|
|
166
|
+
// On subsequent calls the Agent resumes where it left off.
|
|
167
|
+
const existingConversation = sessionConversations?.get(skillName);
|
|
168
|
+
const agent = new Agent({ config, conversation: existingConversation });
|
|
111
169
|
const text = await agent.run(fullPrompt, { modelOverride: skill.model });
|
|
170
|
+
// Store the (possibly updated) conversation back into the session map
|
|
171
|
+
// so the next call to this skill can continue the conversation.
|
|
172
|
+
if (sessionConversations) {
|
|
173
|
+
sessionConversations.set(skillName, agent.getConversation());
|
|
174
|
+
}
|
|
112
175
|
return {
|
|
113
176
|
jsonrpc: "2.0",
|
|
114
177
|
id: request.id,
|
|
@@ -150,10 +213,21 @@ export async function handleRequest(request, skills, cwd) {
|
|
|
150
213
|
*/
|
|
151
214
|
export async function runMCPServer(cwd) {
|
|
152
215
|
const skillsDir = join(cwd, ".phase2s", "skills");
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
216
|
+
let skills = await loadSkillsFromDir(skillsDir);
|
|
217
|
+
// One Conversation per skill, scoped to this process lifetime (= one Claude
|
|
218
|
+
// Code project session). Multi-turn skills like /satori and /consensus-plan
|
|
219
|
+
// resume where they left off rather than starting cold on every tools/call.
|
|
220
|
+
const sessionConversations = new Map();
|
|
221
|
+
const respond = (message) => {
|
|
222
|
+
process.stdout.write(JSON.stringify(message) + "\n");
|
|
156
223
|
};
|
|
224
|
+
// Watch for new skills added mid-session (e.g. via /skill). When detected,
|
|
225
|
+
// reload the skills list and notify the MCP client so it re-fetches tools/list.
|
|
226
|
+
setupSkillsWatcher(skillsDir, (updated) => {
|
|
227
|
+
skills = updated;
|
|
228
|
+
}, () => {
|
|
229
|
+
respond(buildNotification("notifications/tools/list_changed"));
|
|
230
|
+
});
|
|
157
231
|
// Manual event queue — safer than readline async iterator for long-lived servers
|
|
158
232
|
const lineQueue = [];
|
|
159
233
|
let pendingResolve = null;
|
|
@@ -208,7 +282,7 @@ export async function runMCPServer(cwd) {
|
|
|
208
282
|
});
|
|
209
283
|
continue;
|
|
210
284
|
}
|
|
211
|
-
const response = await handleRequest(request, skills, cwd);
|
|
285
|
+
const response = await handleRequest(request, skills, cwd, sessionConversations);
|
|
212
286
|
respond(response);
|
|
213
287
|
}
|
|
214
288
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,8 +16,10 @@ export declare function loadSkillsFromDir(dir: string): Promise<Skill[]>;
|
|
|
16
16
|
* 1. .phase2s/skills/ — current project skills (highest priority)
|
|
17
17
|
* 2. ~/.phase2s/skills/ — global user skills
|
|
18
18
|
* 3. ~/.codex/skills/ — Codex CLI's native skill directory (cross-tool compatibility)
|
|
19
|
+
* 4. <pkg-root>/.phase2s/skills/ — skills bundled inside the installed package (lowest priority)
|
|
19
20
|
*
|
|
20
|
-
* Deduplication: first skill found with a given name wins
|
|
21
|
+
* Deduplication: first skill found with a given name wins.
|
|
22
|
+
* Project skills override global, global override codex, all override bundled defaults.
|
|
21
23
|
*/
|
|
22
24
|
export declare function loadAllSkills(): Promise<Skill[]>;
|
|
23
25
|
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/skills/loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/skills/loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAmBxC;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAkCrE;AA4DD;;;;;;;;;GASG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAyBtD"}
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import { readFile, readdir, stat } from "node:fs/promises";
|
|
2
|
-
import { join, resolve } from "node:path";
|
|
2
|
+
import { join, resolve, dirname } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
3
4
|
import { parse as parseYaml } from "yaml";
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the path to the skills bundled inside the installed package.
|
|
7
|
+
*
|
|
8
|
+
* At runtime this file lives at:
|
|
9
|
+
* <pkg-root>/dist/src/skills/loader.js
|
|
10
|
+
*
|
|
11
|
+
* The bundled skills live at:
|
|
12
|
+
* <pkg-root>/.phase2s/skills/
|
|
13
|
+
*
|
|
14
|
+
* Three levels up from this file's directory gets us to <pkg-root>.
|
|
15
|
+
*/
|
|
16
|
+
function bundledSkillsDir() {
|
|
17
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
18
|
+
const pkgRoot = resolve(dirname(thisFile), "../../..");
|
|
19
|
+
return join(pkgRoot, ".phase2s", "skills");
|
|
20
|
+
}
|
|
4
21
|
/**
|
|
5
22
|
* Load skills from SKILL.md files in a directory.
|
|
6
23
|
*
|
|
@@ -109,8 +126,10 @@ async function parseSkillFile(path) {
|
|
|
109
126
|
* 1. .phase2s/skills/ — current project skills (highest priority)
|
|
110
127
|
* 2. ~/.phase2s/skills/ — global user skills
|
|
111
128
|
* 3. ~/.codex/skills/ — Codex CLI's native skill directory (cross-tool compatibility)
|
|
129
|
+
* 4. <pkg-root>/.phase2s/skills/ — skills bundled inside the installed package (lowest priority)
|
|
112
130
|
*
|
|
113
|
-
* Deduplication: first skill found with a given name wins
|
|
131
|
+
* Deduplication: first skill found with a given name wins.
|
|
132
|
+
* Project skills override global, global override codex, all override bundled defaults.
|
|
114
133
|
*/
|
|
115
134
|
export async function loadAllSkills() {
|
|
116
135
|
const skills = [];
|
|
@@ -119,6 +138,7 @@ export async function loadAllSkills() {
|
|
|
119
138
|
join(process.cwd(), ".phase2s", "skills"),
|
|
120
139
|
join(home, ".phase2s", "skills"),
|
|
121
140
|
join(home, ".codex", "skills"), // Codex CLI native skills — same SKILL.md format
|
|
141
|
+
bundledSkillsDir(), // skills shipped inside the npm package
|
|
122
142
|
];
|
|
123
143
|
const seen = new Set();
|
|
124
144
|
for (const dir of dirs) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/skills/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/skills/loader.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED