gentle-pi 0.1.13 → 0.1.15
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 +40 -38
- package/extensions/gentle-ai.ts +73 -50
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -27,25 +27,27 @@ On session start, `gentle-pi` automatically installs SDD assets into the project
|
|
|
27
27
|
|
|
28
28
|
## What you get
|
|
29
29
|
|
|
30
|
-
| Capability
|
|
31
|
-
|
|
32
|
-
| el Gentleman identity | Answers as a Pi-specific harness, not a generic assistant. Defaults to the `gentleman` persona and can switch to `neutral`.
|
|
33
|
-
| SDD/OpenSpec routing
|
|
34
|
-
| SDD phase agents
|
|
35
|
-
| Strict TDD support
|
|
36
|
-
| Review workload guard | Forecasts large diffs and recommends chained PRs or explicit `size:exception`.
|
|
37
|
-
| Model assignment UI
|
|
38
|
-
| Foundation skills
|
|
39
|
-
| Safety policy
|
|
30
|
+
| Capability | What it does |
|
|
31
|
+
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
32
|
+
| el Gentleman identity | Answers as a Pi-specific harness, not a generic assistant. Defaults to the `gentleman` persona and can switch to `neutral`. |
|
|
33
|
+
| SDD/OpenSpec routing | Small work stays inline, context-heavy work delegates, large/risky work uses SDD artifacts. |
|
|
34
|
+
| SDD phase agents | Installs `sdd-init`, `sdd-explore`, `sdd-proposal`, `sdd-spec`, `sdd-design`, `sdd-tasks`, `sdd-apply`, `sdd-verify`, and `sdd-archive`. |
|
|
35
|
+
| Strict TDD support | Preserves RED → GREEN → TRIANGULATE → REFACTOR evidence and verify-time compliance checks. |
|
|
36
|
+
| Review workload guard | Forecasts large diffs and recommends chained PRs or explicit `size:exception`. |
|
|
37
|
+
| Model assignment UI | Opens a modal to assign Pi models to project, user, and built-in agents, with SDD agents shown first. |
|
|
38
|
+
| Foundation skills | Adds PR, issue, chained-PR, comment, docs, work-unit, and Judgment Day skills. |
|
|
39
|
+
| Safety policy | Blocks destructive shell actions unless there is explicit user approval. |
|
|
40
40
|
|
|
41
41
|
## Core commands
|
|
42
42
|
|
|
43
43
|
```text
|
|
44
44
|
/gentle-ai:status Show package, SDD asset, OpenSpec, and model config status.
|
|
45
|
-
/
|
|
46
|
-
/gentle-ai:models Compatibility alias that points to /
|
|
47
|
-
/gentleman:
|
|
48
|
-
/gentle
|
|
45
|
+
/gentle:models Open the per-agent model assignment modal.
|
|
46
|
+
/gentle-ai:models Compatibility alias that points to /gentle:models.
|
|
47
|
+
/gentleman:models Compatibility alias that points to /gentle:models.
|
|
48
|
+
/gentle:persona Switch between gentleman and neutral personas.
|
|
49
|
+
/gentle-ai:persona Compatibility alias that points to /gentle:persona.
|
|
50
|
+
/gentleman:persona Compatibility alias that points to /gentle:persona.
|
|
49
51
|
/sdd-init Bootstrap or refresh openspec/config.yaml.
|
|
50
52
|
/gentle-ai:install-sdd Reinstall SDD assets without overwriting local files.
|
|
51
53
|
/gentle-ai:install-sdd --force
|
|
@@ -59,15 +61,15 @@ Default persona: `gentleman`.
|
|
|
59
61
|
Run:
|
|
60
62
|
|
|
61
63
|
```text
|
|
62
|
-
/
|
|
64
|
+
/gentle:persona
|
|
63
65
|
```
|
|
64
66
|
|
|
65
67
|
Available modes:
|
|
66
68
|
|
|
67
|
-
| Persona
|
|
68
|
-
|
|
69
|
-
| `gentleman` | Teaching-oriented senior architect persona with Rioplatense Spanish/voseo when the user writes Spanish.
|
|
70
|
-
| `neutral`
|
|
69
|
+
| Persona | Behavior |
|
|
70
|
+
| ----------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
71
|
+
| `gentleman` | Teaching-oriented senior architect persona with Rioplatense Spanish/voseo when the user writes Spanish. |
|
|
72
|
+
| `neutral` | Same senior architect discipline and teaching philosophy, but with warm professional language and no regional expressions. |
|
|
71
73
|
|
|
72
74
|
Saved config:
|
|
73
75
|
|
|
@@ -82,7 +84,7 @@ Run `/reload` or start a new Pi session after switching if the current session a
|
|
|
82
84
|
Run:
|
|
83
85
|
|
|
84
86
|
```text
|
|
85
|
-
/
|
|
87
|
+
/gentle:models
|
|
86
88
|
```
|
|
87
89
|
|
|
88
90
|
This opens a modal similar to Gentle-AI's model picker. It discovers Pi subagents from project, user, and built-in sources, with SDD agents sorted first:
|
|
@@ -121,13 +123,13 @@ The modal covers:
|
|
|
121
123
|
|
|
122
124
|
Small recommendation in English:
|
|
123
125
|
|
|
124
|
-
| Agent kind
|
|
125
|
-
|
|
126
|
-
| Exploration, proposal, archive | Fast and cheap is usually enough.
|
|
127
|
-
| Spec, design, tasks
|
|
128
|
-
| Apply
|
|
129
|
-
| Verify / review agents
|
|
130
|
-
| Tiny utility agents
|
|
126
|
+
| Agent kind | Recommended model shape |
|
|
127
|
+
| ------------------------------ | -------------------------------------------------------------------------------------- |
|
|
128
|
+
| Exploration, proposal, archive | Fast and cheap is usually enough. |
|
|
129
|
+
| Spec, design, tasks | Strong reasoning model, because these phases shape the implementation. |
|
|
130
|
+
| Apply | Strong coding model with good tool-use reliability. |
|
|
131
|
+
| Verify / review agents | Strongest fresh-context model you can afford; verification benefits from independence. |
|
|
132
|
+
| Tiny utility agents | Inherit the active/default model unless they become a bottleneck. |
|
|
131
133
|
|
|
132
134
|
Saved config:
|
|
133
135
|
|
|
@@ -163,17 +165,17 @@ Existing files are skipped. Your local edits remain unless you explicitly run:
|
|
|
163
165
|
|
|
164
166
|
## Package contents
|
|
165
167
|
|
|
166
|
-
| Path
|
|
167
|
-
|
|
168
|
-
| `extensions/gentle-ai.ts`
|
|
169
|
-
| `extensions/sdd-init.ts`
|
|
170
|
-
| `extensions/skill-registry.ts` | Registers `/skill-registry:refresh` and maintains `.atl/skill-registry.md`.
|
|
171
|
-
| `assets/orchestrator.md`
|
|
172
|
-
| `assets/agents/`
|
|
173
|
-
| `assets/chains/`
|
|
174
|
-
| `assets/support/`
|
|
175
|
-
| `skills/`
|
|
176
|
-
| `prompts/`
|
|
168
|
+
| Path | Purpose |
|
|
169
|
+
| ------------------------------ | ------------------------------------------------------------------------------------------------------------- |
|
|
170
|
+
| `extensions/gentle-ai.ts` | Injects el Gentleman, installs assets, provides commands, applies model config, blocks unsafe shell commands. |
|
|
171
|
+
| `extensions/sdd-init.ts` | Registers `/sdd-init` for OpenSpec project initialization. |
|
|
172
|
+
| `extensions/skill-registry.ts` | Registers `/skill-registry:refresh` and maintains `.atl/skill-registry.md`. |
|
|
173
|
+
| `assets/orchestrator.md` | Parent-session orchestration contract. |
|
|
174
|
+
| `assets/agents/` | SDD phase agents copied into `.pi/agents/`. |
|
|
175
|
+
| `assets/chains/` | SDD chains copied into `.pi/chains/`. |
|
|
176
|
+
| `assets/support/` | Strict TDD apply/verify support docs. |
|
|
177
|
+
| `skills/` | el Gentleman and foundation skills. |
|
|
178
|
+
| `prompts/` | Gentle-prefixed prompt templates: `/gcl`, `/gis`, `/gpr`, `/gwr`. |
|
|
177
179
|
|
|
178
180
|
## Foundation skills
|
|
179
181
|
|
package/extensions/gentle-ai.ts
CHANGED
|
@@ -272,7 +272,7 @@ function listAgentFilesRecursive(dir: string): string[] {
|
|
|
272
272
|
|
|
273
273
|
function listAgentsFromDir(dir: string, source: AgentSource): AgentEntry[] {
|
|
274
274
|
return listAgentFilesRecursive(dir)
|
|
275
|
-
.map((filePath) => {
|
|
275
|
+
.map((filePath): AgentEntry | undefined => {
|
|
276
276
|
const name = parseAgentName(filePath);
|
|
277
277
|
return name ? { name, source, filePath } : undefined;
|
|
278
278
|
})
|
|
@@ -590,6 +590,55 @@ async function showSddModelPanel(ctx: ExtensionContext, config: AgentModelConfig
|
|
|
590
590
|
});
|
|
591
591
|
}
|
|
592
592
|
|
|
593
|
+
async function handleModelsCommand(ctx: ExtensionContext): Promise<void> {
|
|
594
|
+
let config = readModelConfig(ctx.cwd);
|
|
595
|
+
let result = await showSddModelPanel(ctx, config);
|
|
596
|
+
while (result.type === "custom") {
|
|
597
|
+
const current = result.agent === "all" ? "inherit" : (config[result.agent] ?? "inherit");
|
|
598
|
+
const custom = await ctx.ui.input(
|
|
599
|
+
`${result.agent === "all" ? "all agents" : result.agent} custom model id`,
|
|
600
|
+
current === "inherit" ? "provider/model" : current,
|
|
601
|
+
);
|
|
602
|
+
if (custom === undefined) return;
|
|
603
|
+
const trimmed = custom.trim();
|
|
604
|
+
if (trimmed.length > 0) {
|
|
605
|
+
if (result.agent === "all") {
|
|
606
|
+
config = Object.fromEntries(listDiscoverableAgents(ctx.cwd).map((agent) => [agent.name, trimmed]));
|
|
607
|
+
} else {
|
|
608
|
+
config = { ...config, [result.agent]: trimmed };
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
result = await showSddModelPanel(ctx, config);
|
|
612
|
+
}
|
|
613
|
+
if (result.type !== "save") return;
|
|
614
|
+
writeModelConfig(ctx.cwd, result.config);
|
|
615
|
+
const applyResult = applyModelConfig(ctx.cwd, result.config);
|
|
616
|
+
ctx.ui.notify(
|
|
617
|
+
[
|
|
618
|
+
"el Gentleman model config saved.",
|
|
619
|
+
`Config: ${modelConfigPath(ctx.cwd)}`,
|
|
620
|
+
`Agents updated: ${applyResult.updated}`,
|
|
621
|
+
...describeModelConfig(ctx.cwd, result.config),
|
|
622
|
+
].join("\n"),
|
|
623
|
+
"info",
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
async function handlePersonaCommand(ctx: ExtensionContext): Promise<void> {
|
|
628
|
+
const current = readPersonaMode(ctx.cwd);
|
|
629
|
+
const selected = await ctx.ui.select(`el Gentleman persona (current: ${current})`, [...PERSONA_OPTIONS]);
|
|
630
|
+
if (selected !== "gentleman" && selected !== "neutral") return;
|
|
631
|
+
writePersonaMode(ctx.cwd, selected);
|
|
632
|
+
ctx.ui.notify(
|
|
633
|
+
[
|
|
634
|
+
`el Gentleman persona set to: ${selected}`,
|
|
635
|
+
`Config: ${personaConfigPath(ctx.cwd)}`,
|
|
636
|
+
"Run /reload or start a new Pi session for already-injected prompts to refresh.",
|
|
637
|
+
].join("\n"),
|
|
638
|
+
"info",
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
|
|
593
642
|
export default function gentleAi(pi: ExtensionAPI): void {
|
|
594
643
|
pi.on("session_start", (_event, ctx) => {
|
|
595
644
|
const result = installSddAssets(ctx.cwd, false);
|
|
@@ -611,6 +660,7 @@ export default function gentleAi(pi: ExtensionAPI): void {
|
|
|
611
660
|
|
|
612
661
|
pi.on("tool_call", async (event, ctx) => {
|
|
613
662
|
if (event.toolName !== "bash") return undefined;
|
|
663
|
+
if (!isRecord(event.input) || typeof event.input.command !== "string") return undefined;
|
|
614
664
|
return confirmCommand(event.input.command, ctx);
|
|
615
665
|
});
|
|
616
666
|
|
|
@@ -626,72 +676,45 @@ export default function gentleAi(pi: ExtensionAPI): void {
|
|
|
626
676
|
},
|
|
627
677
|
});
|
|
628
678
|
|
|
629
|
-
pi.registerCommand("
|
|
679
|
+
pi.registerCommand("gentle:models", {
|
|
630
680
|
description: "Configure per-agent models for el Gentleman.",
|
|
631
681
|
handler: async (_args, ctx) => {
|
|
632
|
-
|
|
633
|
-
let result = await showSddModelPanel(ctx, config);
|
|
634
|
-
while (result.type === "custom") {
|
|
635
|
-
const current = result.agent === "all" ? "inherit" : (config[result.agent] ?? "inherit");
|
|
636
|
-
const custom = await ctx.ui.input(
|
|
637
|
-
`${result.agent === "all" ? "all agents" : result.agent} custom model id`,
|
|
638
|
-
current === "inherit" ? "provider/model" : current,
|
|
639
|
-
);
|
|
640
|
-
if (custom === undefined) return;
|
|
641
|
-
const trimmed = custom.trim();
|
|
642
|
-
if (trimmed.length > 0) {
|
|
643
|
-
if (result.agent === "all") {
|
|
644
|
-
config = Object.fromEntries(listDiscoverableAgents(ctx.cwd).map((agent) => [agent.name, trimmed]));
|
|
645
|
-
} else {
|
|
646
|
-
config = { ...config, [result.agent]: trimmed };
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
result = await showSddModelPanel(ctx, config);
|
|
650
|
-
}
|
|
651
|
-
if (result.type !== "save") return;
|
|
652
|
-
writeModelConfig(ctx.cwd, result.config);
|
|
653
|
-
const applyResult = applyModelConfig(ctx.cwd, result.config);
|
|
654
|
-
ctx.ui.notify(
|
|
655
|
-
[
|
|
656
|
-
"el Gentleman model config saved.",
|
|
657
|
-
`Config: ${modelConfigPath(ctx.cwd)}`,
|
|
658
|
-
`Agents updated: ${applyResult.updated}`,
|
|
659
|
-
...describeModelConfig(ctx.cwd, result.config),
|
|
660
|
-
].join("\n"),
|
|
661
|
-
"info",
|
|
662
|
-
);
|
|
682
|
+
await handleModelsCommand(ctx);
|
|
663
683
|
},
|
|
664
684
|
});
|
|
665
685
|
|
|
666
686
|
pi.registerCommand("gentle-ai:models", {
|
|
667
|
-
description: "
|
|
687
|
+
description: "Compatibility alias for /gentle:models.",
|
|
668
688
|
handler: async (_args, ctx) => {
|
|
669
|
-
ctx
|
|
689
|
+
await handleModelsCommand(ctx);
|
|
670
690
|
},
|
|
671
691
|
});
|
|
672
692
|
|
|
673
|
-
pi.registerCommand("gentleman:
|
|
693
|
+
pi.registerCommand("gentleman:models", {
|
|
694
|
+
description: "Compatibility alias for /gentle:models.",
|
|
695
|
+
handler: async (_args, ctx) => {
|
|
696
|
+
await handleModelsCommand(ctx);
|
|
697
|
+
},
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
pi.registerCommand("gentle:persona", {
|
|
674
701
|
description: "Switch el Gentleman persona between gentleman and neutral.",
|
|
675
702
|
handler: async (_args, ctx) => {
|
|
676
|
-
|
|
677
|
-
const selected = await ctx.ui.select(`el Gentleman persona (current: ${current})`, [...PERSONA_OPTIONS]);
|
|
678
|
-
if (selected !== "gentleman" && selected !== "neutral") return;
|
|
679
|
-
writePersonaMode(ctx.cwd, selected);
|
|
680
|
-
ctx.ui.notify(
|
|
681
|
-
[
|
|
682
|
-
`el Gentleman persona set to: ${selected}`,
|
|
683
|
-
`Config: ${personaConfigPath(ctx.cwd)}`,
|
|
684
|
-
"Run /reload or start a new Pi session for already-injected prompts to refresh.",
|
|
685
|
-
].join("\n"),
|
|
686
|
-
"info",
|
|
687
|
-
);
|
|
703
|
+
await handlePersonaCommand(ctx);
|
|
688
704
|
},
|
|
689
705
|
});
|
|
690
706
|
|
|
691
707
|
pi.registerCommand("gentle-ai:persona", {
|
|
692
|
-
description: "
|
|
708
|
+
description: "Compatibility alias for /gentle:persona.",
|
|
709
|
+
handler: async (_args, ctx) => {
|
|
710
|
+
await handlePersonaCommand(ctx);
|
|
711
|
+
},
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
pi.registerCommand("gentleman:persona", {
|
|
715
|
+
description: "Compatibility alias for /gentle:persona.",
|
|
693
716
|
handler: async (_args, ctx) => {
|
|
694
|
-
ctx
|
|
717
|
+
await handlePersonaCommand(ctx);
|
|
695
718
|
},
|
|
696
719
|
});
|
|
697
720
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gentle-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "Opinionated el Gentleman harness package for Pi: SDD/OpenSpec workflow, strict TDD guidance, subagent assets, and safety defaults.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"README.md"
|
|
27
27
|
],
|
|
28
28
|
"pi": {
|
|
29
|
-
"image": "https://
|
|
29
|
+
"image": "https://cdn.jsdelivr.net/npm/gentle-pi/assets/gentle-logo-only.png",
|
|
30
30
|
"extensions": [
|
|
31
31
|
"./extensions"
|
|
32
32
|
],
|