@shrkcrft/cli 0.1.0-alpha.2 → 0.1.0-alpha.20
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/dist/audit/knowledge-audit-llm.d.ts +19 -0
- package/dist/audit/knowledge-audit-llm.d.ts.map +1 -0
- package/dist/audit/knowledge-audit-llm.js +164 -0
- package/dist/audit/knowledge-audit.d.ts +61 -0
- package/dist/audit/knowledge-audit.d.ts.map +1 -0
- package/dist/audit/knowledge-audit.js +203 -0
- package/dist/audit/knowledge-fix-plan-llm.d.ts +11 -0
- package/dist/audit/knowledge-fix-plan-llm.d.ts.map +1 -0
- package/dist/audit/knowledge-fix-plan-llm.js +141 -0
- package/dist/audit/knowledge-fix-plan.d.ts +41 -0
- package/dist/audit/knowledge-fix-plan.d.ts.map +1 -0
- package/dist/audit/knowledge-fix-plan.js +125 -0
- package/dist/audit/pipeline-audit-llm.d.ts +11 -0
- package/dist/audit/pipeline-audit-llm.d.ts.map +1 -0
- package/dist/audit/pipeline-audit-llm.js +134 -0
- package/dist/audit/pipeline-audit.d.ts +69 -0
- package/dist/audit/pipeline-audit.d.ts.map +1 -0
- package/dist/audit/pipeline-audit.js +166 -0
- package/dist/audit/templates-audit-llm.d.ts +19 -0
- package/dist/audit/templates-audit-llm.d.ts.map +1 -0
- package/dist/audit/templates-audit-llm.js +207 -0
- package/dist/audit/templates-audit.d.ts +63 -0
- package/dist/audit/templates-audit.d.ts.map +1 -0
- package/dist/audit/templates-audit.js +171 -0
- package/dist/audit/templates-fix-plan-llm.d.ts +19 -0
- package/dist/audit/templates-fix-plan-llm.d.ts.map +1 -0
- package/dist/audit/templates-fix-plan-llm.js +162 -0
- package/dist/audit/templates-fix-plan.d.ts +37 -0
- package/dist/audit/templates-fix-plan.d.ts.map +1 -0
- package/dist/audit/templates-fix-plan.js +174 -0
- package/dist/command-registry.d.ts +28 -0
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +91 -1
- package/dist/commands/ai-status.command.d.ts +19 -0
- package/dist/commands/ai-status.command.d.ts.map +1 -0
- package/dist/commands/ai-status.command.js +94 -0
- package/dist/commands/api-diff.command.d.ts +11 -0
- package/dist/commands/api-diff.command.d.ts.map +1 -0
- package/dist/commands/api-diff.command.js +144 -0
- package/dist/commands/apply.command.d.ts.map +1 -1
- package/dist/commands/apply.command.js +10 -2
- package/dist/commands/arch.command.d.ts +9 -0
- package/dist/commands/arch.command.d.ts.map +1 -0
- package/dist/commands/arch.command.js +186 -0
- package/dist/commands/ask.command.d.ts.map +1 -1
- package/dist/commands/ask.command.js +10 -9
- package/dist/commands/cache-align.command.d.ts +12 -0
- package/dist/commands/cache-align.command.d.ts.map +1 -0
- package/dist/commands/cache-align.command.js +78 -0
- package/dist/commands/check.command.d.ts.map +1 -1
- package/dist/commands/check.command.js +19 -2
- package/dist/commands/code-intel.command.d.ts +18 -0
- package/dist/commands/code-intel.command.d.ts.map +1 -0
- package/dist/commands/code-intel.command.js +146 -0
- package/dist/commands/codemod.command.d.ts.map +1 -1
- package/dist/commands/codemod.command.js +27 -6
- package/dist/commands/command-catalog.d.ts +15 -3
- package/dist/commands/command-catalog.d.ts.map +1 -1
- package/dist/commands/command-catalog.js +387 -34
- package/dist/commands/commands.command.d.ts.map +1 -1
- package/dist/commands/commands.command.js +4 -4
- package/dist/commands/completion.command.d.ts +10 -0
- package/dist/commands/completion.command.d.ts.map +1 -0
- package/dist/commands/completion.command.js +121 -0
- package/dist/commands/compress.command.d.ts +8 -0
- package/dist/commands/compress.command.d.ts.map +1 -0
- package/dist/commands/compress.command.js +147 -0
- package/dist/commands/constructs.command.d.ts.map +1 -1
- package/dist/commands/constructs.command.js +89 -23
- package/dist/commands/context.command.d.ts.map +1 -1
- package/dist/commands/context.command.js +121 -1
- package/dist/commands/contract-gate.command.d.ts.map +1 -1
- package/dist/commands/contract-gate.command.js +5 -1
- package/dist/commands/delegate.command.d.ts +65 -0
- package/dist/commands/delegate.command.d.ts.map +1 -0
- package/dist/commands/delegate.command.js +657 -0
- package/dist/commands/deps-audit.command.d.ts +23 -0
- package/dist/commands/deps-audit.command.d.ts.map +1 -0
- package/dist/commands/deps-audit.command.js +270 -0
- package/dist/commands/dev.command.d.ts.map +1 -1
- package/dist/commands/dev.command.js +5 -1
- package/dist/commands/diff-check.command.d.ts +30 -0
- package/dist/commands/diff-check.command.d.ts.map +1 -0
- package/dist/commands/diff-check.command.js +210 -0
- package/dist/commands/doctor.command.d.ts.map +1 -1
- package/dist/commands/doctor.command.js +162 -10
- package/dist/commands/export.command.d.ts.map +1 -1
- package/dist/commands/export.command.js +76 -3
- package/dist/commands/framework.command.d.ts +12 -0
- package/dist/commands/framework.command.d.ts.map +1 -0
- package/dist/commands/framework.command.js +180 -0
- package/dist/commands/gate.command.d.ts +15 -0
- package/dist/commands/gate.command.d.ts.map +1 -0
- package/dist/commands/gate.command.js +300 -0
- package/dist/commands/gen.command.d.ts.map +1 -1
- package/dist/commands/gen.command.js +13 -1
- package/dist/commands/graph-code-subverbs.d.ts +33 -0
- package/dist/commands/graph-code-subverbs.d.ts.map +1 -0
- package/dist/commands/graph-code-subverbs.js +1366 -0
- package/dist/commands/graph.command.d.ts.map +1 -1
- package/dist/commands/graph.command.js +31 -2
- package/dist/commands/help.command.d.ts +4 -3
- package/dist/commands/help.command.d.ts.map +1 -1
- package/dist/commands/help.command.js +86 -18
- package/dist/commands/helper.command.js +1 -1
- package/dist/commands/impact.command.d.ts.map +1 -1
- package/dist/commands/impact.command.js +171 -1
- package/dist/commands/import.command.d.ts.map +1 -1
- package/dist/commands/import.command.js +121 -5
- package/dist/commands/ingest.command.d.ts.map +1 -1
- package/dist/commands/ingest.command.js +5 -1
- package/dist/commands/init.command.d.ts.map +1 -1
- package/dist/commands/init.command.js +174 -7
- package/dist/commands/knowledge-author.command.d.ts.map +1 -1
- package/dist/commands/knowledge-author.command.js +9 -0
- package/dist/commands/knowledge-propose.command.d.ts.map +1 -1
- package/dist/commands/knowledge-propose.command.js +4 -2
- package/dist/commands/knowledge.command.d.ts.map +1 -1
- package/dist/commands/knowledge.command.js +26 -3
- package/dist/commands/migrate.command.d.ts +13 -0
- package/dist/commands/migrate.command.d.ts.map +1 -0
- package/dist/commands/migrate.command.js +152 -0
- package/dist/commands/move-plan.command.d.ts +23 -0
- package/dist/commands/move-plan.command.d.ts.map +1 -0
- package/dist/commands/move-plan.command.js +360 -0
- package/dist/commands/packs-new.d.ts +1 -1
- package/dist/commands/packs-new.d.ts.map +1 -1
- package/dist/commands/packs-new.js +5 -36
- package/dist/commands/packs.command.d.ts.map +1 -1
- package/dist/commands/packs.command.js +2 -10
- package/dist/commands/plan-context.command.d.ts +11 -0
- package/dist/commands/plan-context.command.d.ts.map +1 -0
- package/dist/commands/plan-context.command.js +85 -0
- package/dist/commands/preflight.command.d.ts.map +1 -1
- package/dist/commands/preflight.command.js +15 -0
- package/dist/commands/profiles.command.js +4 -4
- package/dist/commands/recommend.command.d.ts +6 -0
- package/dist/commands/recommend.command.d.ts.map +1 -1
- package/dist/commands/recommend.command.js +119 -5
- package/dist/commands/release.command.js +13 -13
- package/dist/commands/rule-graph-subverbs.d.ts +3 -0
- package/dist/commands/rule-graph-subverbs.d.ts.map +1 -0
- package/dist/commands/rule-graph-subverbs.js +132 -0
- package/dist/commands/rules.command.d.ts.map +1 -1
- package/dist/commands/rules.command.js +20 -3
- package/dist/commands/scaffold-validate.command.d.ts +22 -0
- package/dist/commands/scaffold-validate.command.d.ts.map +1 -0
- package/dist/commands/scaffold-validate.command.js +215 -0
- package/dist/commands/search-structural.command.d.ts +18 -0
- package/dist/commands/search-structural.command.d.ts.map +1 -0
- package/dist/commands/search-structural.command.js +376 -0
- package/dist/commands/search.command.js +1 -1
- package/dist/commands/smart-context.command.d.ts +67 -0
- package/dist/commands/smart-context.command.d.ts.map +1 -0
- package/dist/commands/smart-context.command.js +4728 -0
- package/dist/commands/spike.command.d.ts +22 -0
- package/dist/commands/spike.command.d.ts.map +1 -0
- package/dist/commands/spike.command.js +235 -0
- package/dist/commands/surface.command.d.ts +1 -0
- package/dist/commands/surface.command.d.ts.map +1 -1
- package/dist/commands/surface.command.js +10 -3
- package/dist/commands/task-context.command.d.ts.map +1 -1
- package/dist/commands/task-context.command.js +5 -17
- package/dist/commands/task.command.d.ts.map +1 -1
- package/dist/commands/task.command.js +8 -2
- package/dist/commands/template-quality.command.d.ts.map +1 -1
- package/dist/commands/template-quality.command.js +39 -3
- package/dist/commands/templates.command.d.ts.map +1 -1
- package/dist/commands/templates.command.js +37 -2
- package/dist/commands/tests.command.d.ts.map +1 -1
- package/dist/commands/tests.command.js +13 -2
- package/dist/commands/watch.command.d.ts +26 -0
- package/dist/commands/watch.command.d.ts.map +1 -0
- package/dist/commands/watch.command.js +456 -0
- package/dist/dashboard/code-intelligence-data.d.ts +33 -0
- package/dist/dashboard/code-intelligence-data.d.ts.map +1 -0
- package/dist/dashboard/code-intelligence-data.js +329 -0
- package/dist/dashboard/dashboard-api-server.d.ts.map +1 -1
- package/dist/dashboard/dashboard-api-server.js +256 -2
- package/dist/dashboard/knowledge-ask.d.ts +4 -0
- package/dist/dashboard/knowledge-ask.d.ts.map +1 -0
- package/dist/dashboard/knowledge-ask.js +112 -0
- package/dist/env/load-dotenv.d.ts +15 -0
- package/dist/env/load-dotenv.d.ts.map +1 -0
- package/dist/env/load-dotenv.js +70 -0
- package/dist/export/claude-commands-export.d.ts +60 -0
- package/dist/export/claude-commands-export.d.ts.map +1 -0
- package/dist/export/claude-commands-export.js +276 -0
- package/dist/export/export-formats.d.ts +1 -1
- package/dist/export/export-formats.d.ts.map +1 -1
- package/dist/export/export-formats.js +139 -12
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/init/init-templates.d.ts.map +1 -1
- package/dist/init/init-templates.js +133 -113
- package/dist/init/paths-advisory.d.ts +20 -0
- package/dist/init/paths-advisory.d.ts.map +1 -0
- package/dist/init/paths-advisory.js +88 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +331 -17
- package/dist/output/ccr-store-config.d.ts +18 -0
- package/dist/output/ccr-store-config.d.ts.map +1 -0
- package/dist/output/ccr-store-config.js +41 -0
- package/dist/output/format-output.d.ts.map +1 -1
- package/dist/output/format-output.js +6 -1
- package/dist/output/output-compression.d.ts +15 -0
- package/dist/output/output-compression.d.ts.map +1 -0
- package/dist/output/output-compression.js +60 -0
- package/dist/output/resolve-compress-type.d.ts +22 -0
- package/dist/output/resolve-compress-type.d.ts.map +1 -0
- package/dist/output/resolve-compress-type.js +21 -0
- package/dist/output/watch-loop.d.ts +9 -1
- package/dist/output/watch-loop.d.ts.map +1 -1
- package/dist/output/watch-loop.js +13 -3
- package/dist/schemas/json-schemas.d.ts +384 -36
- package/dist/schemas/json-schemas.d.ts.map +1 -1
- package/dist/schemas/json-schemas.js +247 -36
- package/dist/surface/profiles.d.ts.map +1 -1
- package/dist/surface/profiles.js +54 -9
- package/dist/surface/surface-config-writer.d.ts.map +1 -1
- package/dist/surface/surface-config-writer.js +23 -11
- package/dist/validation/run-validation-loop.d.ts.map +1 -1
- package/dist/validation/run-validation-loop.js +5 -1
- package/package.json +35 -21
- package/dist/commands/plugin.command.d.ts +0 -11
- package/dist/commands/plugin.command.d.ts.map +0 -1
- package/dist/commands/plugin.command.js +0 -394
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
import { aggregateActionHints, KnowledgeType } from '@shrkcrft/knowledge';
|
|
2
2
|
import { priorityWeight } from '@shrkcrft/knowledge';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
function projectSlug(name) {
|
|
4
|
+
if (!name)
|
|
5
|
+
return 'project';
|
|
6
|
+
return (name
|
|
7
|
+
.toLowerCase()
|
|
8
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
9
|
+
.replace(/^-+|-+$/g, '')
|
|
10
|
+
.slice(0, 48) || 'project');
|
|
11
|
+
}
|
|
12
|
+
function defaultOutputFor(format, inspection) {
|
|
13
|
+
switch (format) {
|
|
14
|
+
case 'agents-md':
|
|
15
|
+
return 'AGENTS.md';
|
|
16
|
+
case 'claude-md':
|
|
17
|
+
return 'CLAUDE.md';
|
|
18
|
+
case 'claude-skill':
|
|
19
|
+
return `.claude/skills/${projectSlug(inspection.config?.projectName)}/SKILL.md`;
|
|
20
|
+
case 'cursor-rules':
|
|
21
|
+
return '.cursor/rules/sharkcraft.mdc';
|
|
22
|
+
case 'copilot-instructions':
|
|
23
|
+
return '.github/copilot-instructions.md';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
9
26
|
function selectTopByPriority(entries, limit) {
|
|
10
27
|
return [...entries]
|
|
11
28
|
.sort((a, b) => priorityWeight(b.priority) - priorityWeight(a.priority))
|
|
@@ -100,23 +117,131 @@ function renderBody(inspection, options) {
|
|
|
100
117
|
}
|
|
101
118
|
return sections.join('\n\n');
|
|
102
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Filter rules / paths to the high-signal subset for an inlined skill.
|
|
122
|
+
*
|
|
123
|
+
* Every rule the skill carries pays in Claude's context every time the
|
|
124
|
+
* skill is loaded. Low-priority items dilute the signal of the
|
|
125
|
+
* load-bearing ones (`Critical` safety + `High` architecture). We keep
|
|
126
|
+
* only Critical + High by default, falling back to "all" only if the
|
|
127
|
+
* filtered list is empty (e.g. a repo with no high-priority entries
|
|
128
|
+
* yet shouldn't ship an empty skill).
|
|
129
|
+
*/
|
|
130
|
+
function filterHighSignal(entries) {
|
|
131
|
+
const filtered = entries.filter((e) => {
|
|
132
|
+
const p = String(e.priority).toLowerCase();
|
|
133
|
+
return p === 'critical' || p === 'high';
|
|
134
|
+
});
|
|
135
|
+
return filtered.length > 0 ? filtered : [...entries];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Render the body in tight, decision-driving form for the Claude Code
|
|
139
|
+
* Skill format. Skills get loaded into Claude's prompt when the skill's
|
|
140
|
+
* `description` matches the current task, so the body must be short and
|
|
141
|
+
* directly actionable — no preamble, no metadata about generation, no
|
|
142
|
+
* pipelines (Claude can run `shrk task` for those when needed).
|
|
143
|
+
*
|
|
144
|
+
* Sections:
|
|
145
|
+
* 1. Where files belong (path conventions, top N) — most-leveraged signal.
|
|
146
|
+
* 2. Rules to follow (Critical + High only) — pads context otherwise.
|
|
147
|
+
* 3. Do / Don't — forbidden actions and verification commands.
|
|
148
|
+
* 4. How to write code in this repo — the gen → review → apply loop
|
|
149
|
+
* verbatim, since Claude needs to know shrk is the write path.
|
|
150
|
+
*/
|
|
151
|
+
function renderSkillBody(inspection, options) {
|
|
152
|
+
const { rules: allRules, paths: allPaths } = gatherRulesAndPaths(inspection, {
|
|
153
|
+
...options,
|
|
154
|
+
// Pull more upfront, then filter down to high-signal — keeps the
|
|
155
|
+
// softcap-at-15 default but the inlined skill stays terse.
|
|
156
|
+
maxRules: options.maxRules ?? 24,
|
|
157
|
+
maxPaths: options.maxPaths ?? 18,
|
|
158
|
+
});
|
|
159
|
+
// Skills are inlined into the prompt — every entry costs Claude
|
|
160
|
+
// context. Only ship the items the user said are load-bearing.
|
|
161
|
+
const rules = filterHighSignal(allRules).slice(0, options.maxRules ?? 12);
|
|
162
|
+
const paths = filterHighSignal(allPaths).slice(0, options.maxPaths ?? 10);
|
|
163
|
+
const sections = [];
|
|
164
|
+
if (inspection.config?.description) {
|
|
165
|
+
sections.push(`## About this codebase\n\n${inspection.config.description}`);
|
|
166
|
+
}
|
|
167
|
+
const pathsBody = renderPathsSection(paths);
|
|
168
|
+
if (pathsBody) {
|
|
169
|
+
sections.push(`## Where files belong\n\nWhen creating or moving a file, place it according to these conventions:\n\n${pathsBody}`);
|
|
170
|
+
}
|
|
171
|
+
const rulesBody = renderRulesSection(rules);
|
|
172
|
+
if (rulesBody) {
|
|
173
|
+
sections.push(`## Rules this codebase follows\n\nApply these whenever you generate, modify, or review code:\n\n${rulesBody}`);
|
|
174
|
+
}
|
|
175
|
+
const agg = aggregateActionHints(inspection.knowledgeEntries);
|
|
176
|
+
const doDont = [];
|
|
177
|
+
if (agg.forbiddenActions.length) {
|
|
178
|
+
doDont.push('**Do not:**');
|
|
179
|
+
for (const f of agg.forbiddenActions.slice(0, 8))
|
|
180
|
+
doDont.push(`- ${f}`);
|
|
181
|
+
doDont.push('');
|
|
182
|
+
}
|
|
183
|
+
if (agg.verificationCommands.length) {
|
|
184
|
+
doDont.push('**Verify changes with:**');
|
|
185
|
+
for (const c of agg.verificationCommands.slice(0, 6))
|
|
186
|
+
doDont.push(`- \`${c}\``);
|
|
187
|
+
}
|
|
188
|
+
if (doDont.length) {
|
|
189
|
+
sections.push(`## Do / Don't\n\n${doDont.join('\n').trim()}`);
|
|
190
|
+
}
|
|
191
|
+
sections.push(`## How to write code in this repo\n\n` +
|
|
192
|
+
`This repository uses [SharkCraft](https://github.com/shrkcrft/sharkcraft) to gate writes — the CLI is the only write path, and writes go through a plan → review → apply loop.\n\n` +
|
|
193
|
+
`1. **Get a task packet** before non-trivial work: \`shrk task "<one-sentence task>"\` returns the focused rules, paths, templates, and verification commands for that task.\n` +
|
|
194
|
+
`2. **Scaffold via templates** instead of writing files freehand: \`shrk gen <template-id> <name> --dry-run --save-plan plan.json\` produces a signed plan.\n` +
|
|
195
|
+
`3. **Apply the plan** through the CLI: \`shrk apply plan.json --verify-signature\` — never write through MCP.\n` +
|
|
196
|
+
`4. **Check the result**: \`shrk check boundaries\` + the verification commands listed above.\n\n` +
|
|
197
|
+
`For ad-hoc questions about the codebase, query the MCP server (\`shrk mcp serve\`) or run \`shrk context --task "<query>"\` for token-budgeted context.`);
|
|
198
|
+
return sections.join('\n\n');
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Build the YAML frontmatter for a Claude Code Skill. The `description`
|
|
202
|
+
* field is what Claude uses to decide whether to load this skill — keep
|
|
203
|
+
* it specific (project name + what's covered) so it doesn't trigger on
|
|
204
|
+
* unrelated tasks.
|
|
205
|
+
*/
|
|
206
|
+
function renderSkillFrontmatter(inspection) {
|
|
207
|
+
const slug = projectSlug(inspection.config?.projectName);
|
|
208
|
+
const projectName = inspection.config?.projectName ?? slug;
|
|
209
|
+
const description = `Codebase rules, path conventions, and review gates for ${projectName}. ` +
|
|
210
|
+
`Use this skill whenever generating, modifying, or reviewing code in this repository — ` +
|
|
211
|
+
`it tells you the per-file path conventions, the architecture boundaries, the verification commands, ` +
|
|
212
|
+
`and the safe write path (CLI plan → review → apply).`;
|
|
213
|
+
return `---\nname: ${slug}\ndescription: ${JSON.stringify(description)}\n---`;
|
|
214
|
+
}
|
|
103
215
|
export function renderExport(inspection, options) {
|
|
104
|
-
const
|
|
105
|
-
const suggestedPath = DEFAULT_OUTPUT_PATH[options.format];
|
|
216
|
+
const suggestedPath = defaultOutputFor(options.format, inspection);
|
|
106
217
|
let content = '';
|
|
107
218
|
switch (options.format) {
|
|
108
|
-
case 'agents-md':
|
|
219
|
+
case 'agents-md': {
|
|
220
|
+
const body = renderBody(inspection, options);
|
|
109
221
|
content = `# Agents Guide\n\n${PREAMBLE}\n\n${body}\n`;
|
|
110
222
|
break;
|
|
111
|
-
|
|
223
|
+
}
|
|
224
|
+
case 'claude-md': {
|
|
225
|
+
const body = renderBody(inspection, options);
|
|
112
226
|
content = `# CLAUDE.md\n\n${PREAMBLE}\n\nThis file is read by Claude Code (claude.ai/code) at session start. Treat it as a compatibility view of the project's SharkCraft knowledge — use the MCP server (\`shrk mcp serve\`) for the live, queryable source of truth.\n\n${body}\n`;
|
|
113
227
|
break;
|
|
228
|
+
}
|
|
229
|
+
case 'claude-skill': {
|
|
230
|
+
// Claude Code Skill: YAML frontmatter declares when to load this,
|
|
231
|
+
// body is tight decision-driving content. No preamble, no boilerplate
|
|
232
|
+
// — every token in here costs Claude context when loaded.
|
|
233
|
+
const frontmatter = renderSkillFrontmatter(inspection);
|
|
234
|
+
const projectName = inspection.config?.projectName ?? 'this codebase';
|
|
235
|
+
const body = renderSkillBody(inspection, options);
|
|
236
|
+
content = `${frontmatter}\n\n# ${projectName} — codebase guide\n\n${body}\n`;
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
114
239
|
case 'cursor-rules':
|
|
115
240
|
// Cursor MDC frontmatter: leave alwaysApply off so the user can tune.
|
|
116
|
-
content = `---\ndescription: SharkCraft project rules (auto-generated)\nalwaysApply: false\n---\n\n${PREAMBLE}\n\n${
|
|
241
|
+
content = `---\ndescription: SharkCraft project rules (auto-generated)\nalwaysApply: false\n---\n\n${PREAMBLE}\n\n${renderBody(inspection, options)}\n`;
|
|
117
242
|
break;
|
|
118
243
|
case 'copilot-instructions':
|
|
119
|
-
content = `# Copilot instructions\n\n${PREAMBLE}\n\n${
|
|
244
|
+
content = `# Copilot instructions\n\n${PREAMBLE}\n\n${renderBody(inspection, options)}\n`;
|
|
120
245
|
break;
|
|
121
246
|
}
|
|
122
247
|
return { format: options.format, suggestedPath, content };
|
|
@@ -124,12 +249,14 @@ export function renderExport(inspection, options) {
|
|
|
124
249
|
export function isExportFormat(value) {
|
|
125
250
|
return (value === 'agents-md' ||
|
|
126
251
|
value === 'claude-md' ||
|
|
252
|
+
value === 'claude-skill' ||
|
|
127
253
|
value === 'cursor-rules' ||
|
|
128
254
|
value === 'copilot-instructions');
|
|
129
255
|
}
|
|
130
256
|
export const ALL_EXPORT_FORMATS = Object.freeze([
|
|
131
257
|
'agents-md',
|
|
132
258
|
'claude-md',
|
|
259
|
+
'claude-skill',
|
|
133
260
|
'cursor-rules',
|
|
134
261
|
'copilot-instructions',
|
|
135
262
|
]);
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,9 @@ export { packsListCommand, packsGetCommand, packsInspectCommand, packsDoctorComm
|
|
|
17
17
|
export { pipelinesListCommand, pipelinesGetCommand, pipelinesContextCommand, pipelinesPlanCommand, pipelinesScriptCommand, pipelinesNextCommand, } from './commands/pipelines.command.js';
|
|
18
18
|
export { schemasListCommand, schemasGetCommand, schemasWriteCommand, } from './commands/schemas.command.js';
|
|
19
19
|
export { versionCommand } from './commands/version.command.js';
|
|
20
|
+
export { compressCommand, expandCommand } from './commands/compress.command.js';
|
|
21
|
+
export { alignCommand, unalignCommand } from './commands/cache-align.command.js';
|
|
20
22
|
export { makeHelpCommand } from './commands/help.command.js';
|
|
21
23
|
export { buildRegistry, runCli } from './main.js';
|
|
24
|
+
export { buildWatchPlan, maybeRunInWatchMode, runWatchLoop, } from './output/watch-loop.js';
|
|
22
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,YAAY,GACb,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -17,5 +17,8 @@ export { packsListCommand, packsGetCommand, packsInspectCommand, packsDoctorComm
|
|
|
17
17
|
export { pipelinesListCommand, pipelinesGetCommand, pipelinesContextCommand, pipelinesPlanCommand, pipelinesScriptCommand, pipelinesNextCommand, } from "./commands/pipelines.command.js";
|
|
18
18
|
export { schemasListCommand, schemasGetCommand, schemasWriteCommand, } from "./commands/schemas.command.js";
|
|
19
19
|
export { versionCommand } from "./commands/version.command.js";
|
|
20
|
+
export { compressCommand, expandCommand } from "./commands/compress.command.js";
|
|
21
|
+
export { alignCommand, unalignCommand } from "./commands/cache-align.command.js";
|
|
20
22
|
export { makeHelpCommand } from "./commands/help.command.js";
|
|
21
23
|
export { buildRegistry, runCli } from "./main.js";
|
|
24
|
+
export { buildWatchPlan, maybeRunInWatchMode, runWatchLoop, } from "./output/watch-loop.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-templates.d.ts","sourceRoot":"","sources":["../../src/init/init-templates.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"init-templates.d.ts","sourceRoot":"","sources":["../../src/init/init-templates.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD,eAAO,MAAM,UAAU,EAAE,SAAS,SAAS,EA2W1C,CAAC"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
// Self-contained scaffolding for `shrk init --legacy`. Every generated
|
|
2
|
+
// `sharkcraft/*.ts` file must work in a brand-new downstream repo where
|
|
3
|
+
// no `@shrkcrft/*` packages are installed beyond the CLI itself. The
|
|
4
|
+
// loaders (knowledge / templates / pipelines / path-conventions) are
|
|
5
|
+
// shape-agnostic — they accept any object with the required string
|
|
6
|
+
// fields — so each emitted file declares its own minimal helpers +
|
|
7
|
+
// enum-like constants inline.
|
|
1
8
|
export const INIT_FILES = [
|
|
2
9
|
{
|
|
3
10
|
relativePath: 'sharkcraft.config.ts',
|
|
4
|
-
content:
|
|
11
|
+
content: `// Generated by \`shrk init --legacy\`. Plain default export — no
|
|
12
|
+
// @shrkcrft/* import required. The config loader validates this object
|
|
13
|
+
// by shape (zod), so the literal works without a helper call.
|
|
5
14
|
|
|
6
|
-
export default
|
|
15
|
+
export default {
|
|
7
16
|
projectName: 'my-project',
|
|
8
17
|
description: 'A SharkCraft-powered repository.',
|
|
9
18
|
knowledgeFiles: ['knowledge.ts'],
|
|
@@ -13,12 +22,36 @@ export default defineSharkCraftConfig({
|
|
|
13
22
|
docsFiles: ['docs/overview.md', 'docs/architecture.md', 'docs/quick-start.md'],
|
|
14
23
|
defaultMaxTokens: 4000,
|
|
15
24
|
defaultScope: ['typescript'],
|
|
16
|
-
}
|
|
25
|
+
};
|
|
17
26
|
`,
|
|
18
27
|
},
|
|
19
28
|
{
|
|
20
29
|
relativePath: 'knowledge.ts',
|
|
21
|
-
content:
|
|
30
|
+
content: `// Local helpers — keep this file self-contained (no @shrkcrft/* imports).
|
|
31
|
+
// The knowledge loader is shape-agnostic; it accepts any object whose
|
|
32
|
+
// \`id\`, \`title\`, and \`content\` are strings.
|
|
33
|
+
|
|
34
|
+
const KnowledgePriority = {
|
|
35
|
+
Critical: 'critical',
|
|
36
|
+
High: 'high',
|
|
37
|
+
Medium: 'medium',
|
|
38
|
+
Low: 'low',
|
|
39
|
+
} as const;
|
|
40
|
+
|
|
41
|
+
const KnowledgeType = {
|
|
42
|
+
Rule: 'rule',
|
|
43
|
+
Path: 'path',
|
|
44
|
+
Template: 'template',
|
|
45
|
+
Architecture: 'architecture',
|
|
46
|
+
Technical: 'technical',
|
|
47
|
+
Convention: 'convention',
|
|
48
|
+
Workflow: 'workflow',
|
|
49
|
+
Warning: 'warning',
|
|
50
|
+
} as const;
|
|
51
|
+
|
|
52
|
+
function defineKnowledgeEntry<T>(entry: T): T {
|
|
53
|
+
return entry;
|
|
54
|
+
}
|
|
22
55
|
|
|
23
56
|
export const projectOverview = defineKnowledgeEntry({
|
|
24
57
|
id: 'project.overview',
|
|
@@ -67,8 +100,20 @@ export default [projectOverview, aiAgentBriefing, generationSafety];
|
|
|
67
100
|
},
|
|
68
101
|
{
|
|
69
102
|
relativePath: 'rules.ts',
|
|
70
|
-
content:
|
|
71
|
-
|
|
103
|
+
content: `// Local helpers — keep this file self-contained (no @shrkcrft/* imports).
|
|
104
|
+
|
|
105
|
+
const KnowledgePriority = {
|
|
106
|
+
Critical: 'critical',
|
|
107
|
+
High: 'high',
|
|
108
|
+
Medium: 'medium',
|
|
109
|
+
Low: 'low',
|
|
110
|
+
} as const;
|
|
111
|
+
|
|
112
|
+
const KnowledgeType = { Rule: 'rule' } as const;
|
|
113
|
+
|
|
114
|
+
function defineRule<T>(rule: T): T {
|
|
115
|
+
return { ...rule, type: KnowledgeType.Rule } as T;
|
|
116
|
+
}
|
|
72
117
|
|
|
73
118
|
export const tsNamingClasses = defineRule({
|
|
74
119
|
id: 'typescript.naming.classes',
|
|
@@ -142,81 +187,15 @@ export default [
|
|
|
142
187
|
},
|
|
143
188
|
{
|
|
144
189
|
relativePath: 'paths.ts',
|
|
145
|
-
content:
|
|
146
|
-
import { KnowledgePriority } from '@shrkcrft/knowledge';
|
|
147
|
-
|
|
148
|
-
export const appSrc = definePathConvention({
|
|
149
|
-
id: 'app.src',
|
|
150
|
-
title: 'Application source root',
|
|
151
|
-
path: 'src',
|
|
152
|
-
description: 'All application source lives here.',
|
|
153
|
-
priority: KnowledgePriority.Critical,
|
|
154
|
-
scope: ['typescript'],
|
|
155
|
-
tags: ['source-path', 'root'],
|
|
156
|
-
appliesWhen: ['generate-code'],
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
export const services = definePathConvention({
|
|
160
|
-
id: 'app.services',
|
|
161
|
-
title: 'Application services',
|
|
162
|
-
path: 'src/services',
|
|
163
|
-
description: 'Application services live here.',
|
|
164
|
-
priority: KnowledgePriority.High,
|
|
165
|
-
scope: ['typescript', 'backend'],
|
|
166
|
-
tags: ['service', 'source-path'],
|
|
167
|
-
appliesWhen: ['generate-service', 'create-business-logic'],
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
export const utils = definePathConvention({
|
|
171
|
-
id: 'app.utils',
|
|
172
|
-
title: 'Utilities',
|
|
173
|
-
path: 'src/utils',
|
|
174
|
-
description: 'Pure functions, no side effects.',
|
|
175
|
-
priority: KnowledgePriority.Medium,
|
|
176
|
-
scope: ['typescript'],
|
|
177
|
-
tags: ['util', 'source-path'],
|
|
178
|
-
appliesWhen: ['generate-utility'],
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
export const features = definePathConvention({
|
|
182
|
-
id: 'app.features',
|
|
183
|
-
title: 'Feature folders',
|
|
184
|
-
path: 'src/features',
|
|
185
|
-
description: 'Vertical feature slices. Use this for end-to-end features.',
|
|
186
|
-
priority: KnowledgePriority.Medium,
|
|
187
|
-
scope: ['typescript'],
|
|
188
|
-
tags: ['feature', 'source-path'],
|
|
189
|
-
appliesWhen: ['generate-feature'],
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
export const tests = definePathConvention({
|
|
193
|
-
id: 'app.tests',
|
|
194
|
-
title: 'Test files',
|
|
195
|
-
path: 'tests',
|
|
196
|
-
description: 'Test files (or co-located *.spec.ts next to the unit under test).',
|
|
197
|
-
priority: KnowledgePriority.Medium,
|
|
198
|
-
scope: ['typescript', 'testing'],
|
|
199
|
-
tags: ['test', 'source-path'],
|
|
200
|
-
appliesWhen: ['generate-test'],
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
export const docs = definePathConvention({
|
|
204
|
-
id: 'app.docs',
|
|
205
|
-
title: 'Documentation',
|
|
206
|
-
path: 'docs',
|
|
207
|
-
description: 'Long-form human-readable docs (optional).',
|
|
208
|
-
priority: KnowledgePriority.Low,
|
|
209
|
-
scope: ['typescript'],
|
|
210
|
-
tags: ['docs'],
|
|
211
|
-
appliesWhen: ['add-docs'],
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
export default [appSrc, services, utils, features, tests, docs];
|
|
215
|
-
`,
|
|
190
|
+
content: PATHS_PLACEHOLDER_CONTENT(),
|
|
216
191
|
},
|
|
217
192
|
{
|
|
218
193
|
relativePath: 'templates.ts',
|
|
219
|
-
content:
|
|
194
|
+
content: `// Local helpers — keep this file self-contained (no @shrkcrft/* imports).
|
|
195
|
+
|
|
196
|
+
function defineTemplate<T>(template: T): T {
|
|
197
|
+
return template;
|
|
198
|
+
}
|
|
220
199
|
|
|
221
200
|
export const tsService = defineTemplate({
|
|
222
201
|
id: 'typescript.service',
|
|
@@ -229,8 +208,8 @@ export const tsService = defineTemplate({
|
|
|
229
208
|
{ name: 'name', required: true, description: 'kebab-case file name (e.g. user-profile)' },
|
|
230
209
|
{ name: 'className', required: true, description: 'PascalCase class name (e.g. UserProfileService)' },
|
|
231
210
|
],
|
|
232
|
-
targetPath: ({ name }) => \`src/services/\${name}.service.ts\`,
|
|
233
|
-
content: ({ className }) => \`export class \${className} {
|
|
211
|
+
targetPath: ({ name }: { name: string }) => \`src/services/\${name}.service.ts\`,
|
|
212
|
+
content: ({ className }: { className: string }) => \`export class \${className} {
|
|
234
213
|
constructor() {}
|
|
235
214
|
|
|
236
215
|
init(): void {
|
|
@@ -253,42 +232,14 @@ export const tsUtility = defineTemplate({
|
|
|
253
232
|
{ name: 'name', required: true, description: 'kebab-case file name' },
|
|
254
233
|
{ name: 'camel', required: true, description: 'camelCase function name' },
|
|
255
234
|
],
|
|
256
|
-
targetPath: ({ name }) => \`src/utils/\${name}.ts\`,
|
|
257
|
-
content: ({ camel }) => \`export function \${camel}(input: unknown): unknown {
|
|
235
|
+
targetPath: ({ name }: { name: string }) => \`src/utils/\${name}.ts\`,
|
|
236
|
+
content: ({ camel }: { camel: string }) => \`export function \${camel}(input: unknown): unknown {
|
|
258
237
|
return input;
|
|
259
238
|
}
|
|
260
239
|
\`,
|
|
261
240
|
postGenerationNotes: ['Keep utilities pure. No side effects, no shared mutable state.'],
|
|
262
241
|
});
|
|
263
242
|
|
|
264
|
-
export const tsFeatureFolder = defineTemplate({
|
|
265
|
-
id: 'typescript.feature',
|
|
266
|
-
name: 'TypeScript Feature folder',
|
|
267
|
-
description: 'Creates a vertical feature slice (index + service + types).',
|
|
268
|
-
tags: ['typescript', 'feature'],
|
|
269
|
-
scope: ['typescript'],
|
|
270
|
-
appliesWhen: ['generate-feature'],
|
|
271
|
-
variables: [
|
|
272
|
-
{ name: 'name', required: true },
|
|
273
|
-
{ name: 'pascal', required: true },
|
|
274
|
-
],
|
|
275
|
-
files: ({ name, pascal }) => [
|
|
276
|
-
{
|
|
277
|
-
targetPath: \`src/features/\${name}/index.ts\`,
|
|
278
|
-
content: \`export * from './\${name}.service.ts';\nexport * from './\${name}.types.ts';\n\`,
|
|
279
|
-
},
|
|
280
|
-
{
|
|
281
|
-
targetPath: \`src/features/\${name}/\${name}.service.ts\`,
|
|
282
|
-
content: \`import type { I\${pascal}Config } from './\${name}.types.ts';\n\nexport class \${pascal}Service {\n constructor(private readonly config: I\${pascal}Config) {}\n}\n\`,
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
targetPath: \`src/features/\${name}/\${name}.types.ts\`,
|
|
286
|
-
content: \`export interface I\${pascal}Config {\n enabled: boolean;\n}\n\`,
|
|
287
|
-
},
|
|
288
|
-
],
|
|
289
|
-
postGenerationNotes: ['Add tests under tests/<feature> or co-located *.spec.ts.'],
|
|
290
|
-
});
|
|
291
|
-
|
|
292
243
|
export const tsTest = defineTemplate({
|
|
293
244
|
id: 'typescript.test',
|
|
294
245
|
name: 'TypeScript Test File',
|
|
@@ -300,11 +251,18 @@ export const tsTest = defineTemplate({
|
|
|
300
251
|
{ name: 'name', required: true },
|
|
301
252
|
{ name: 'pascal', required: true },
|
|
302
253
|
],
|
|
303
|
-
targetPath: ({ name }) => \`tests/\${name}.spec.ts\`,
|
|
304
|
-
content: ({ pascal }) => \`import { describe, expect, test } from 'bun:test'
|
|
254
|
+
targetPath: ({ name }: { name: string }) => \`tests/\${name}.spec.ts\`,
|
|
255
|
+
content: ({ pascal }: { pascal: string }) => \`import { describe, expect, test } from 'bun:test';
|
|
256
|
+
|
|
257
|
+
describe('\${pascal}', () => {
|
|
258
|
+
test('placeholder', () => {
|
|
259
|
+
expect(true).toBe(true);
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
\`,
|
|
305
263
|
});
|
|
306
264
|
|
|
307
|
-
export default [tsService, tsUtility,
|
|
265
|
+
export default [tsService, tsUtility, tsTest];
|
|
308
266
|
`,
|
|
309
267
|
},
|
|
310
268
|
{
|
|
@@ -411,3 +369,65 @@ Lower-priority work for SharkCraft-powered knowledge in this repo.
|
|
|
411
369
|
`,
|
|
412
370
|
},
|
|
413
371
|
];
|
|
372
|
+
function PATHS_PLACEHOLDER_CONTENT() {
|
|
373
|
+
// The legacy seed ships generic path examples. The modern preset path
|
|
374
|
+
// (`shrk init --preset <id>`) is workspace-aware. To avoid emitting
|
|
375
|
+
// broken defaults like `src/services/` in repos that don't have them,
|
|
376
|
+
// the legacy seed now ships *commented* examples plus an `// TODO:`
|
|
377
|
+
// marker the human is expected to fill in. The runner-instructions in
|
|
378
|
+
// docs/onboarding.md describe how to derive paths from the live repo.
|
|
379
|
+
return `// Local helpers — keep this file self-contained (no @shrkcrft/* imports).
|
|
380
|
+
|
|
381
|
+
const KnowledgePriority = {
|
|
382
|
+
Critical: 'critical',
|
|
383
|
+
High: 'high',
|
|
384
|
+
Medium: 'medium',
|
|
385
|
+
Low: 'low',
|
|
386
|
+
} as const;
|
|
387
|
+
|
|
388
|
+
const KnowledgeType = { Path: 'path' } as const;
|
|
389
|
+
|
|
390
|
+
function definePathConvention<T>(convention: T): T {
|
|
391
|
+
return { ...convention, type: KnowledgeType.Path } as T;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// TODO: replace the examples below with real path conventions for this
|
|
395
|
+
// repository. Run \`shrk onboard --dry-run\` to see what the inference
|
|
396
|
+
// engine detects from the workspace.
|
|
397
|
+
|
|
398
|
+
export const appSrc = definePathConvention({
|
|
399
|
+
id: 'app.src',
|
|
400
|
+
title: 'Application source root',
|
|
401
|
+
path: 'src',
|
|
402
|
+
description: 'All application source lives here. Adjust to match this repo.',
|
|
403
|
+
priority: KnowledgePriority.Critical,
|
|
404
|
+
scope: ['typescript'],
|
|
405
|
+
tags: ['source-path', 'root'],
|
|
406
|
+
appliesWhen: ['generate-code'],
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
export const tests = definePathConvention({
|
|
410
|
+
id: 'app.tests',
|
|
411
|
+
title: 'Test files',
|
|
412
|
+
path: 'tests',
|
|
413
|
+
description: 'Test files. Many repos co-locate \`*.spec.ts\` next to the unit under test instead — pick one.',
|
|
414
|
+
priority: KnowledgePriority.Medium,
|
|
415
|
+
scope: ['typescript', 'testing'],
|
|
416
|
+
tags: ['test', 'source-path'],
|
|
417
|
+
appliesWhen: ['generate-test'],
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
export const docs = definePathConvention({
|
|
421
|
+
id: 'app.docs',
|
|
422
|
+
title: 'Documentation',
|
|
423
|
+
path: 'docs',
|
|
424
|
+
description: 'Long-form human-readable docs (optional).',
|
|
425
|
+
priority: KnowledgePriority.Low,
|
|
426
|
+
scope: ['typescript'],
|
|
427
|
+
tags: ['docs'],
|
|
428
|
+
appliesWhen: ['add-docs'],
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
export default [appSrc, tests, docs];
|
|
432
|
+
`;
|
|
433
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface IPathsAdvisory {
|
|
2
|
+
missingPaths: readonly string[];
|
|
3
|
+
existingPaths: readonly string[];
|
|
4
|
+
/** True when an advisory comment was prepended to the file. */
|
|
5
|
+
annotated: boolean;
|
|
6
|
+
pathsFile: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Scan the generated `sharkcraft/paths.ts` for `path: '<x>'` references
|
|
10
|
+
* and check each `<x>` against the live workspace. When any path is
|
|
11
|
+
* missing, prepend a clearly-labeled comment block listing the missing
|
|
12
|
+
* paths so the user knows which defaults to adjust.
|
|
13
|
+
*
|
|
14
|
+
* Idempotent — if the file already starts with the advisory marker,
|
|
15
|
+
* it is left untouched. Non-destructive — never edits, comments, or
|
|
16
|
+
* removes the original entries. The user is expected to revise them
|
|
17
|
+
* based on the advisory + `shrk onboard --dry-run` output.
|
|
18
|
+
*/
|
|
19
|
+
export declare function annotatePathsAgainstDisk(cwd: string, sharkcraftDir: string): IPathsAdvisory;
|
|
20
|
+
//# sourceMappingURL=paths-advisory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths-advisory.d.ts","sourceRoot":"","sources":["../../src/init/paths-advisory.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,GACpB,cAAc,CAwChB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import * as nodePath from 'node:path';
|
|
3
|
+
const ADVISORY_MARKER = '// ⚠️ Workspace-shape advisory (added by `shrk init`):';
|
|
4
|
+
/**
|
|
5
|
+
* Scan the generated `sharkcraft/paths.ts` for `path: '<x>'` references
|
|
6
|
+
* and check each `<x>` against the live workspace. When any path is
|
|
7
|
+
* missing, prepend a clearly-labeled comment block listing the missing
|
|
8
|
+
* paths so the user knows which defaults to adjust.
|
|
9
|
+
*
|
|
10
|
+
* Idempotent — if the file already starts with the advisory marker,
|
|
11
|
+
* it is left untouched. Non-destructive — never edits, comments, or
|
|
12
|
+
* removes the original entries. The user is expected to revise them
|
|
13
|
+
* based on the advisory + `shrk onboard --dry-run` output.
|
|
14
|
+
*/
|
|
15
|
+
export function annotatePathsAgainstDisk(cwd, sharkcraftDir) {
|
|
16
|
+
const pathsFile = nodePath.join(sharkcraftDir, 'paths.ts');
|
|
17
|
+
if (!existsSync(pathsFile)) {
|
|
18
|
+
return { missingPaths: [], existingPaths: [], annotated: false, pathsFile };
|
|
19
|
+
}
|
|
20
|
+
const original = readFileSync(pathsFile, 'utf8');
|
|
21
|
+
if (original.startsWith(ADVISORY_MARKER)) {
|
|
22
|
+
// Already annotated. Re-derive sets for caller diagnostics.
|
|
23
|
+
return classifyOnly(cwd, pathsFile, original);
|
|
24
|
+
}
|
|
25
|
+
const { existing, missing } = classifyPathReferences(cwd, original);
|
|
26
|
+
if (missing.length === 0) {
|
|
27
|
+
return {
|
|
28
|
+
missingPaths: [],
|
|
29
|
+
existingPaths: existing,
|
|
30
|
+
annotated: false,
|
|
31
|
+
pathsFile,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const lines = [
|
|
35
|
+
ADVISORY_MARKER,
|
|
36
|
+
'//',
|
|
37
|
+
'// The following paths referenced below do NOT exist in this repository:',
|
|
38
|
+
...missing.map((p) => `// - ${p}`),
|
|
39
|
+
'//',
|
|
40
|
+
'// They are conservative defaults from the chosen preset. Adjust them to',
|
|
41
|
+
'// match your actual layout. Run `shrk onboard --dry-run` to see what',
|
|
42
|
+
'// the inference engine detects from your workspace.',
|
|
43
|
+
'//',
|
|
44
|
+
'',
|
|
45
|
+
];
|
|
46
|
+
writeFileSync(pathsFile, lines.join('\n') + original, 'utf8');
|
|
47
|
+
return {
|
|
48
|
+
missingPaths: missing,
|
|
49
|
+
existingPaths: existing,
|
|
50
|
+
annotated: true,
|
|
51
|
+
pathsFile,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function classifyOnly(cwd, pathsFile, original) {
|
|
55
|
+
const { existing, missing } = classifyPathReferences(cwd, original);
|
|
56
|
+
return {
|
|
57
|
+
missingPaths: missing,
|
|
58
|
+
existingPaths: existing,
|
|
59
|
+
annotated: false,
|
|
60
|
+
pathsFile,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function classifyPathReferences(cwd, source) {
|
|
64
|
+
// Match `path: '<x>'` / `path: "<x>"`. Ignore obvious code-context
|
|
65
|
+
// references (e.g. inside template literals); we only consume the
|
|
66
|
+
// first plain-string occurrence per entry.
|
|
67
|
+
const re = /\bpath\s*:\s*['"]([^'"\n]+)['"]/g;
|
|
68
|
+
const seen = new Set();
|
|
69
|
+
let m;
|
|
70
|
+
while ((m = re.exec(source)) !== null) {
|
|
71
|
+
if (m[1])
|
|
72
|
+
seen.add(m[1]);
|
|
73
|
+
}
|
|
74
|
+
const existing = [];
|
|
75
|
+
const missing = [];
|
|
76
|
+
for (const p of [...seen].sort()) {
|
|
77
|
+
if (isReachable(cwd, p))
|
|
78
|
+
existing.push(p);
|
|
79
|
+
else
|
|
80
|
+
missing.push(p);
|
|
81
|
+
}
|
|
82
|
+
return { existing, missing };
|
|
83
|
+
}
|
|
84
|
+
function isReachable(cwd, p) {
|
|
85
|
+
// Absolute or rooted-relative — resolve as-is.
|
|
86
|
+
const full = nodePath.isAbsolute(p) ? p : nodePath.resolve(cwd, p);
|
|
87
|
+
return existsSync(full);
|
|
88
|
+
}
|
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAEA,OAAO,EACL,eAAe,EAKhB,MAAM,uBAAuB,CAAC;AAwX/B,wBAAgB,aAAa,IAAI,eAAe,CA4X/C;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BrE;AAsHD;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAoDxE"}
|