@praxis-framework/seed 0.1.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/README.md +47 -0
- package/dist/catalog.d.ts +60 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +239 -0
- package/dist/catalog.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/seed.d.ts +43 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +508 -0
- package/dist/seed.js.map +1 -0
- package/dist/template.d.ts +16 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +47 -0
- package/dist/template.js.map +1 -0
- package/dist/traits.d.ts +26 -0
- package/dist/traits.d.ts.map +1 -0
- package/dist/traits.js +43 -0
- package/dist/traits.js.map +1 -0
- package/dist/types.d.ts +288 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +87 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
- package/template/.env.example +8 -0
- package/template/CLAUDE.md +151 -0
- package/template/_gitignore +20 -0
- package/template/docker-compose.yml +44 -0
- package/template/escalations/README.md +51 -0
- package/template/lib/.gitkeep +0 -0
- package/template/lib/autonomy.yaml +158 -0
- package/template/lib/output-schemas.yaml +88 -0
- package/template/lib/tools.yaml +70 -0
- package/template/memory/README.md +51 -0
- package/template/memory/accounts/.gitkeep +0 -0
- package/template/memory/notes/.gitkeep +0 -0
- package/template/memory/people/.gitkeep +0 -0
- package/template/persona.md +75 -0
- package/template/verbs/escalate.md +112 -0
- package/template/verbs/proposed/README.md +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# @praxis-framework/seed
|
|
2
|
+
|
|
3
|
+
Role-scaffolding library that powers [`@praxis-framework/cli`](https://www.npmjs.com/package/@praxis-framework/cli)'s `init` command.
|
|
4
|
+
|
|
5
|
+
Given a validated role definition, `seedRole()` writes a populated [praxis-framework](https://github.com/steveworley/praxis-framework) role into a target directory: `persona.md`, `CLAUDE.md`, `verbs/`, `lib/`, `memory/`, `escalations/`, and `output/`.
|
|
6
|
+
|
|
7
|
+
## Who should use this
|
|
8
|
+
|
|
9
|
+
Most operators should reach for [`@praxis-framework/cli`](https://www.npmjs.com/package/@praxis-framework/cli) instead — it wraps this library in an interactive wizard and handles input collection, validation feedback, and git integration. The CLI is the supported entry point.
|
|
10
|
+
|
|
11
|
+
This package is published separately so the framework's dashboard can also call `seedRole()` directly from its in-browser setup flow. If you're building tooling on top of praxis and need programmatic scaffolding, import from here. Otherwise use the CLI.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @praxis-framework/seed
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { seedRole, type SeedInput } from '@praxis-framework/seed';
|
|
23
|
+
|
|
24
|
+
const input: SeedInput = {
|
|
25
|
+
organisation: { name: 'Acme', size: 'small' },
|
|
26
|
+
role_definition: {
|
|
27
|
+
role_name: 'sales-lead',
|
|
28
|
+
one_sentence_purpose: 'drives outbound on Acme\'s flagship product',
|
|
29
|
+
},
|
|
30
|
+
voice_traits: [{ trait: 'direct', qualifiers: ['short sentences, no hedging'] }],
|
|
31
|
+
capabilities: ['drafts cold-outreach emails'],
|
|
32
|
+
inhibitions: ['never quote prices without sign-off'],
|
|
33
|
+
initial_verbs: [{ slug: 'draft-cold-emails', description: ['compose an outreach email per prospect'] }],
|
|
34
|
+
tools: [],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const result = await seedRole(input, '/path/to/new-role');
|
|
38
|
+
console.log(result.filesWritten);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`SeedInput` is validated with Zod; invalid input throws `SeedError` with `code: 'INVALID_INPUT'`. Refer to the source in [`src/types.ts`](./src/types.ts) for the full schema.
|
|
42
|
+
|
|
43
|
+
If the target directory isn't already a git repository, `seedRole()` runs `git init --initial-branch=main` before writing any files. Existing repos are left untouched — the seed never re-inits or renames the operator's chosen default branch. Commits are the caller's responsibility.
|
|
44
|
+
|
|
45
|
+
## License
|
|
46
|
+
|
|
47
|
+
MIT — see [LICENSE](https://github.com/steveworley/praxis-framework/blob/main/LICENSE).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tools-catalog parsing and writing for the seed package.
|
|
3
|
+
*
|
|
4
|
+
* The framework template ships a single `template/lib/tools.yaml` listing
|
|
5
|
+
* every capability a role can opt into. When seeding a role we don't want to
|
|
6
|
+
* copy the catalog wholesale — the seeded `lib/tools.yaml` should contain
|
|
7
|
+
* only the tools enabled for *this* role: every always-available built-in
|
|
8
|
+
* (bash, edit, log) plus any optional capability the operator selected via
|
|
9
|
+
* the wizard.
|
|
10
|
+
*
|
|
11
|
+
* Parser shape mirrors `cli/src/lib/catalog.ts` so the two packages stay in
|
|
12
|
+
* sync. The seed package can't depend on the CLI (the dashboard imports the
|
|
13
|
+
* seed package and we don't want to drag CLI code in), so the parser is
|
|
14
|
+
* duplicated here. If a third caller appears, lift this into a shared module.
|
|
15
|
+
*/
|
|
16
|
+
export type CatalogFieldValue = string | number | boolean | null | string[];
|
|
17
|
+
export type CatalogEntry = Record<string, CatalogFieldValue>;
|
|
18
|
+
export type RawCatalog = Record<string, CatalogEntry>;
|
|
19
|
+
/**
|
|
20
|
+
* Parse a `tools.yaml` payload into `{ capabilityName: { fieldKey: value } }`.
|
|
21
|
+
*
|
|
22
|
+
* Supported shape — the same as the framework catalog ships today:
|
|
23
|
+
*
|
|
24
|
+
* capabilities:
|
|
25
|
+
* bash:
|
|
26
|
+
* description: "..."
|
|
27
|
+
* transport_options: [native]
|
|
28
|
+
* default_transport: native
|
|
29
|
+
* always_available: true
|
|
30
|
+
* mcp:slack:
|
|
31
|
+
* description: "..."
|
|
32
|
+
* transport_options: [stdio, sse, url]
|
|
33
|
+
* default_transport: stdio
|
|
34
|
+
* default_auth_env: SLACK_MCP_TOKEN
|
|
35
|
+
* docker_image: praxis/mcp-slack:latest
|
|
36
|
+
*
|
|
37
|
+
* Comments and blank lines are skipped at any depth. Unknown YAML constructs
|
|
38
|
+
* are skipped rather than failing — strict validation is the catalog
|
|
39
|
+
* loader's job (the seed package only needs to filter and re-emit).
|
|
40
|
+
*/
|
|
41
|
+
export declare function parseToolsYaml(text: string): RawCatalog;
|
|
42
|
+
/**
|
|
43
|
+
* Read the framework catalog and return the entries enabled for a seeded
|
|
44
|
+
* role: every built-in (`always_available: true`) plus any optional
|
|
45
|
+
* capability whose name appears in `selectedTools`. Selected names with no
|
|
46
|
+
* matching catalog entry are silently dropped — the wizard validates against
|
|
47
|
+
* the catalog upstream, so unknown names here are an invariant violation
|
|
48
|
+
* we'd rather not propagate into the seeded file.
|
|
49
|
+
*
|
|
50
|
+
* Throws `SeedError('TEMPLATE_MISSING')` when the template's tools.yaml
|
|
51
|
+
* isn't readable.
|
|
52
|
+
*/
|
|
53
|
+
export declare function buildSeededCatalog(templateRoot: string, selectedTools: readonly string[]): Promise<RawCatalog>;
|
|
54
|
+
/**
|
|
55
|
+
* Render a filtered catalog back to YAML matching the framework template's
|
|
56
|
+
* shape. Header comment is short — operators read the framework's catalog
|
|
57
|
+
* for the schema; the seeded file is just the activated subset.
|
|
58
|
+
*/
|
|
59
|
+
export declare function renderToolsYaml(catalog: RawCatalog): string;
|
|
60
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,EAAE,CAAC;AAC5E,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAC7D,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CA+DvD;AAgDD;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,OAAO,CAAC,UAAU,CAAC,CAuBrB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAmC3D"}
|
package/dist/catalog.js
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { SeedError } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Parse a `tools.yaml` payload into `{ capabilityName: { fieldKey: value } }`.
|
|
6
|
+
*
|
|
7
|
+
* Supported shape — the same as the framework catalog ships today:
|
|
8
|
+
*
|
|
9
|
+
* capabilities:
|
|
10
|
+
* bash:
|
|
11
|
+
* description: "..."
|
|
12
|
+
* transport_options: [native]
|
|
13
|
+
* default_transport: native
|
|
14
|
+
* always_available: true
|
|
15
|
+
* mcp:slack:
|
|
16
|
+
* description: "..."
|
|
17
|
+
* transport_options: [stdio, sse, url]
|
|
18
|
+
* default_transport: stdio
|
|
19
|
+
* default_auth_env: SLACK_MCP_TOKEN
|
|
20
|
+
* docker_image: praxis/mcp-slack:latest
|
|
21
|
+
*
|
|
22
|
+
* Comments and blank lines are skipped at any depth. Unknown YAML constructs
|
|
23
|
+
* are skipped rather than failing — strict validation is the catalog
|
|
24
|
+
* loader's job (the seed package only needs to filter and re-emit).
|
|
25
|
+
*/
|
|
26
|
+
export function parseToolsYaml(text) {
|
|
27
|
+
const lines = text.split('\n');
|
|
28
|
+
const out = {};
|
|
29
|
+
let i = 0;
|
|
30
|
+
let inCapabilities = false;
|
|
31
|
+
let currentCap = null;
|
|
32
|
+
let currentCapIndent = 0;
|
|
33
|
+
while (i < lines.length) {
|
|
34
|
+
const raw = lines[i] ?? '';
|
|
35
|
+
const trimmed = raw.trim();
|
|
36
|
+
if (trimmed.length === 0 || trimmed.startsWith('#')) {
|
|
37
|
+
i += 1;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (!inCapabilities) {
|
|
41
|
+
if (/^capabilities\s*:\s*$/.test(trimmed)) {
|
|
42
|
+
inCapabilities = true;
|
|
43
|
+
}
|
|
44
|
+
i += 1;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const leading = raw.length - raw.trimStart().length;
|
|
48
|
+
// A new top-level key (zero indent) ends the capabilities block.
|
|
49
|
+
if (leading === 0 && /:\s*$/.test(trimmed)) {
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
// Capability header: `<name>:` at the first indent level under
|
|
53
|
+
// `capabilities:`. Names may contain colons (e.g. `mcp:slack`), so we
|
|
54
|
+
// strip only the trailing `:` separator.
|
|
55
|
+
const isHeaderLine = trimmed.endsWith(':') && !trimmed.startsWith('-');
|
|
56
|
+
if (isHeaderLine && (currentCap === null || leading <= currentCapIndent)) {
|
|
57
|
+
const name = trimmed.slice(0, -1).trim();
|
|
58
|
+
if (name.length > 0) {
|
|
59
|
+
currentCap = name;
|
|
60
|
+
currentCapIndent = leading;
|
|
61
|
+
out[name] = {};
|
|
62
|
+
i += 1;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (currentCap !== null && leading > currentCapIndent) {
|
|
67
|
+
const fieldMatch = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*:\s*(.*)$/.exec(raw);
|
|
68
|
+
if (fieldMatch) {
|
|
69
|
+
const key = (fieldMatch[1] ?? '').trim();
|
|
70
|
+
const rest = (fieldMatch[2] ?? '').trim();
|
|
71
|
+
out[currentCap][key] = parseScalar(rest);
|
|
72
|
+
}
|
|
73
|
+
i += 1;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
i += 1;
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
function parseScalar(raw) {
|
|
81
|
+
const value = raw.trim();
|
|
82
|
+
if (value.length === 0)
|
|
83
|
+
return null;
|
|
84
|
+
if (value === 'null' || value === '~')
|
|
85
|
+
return null;
|
|
86
|
+
if (value === 'true')
|
|
87
|
+
return true;
|
|
88
|
+
if (value === 'false')
|
|
89
|
+
return false;
|
|
90
|
+
if (value.startsWith('[') && value.endsWith(']')) {
|
|
91
|
+
const inner = value.slice(1, -1).trim();
|
|
92
|
+
if (inner.length === 0)
|
|
93
|
+
return [];
|
|
94
|
+
return inner.split(',').map((part) => stripQuotes(part.trim()));
|
|
95
|
+
}
|
|
96
|
+
if (/^-?\d+$/.test(value)) {
|
|
97
|
+
const n = Number.parseInt(value, 10);
|
|
98
|
+
if (Number.isFinite(n))
|
|
99
|
+
return n;
|
|
100
|
+
}
|
|
101
|
+
return stripQuotes(value);
|
|
102
|
+
}
|
|
103
|
+
function stripQuotes(value) {
|
|
104
|
+
if (value.length < 2)
|
|
105
|
+
return value;
|
|
106
|
+
const first = value[0];
|
|
107
|
+
const last = value[value.length - 1];
|
|
108
|
+
if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
|
|
109
|
+
return value.slice(1, -1);
|
|
110
|
+
}
|
|
111
|
+
return value;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Field-emit order for each capability. Matches the order the framework
|
|
115
|
+
* catalog uses today so the seeded file is visually familiar to operators.
|
|
116
|
+
* Fields not in this list (if any future schema additions slip through) are
|
|
117
|
+
* appended in insertion order at the end.
|
|
118
|
+
*/
|
|
119
|
+
const FIELD_ORDER = [
|
|
120
|
+
'description',
|
|
121
|
+
'transport_options',
|
|
122
|
+
'default_transport',
|
|
123
|
+
'always_available',
|
|
124
|
+
'default_auth_env',
|
|
125
|
+
'docker_image',
|
|
126
|
+
];
|
|
127
|
+
/**
|
|
128
|
+
* Read the framework catalog and return the entries enabled for a seeded
|
|
129
|
+
* role: every built-in (`always_available: true`) plus any optional
|
|
130
|
+
* capability whose name appears in `selectedTools`. Selected names with no
|
|
131
|
+
* matching catalog entry are silently dropped — the wizard validates against
|
|
132
|
+
* the catalog upstream, so unknown names here are an invariant violation
|
|
133
|
+
* we'd rather not propagate into the seeded file.
|
|
134
|
+
*
|
|
135
|
+
* Throws `SeedError('TEMPLATE_MISSING')` when the template's tools.yaml
|
|
136
|
+
* isn't readable.
|
|
137
|
+
*/
|
|
138
|
+
export async function buildSeededCatalog(templateRoot, selectedTools) {
|
|
139
|
+
const catalogPath = path.join(templateRoot, 'lib', 'tools.yaml');
|
|
140
|
+
let text;
|
|
141
|
+
try {
|
|
142
|
+
text = await fs.readFile(catalogPath, 'utf-8');
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
const cause = e instanceof Error ? e.message : String(e);
|
|
146
|
+
throw new SeedError(`Failed to read template catalog ${catalogPath}: ${cause}`, 'TEMPLATE_MISSING');
|
|
147
|
+
}
|
|
148
|
+
const full = parseToolsYaml(text);
|
|
149
|
+
const selected = new Set(selectedTools);
|
|
150
|
+
const out = {};
|
|
151
|
+
for (const [name, entry] of Object.entries(full)) {
|
|
152
|
+
const isBuiltin = entry['always_available'] === true;
|
|
153
|
+
if (isBuiltin || selected.has(name)) {
|
|
154
|
+
out[name] = entry;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Render a filtered catalog back to YAML matching the framework template's
|
|
161
|
+
* shape. Header comment is short — operators read the framework's catalog
|
|
162
|
+
* for the schema; the seeded file is just the activated subset.
|
|
163
|
+
*/
|
|
164
|
+
export function renderToolsYaml(catalog) {
|
|
165
|
+
const lines = [];
|
|
166
|
+
lines.push('# Tools enabled for this role.');
|
|
167
|
+
lines.push('#');
|
|
168
|
+
lines.push("# Mirrors the framework catalog at <framework>/template/lib/tools.yaml,");
|
|
169
|
+
lines.push('# filtered to the always-available built-ins plus any optional capabilities');
|
|
170
|
+
lines.push("# the operator selected during `praxis init`. To enable another tool, add");
|
|
171
|
+
lines.push('# its entry from the framework catalog here.');
|
|
172
|
+
lines.push('');
|
|
173
|
+
lines.push('capabilities:');
|
|
174
|
+
const names = Object.keys(catalog);
|
|
175
|
+
for (const name of names) {
|
|
176
|
+
const entry = catalog[name] ?? {};
|
|
177
|
+
lines.push(` ${name}:`);
|
|
178
|
+
const seen = new Set();
|
|
179
|
+
for (const key of FIELD_ORDER) {
|
|
180
|
+
if (key in entry) {
|
|
181
|
+
seen.add(key);
|
|
182
|
+
lines.push(` ${key}: ${formatYamlValue(entry[key])}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Trail with any fields not in the canonical order.
|
|
186
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
187
|
+
if (seen.has(key))
|
|
188
|
+
continue;
|
|
189
|
+
lines.push(` ${key}: ${formatYamlValue(value)}`);
|
|
190
|
+
}
|
|
191
|
+
lines.push('');
|
|
192
|
+
}
|
|
193
|
+
// Trim the trailing blank line so file ends with one newline.
|
|
194
|
+
while (lines.length > 0 && lines[lines.length - 1] === '') {
|
|
195
|
+
lines.pop();
|
|
196
|
+
}
|
|
197
|
+
return `${lines.join('\n')}\n`;
|
|
198
|
+
}
|
|
199
|
+
function formatYamlValue(value) {
|
|
200
|
+
if (value === null)
|
|
201
|
+
return 'null';
|
|
202
|
+
if (value === true)
|
|
203
|
+
return 'true';
|
|
204
|
+
if (value === false)
|
|
205
|
+
return 'false';
|
|
206
|
+
if (typeof value === 'number')
|
|
207
|
+
return String(value);
|
|
208
|
+
if (Array.isArray(value)) {
|
|
209
|
+
if (value.length === 0)
|
|
210
|
+
return '[]';
|
|
211
|
+
return `[${value.map((v) => formatYamlScalar(v)).join(', ')}]`;
|
|
212
|
+
}
|
|
213
|
+
return formatYamlScalar(value);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Quote a string scalar when bare emission would change its meaning to a
|
|
217
|
+
* parser: reserved literals (`true` / `false` / `null` / `~`), integer-shaped
|
|
218
|
+
* values, leading/trailing whitespace, or characters that introduce YAML
|
|
219
|
+
* structure (`#`, `{`, `[`, `,`, `&`, `*`, `!`, `|`, `>`, `'`, `"`, `%`, `@`,
|
|
220
|
+
* backtick) at the start of the value. Mid-value `:` and `/` are safe in
|
|
221
|
+
* block scalars and would force every docker-image string to be quoted, so
|
|
222
|
+
* we leave those bare to match the framework catalog's existing style.
|
|
223
|
+
*/
|
|
224
|
+
function formatYamlScalar(value) {
|
|
225
|
+
if (value.length === 0)
|
|
226
|
+
return '""';
|
|
227
|
+
const first = value[0] ?? '';
|
|
228
|
+
if (value === 'true' ||
|
|
229
|
+
value === 'false' ||
|
|
230
|
+
value === 'null' ||
|
|
231
|
+
value === '~' ||
|
|
232
|
+
/^-?\d+$/.test(value) ||
|
|
233
|
+
value !== value.trim() ||
|
|
234
|
+
'#{}[],&*!|>\'"%@`'.includes(first)) {
|
|
235
|
+
return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
236
|
+
}
|
|
237
|
+
return value;
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @praxis-framework/seed — shared role-seeding logic.
|
|
3
|
+
*
|
|
4
|
+
* The dashboard's setup wizard and the CLI's `praxis init` both call
|
|
5
|
+
* `seedRole(input, targetPath, options?)` to materialise a populated
|
|
6
|
+
* praxis role from the framework template. The function performs only
|
|
7
|
+
* file IO; callers layer their own concerns (git commits, approval flows,
|
|
8
|
+
* UI feedback) on top.
|
|
9
|
+
*/
|
|
10
|
+
export { seedRole, injectPersona, injectClaudeDescription, injectVerbsTable } from './seed.js';
|
|
11
|
+
export { resolveTemplatePath } from './template.js';
|
|
12
|
+
export { TRAIT_LIBRARY, findTrait } from './traits.js';
|
|
13
|
+
export type { TraitEntry } from './traits.js';
|
|
14
|
+
export { SeedVerbSchema, SeedInputSchema, OrganisationSchema, RoleDefinitionSchema, VoiceTraitSchema, SeedError, } from './types.js';
|
|
15
|
+
export type { SeedVerb, SeedInput, SeedOptions, SeedResult, Organisation, RoleDefinition, VoiceTrait, } from './types.js';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,UAAU,EACV,YAAY,EACZ,cAAc,EACd,UAAU,GACX,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @praxis-framework/seed — shared role-seeding logic.
|
|
3
|
+
*
|
|
4
|
+
* The dashboard's setup wizard and the CLI's `praxis init` both call
|
|
5
|
+
* `seedRole(input, targetPath, options?)` to materialise a populated
|
|
6
|
+
* praxis role from the framework template. The function performs only
|
|
7
|
+
* file IO; callers layer their own concerns (git commits, approval flows,
|
|
8
|
+
* UI feedback) on top.
|
|
9
|
+
*/
|
|
10
|
+
export { seedRole, injectPersona, injectClaudeDescription, injectVerbsTable } from './seed.js';
|
|
11
|
+
export { resolveTemplatePath } from './template.js';
|
|
12
|
+
export { TRAIT_LIBRARY, findTrait } from './traits.js';
|
|
13
|
+
export { SeedVerbSchema, SeedInputSchema, OrganisationSchema, RoleDefinitionSchema, VoiceTraitSchema, SeedError, } from './types.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EACL,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,SAAS,GACV,MAAM,YAAY,CAAC"}
|
package/dist/seed.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type SeedVerb, type SeedInput, type SeedOptions, type SeedResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Seed a praxis role from the framework template into `targetPath`.
|
|
4
|
+
*
|
|
5
|
+
* The seed owns one repo concern: if `targetPath` isn't already a git
|
|
6
|
+
* repository, it runs `git init --initial-branch=main` before writing
|
|
7
|
+
* any files. Existing repos are left alone (no branch rename, no
|
|
8
|
+
* re-init). Beyond that, the seed performs only file IO — no commits,
|
|
9
|
+
* no environment side-effects beyond writing into the target. Callers
|
|
10
|
+
* (dashboard, CLI) layer their own commit / approval / cleanup behaviour
|
|
11
|
+
* around the result.
|
|
12
|
+
*/
|
|
13
|
+
export declare function seedRole(rawInput: SeedInput, targetPath: string, options?: SeedOptions): Promise<SeedResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Replace the CLAUDE.md placeholder one-liner with the operator's role
|
|
16
|
+
* description.
|
|
17
|
+
*/
|
|
18
|
+
export declare function injectClaudeDescription(body: string, description: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Replace the verbs-table placeholder row in CLAUDE.md with one row per
|
|
21
|
+
* operator-supplied verb. The framework template ships the table with
|
|
22
|
+
* `Persona` and `Escalate` rows already in place plus a single
|
|
23
|
+
* `_(add your role's verbs here)_` placeholder row; this function deletes
|
|
24
|
+
* the placeholder and appends one row per captured verb in the order they
|
|
25
|
+
* were captured.
|
|
26
|
+
*
|
|
27
|
+
* Columns: `Verb` (slug, prettified bold) / `File` (path to the stub) /
|
|
28
|
+
* `Input Stage` (always `<unset>` — the wizard does not capture this yet) /
|
|
29
|
+
* `Output Stage` (first description bullet, or `<unset>` when the operator
|
|
30
|
+
* left description empty).
|
|
31
|
+
*
|
|
32
|
+
* If the placeholder row is absent (e.g. the template has been customised),
|
|
33
|
+
* the body is returned unchanged — losing the operator's verbs from the
|
|
34
|
+
* manual is bad, but mangling a customised manual is worse.
|
|
35
|
+
*/
|
|
36
|
+
export declare function injectVerbsTable(body: string, verbs: readonly SeedVerb[]): string;
|
|
37
|
+
/**
|
|
38
|
+
* Inject operator-supplied content into the persona template, replacing
|
|
39
|
+
* placeholder section bodies under known section headings. Exported for
|
|
40
|
+
* testing.
|
|
41
|
+
*/
|
|
42
|
+
export declare function injectPersona(body: string, input: SeedInput): string;
|
|
43
|
+
//# sourceMappingURL=seed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,UAAU,EAEhB,MAAM,YAAY,CAAC;AAgFpB;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,SAAS,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAkJrB;AAuCD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEjF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CAkBjF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CA2CpE"}
|