@t3lnet/sceneforge 1.0.14 → 1.0.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/context/context-builder.ts +56 -0
- package/context/tests/context-builder.test.ts +15 -2
- package/dist/index.cjs +47 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -107,6 +107,42 @@ async function mergeWithExisting(
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
async function writeSplitPointer(
|
|
111
|
+
tool: TargetTool,
|
|
112
|
+
stageNames: Stage[],
|
|
113
|
+
outputDir: string
|
|
114
|
+
): Promise<{ filePath: string; merged: boolean }> {
|
|
115
|
+
const config = getToolConfig(tool);
|
|
116
|
+
const stageLines = stageNames.map((stage) => {
|
|
117
|
+
const friendly = formatStageName(stage);
|
|
118
|
+
const stageFile = `${config.splitFilePrefix}${getStageFileName(stage)}${config.fileExtension}`;
|
|
119
|
+
const relativePath = path.posix.join(config.splitDir, stageFile);
|
|
120
|
+
return `- ${friendly}: ${relativePath}`;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const pointerBody = [
|
|
124
|
+
"SceneForge context for this tool is split across the following stage files:",
|
|
125
|
+
"",
|
|
126
|
+
...stageLines,
|
|
127
|
+
"",
|
|
128
|
+
`Open the stage file that matches the work you're doing, or run "npx sceneforge context preview --target ${tool} --stage <stage>" to inspect a specific stage.`,
|
|
129
|
+
].join("\n");
|
|
130
|
+
|
|
131
|
+
const formattedPointer = formatForTool(tool, pointerBody, {
|
|
132
|
+
includeToolHeader: true,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const combinedPath = path.join(outputDir, config.combinedFile);
|
|
136
|
+
await fs.mkdir(path.dirname(combinedPath), { recursive: true });
|
|
137
|
+
const { content: finalContent, merged } = await mergeWithExisting(
|
|
138
|
+
combinedPath,
|
|
139
|
+
formattedPointer
|
|
140
|
+
);
|
|
141
|
+
await fs.writeFile(combinedPath, finalContent, "utf-8");
|
|
142
|
+
|
|
143
|
+
return { filePath: combinedPath, merged };
|
|
144
|
+
}
|
|
145
|
+
|
|
110
146
|
/**
|
|
111
147
|
* Build context content for a specific tool and stage.
|
|
112
148
|
*/
|
|
@@ -210,6 +246,7 @@ export async function deployContext(
|
|
|
210
246
|
}
|
|
211
247
|
} else {
|
|
212
248
|
// Generate split files for each stage
|
|
249
|
+
const deployedStages: Stage[] = [];
|
|
213
250
|
for (const stg of stages) {
|
|
214
251
|
try {
|
|
215
252
|
const content = await buildContext(tool, stg, variables);
|
|
@@ -240,6 +277,7 @@ export async function deployContext(
|
|
|
240
277
|
if (merged) {
|
|
241
278
|
console.log(` [merged] ${path.relative(outputDir, absolutePath)}`);
|
|
242
279
|
}
|
|
280
|
+
deployedStages.push(stg);
|
|
243
281
|
} catch (error) {
|
|
244
282
|
results.push({
|
|
245
283
|
tool,
|
|
@@ -250,6 +288,24 @@ export async function deployContext(
|
|
|
250
288
|
});
|
|
251
289
|
}
|
|
252
290
|
}
|
|
291
|
+
if (deployedStages.length > 0) {
|
|
292
|
+
const pointerResult = await writeSplitPointer(
|
|
293
|
+
tool,
|
|
294
|
+
deployedStages,
|
|
295
|
+
outputDir
|
|
296
|
+
);
|
|
297
|
+
results.push({
|
|
298
|
+
tool,
|
|
299
|
+
filePath: pointerResult.filePath,
|
|
300
|
+
created: true,
|
|
301
|
+
skipped: false,
|
|
302
|
+
});
|
|
303
|
+
if (pointerResult.merged) {
|
|
304
|
+
console.log(
|
|
305
|
+
` [merged] ${path.relative(outputDir, pointerResult.filePath)}`
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
253
309
|
}
|
|
254
310
|
}
|
|
255
311
|
|
|
@@ -118,7 +118,7 @@ describe("context-builder", () => {
|
|
|
118
118
|
outputDir: tempDir,
|
|
119
119
|
});
|
|
120
120
|
|
|
121
|
-
expect(results.length).toBe(
|
|
121
|
+
expect(results.length).toBe(2);
|
|
122
122
|
expect(results[0].created).toBe(true);
|
|
123
123
|
|
|
124
124
|
const splitDir = path.join(tempDir, ".claude/rules");
|
|
@@ -134,9 +134,22 @@ describe("context-builder", () => {
|
|
|
134
134
|
outputDir: tempDir,
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
expect(results.length).toBe(
|
|
137
|
+
expect(results.length).toBe(5);
|
|
138
138
|
expect(results.every((r) => r.created)).toBe(true);
|
|
139
139
|
});
|
|
140
|
+
|
|
141
|
+
it("updates combined file when split files are deployed", async () => {
|
|
142
|
+
await deployContext({
|
|
143
|
+
target: "claude",
|
|
144
|
+
stage: "actions",
|
|
145
|
+
format: "split",
|
|
146
|
+
outputDir: tempDir,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const claudeFile = await fs.readFile(path.join(tempDir, "CLAUDE.md"), "utf-8");
|
|
150
|
+
expect(claudeFile).toContain("split across the following stage files");
|
|
151
|
+
expect(claudeFile).toContain(".claude/rules/stage1-actions.md");
|
|
152
|
+
});
|
|
140
153
|
});
|
|
141
154
|
|
|
142
155
|
describe("listDeployedContext", () => {
|
package/dist/index.cjs
CHANGED
|
@@ -2723,6 +2723,33 @@ async function mergeWithExisting(filePath, newContent) {
|
|
|
2723
2723
|
throw error;
|
|
2724
2724
|
}
|
|
2725
2725
|
}
|
|
2726
|
+
async function writeSplitPointer(tool, stageNames, outputDir) {
|
|
2727
|
+
const config = getToolConfig(tool);
|
|
2728
|
+
const stageLines = stageNames.map((stage) => {
|
|
2729
|
+
const friendly = formatStageName(stage);
|
|
2730
|
+
const stageFile = `${config.splitFilePrefix}${getStageFileName(stage)}${config.fileExtension}`;
|
|
2731
|
+
const relativePath = path6.posix.join(config.splitDir, stageFile);
|
|
2732
|
+
return `- ${friendly}: ${relativePath}`;
|
|
2733
|
+
});
|
|
2734
|
+
const pointerBody = [
|
|
2735
|
+
"SceneForge context for this tool is split across the following stage files:",
|
|
2736
|
+
"",
|
|
2737
|
+
...stageLines,
|
|
2738
|
+
"",
|
|
2739
|
+
`Open the stage file that matches the work you're doing, or run "npx sceneforge context preview --target ${tool} --stage <stage>" to inspect a specific stage.`
|
|
2740
|
+
].join("\n");
|
|
2741
|
+
const formattedPointer = formatForTool(tool, pointerBody, {
|
|
2742
|
+
includeToolHeader: true
|
|
2743
|
+
});
|
|
2744
|
+
const combinedPath = path6.join(outputDir, config.combinedFile);
|
|
2745
|
+
await fs6.mkdir(path6.dirname(combinedPath), { recursive: true });
|
|
2746
|
+
const { content: finalContent, merged } = await mergeWithExisting(
|
|
2747
|
+
combinedPath,
|
|
2748
|
+
formattedPointer
|
|
2749
|
+
);
|
|
2750
|
+
await fs6.writeFile(combinedPath, finalContent, "utf-8");
|
|
2751
|
+
return { filePath: combinedPath, merged };
|
|
2752
|
+
}
|
|
2726
2753
|
async function buildContext(tool, stage, variables) {
|
|
2727
2754
|
const templates = [];
|
|
2728
2755
|
const baseTemplates = await loadTemplatesByCategory("base");
|
|
@@ -2783,6 +2810,7 @@ async function deployContext(options) {
|
|
|
2783
2810
|
});
|
|
2784
2811
|
}
|
|
2785
2812
|
} else {
|
|
2813
|
+
const deployedStages = [];
|
|
2786
2814
|
for (const stg of stages) {
|
|
2787
2815
|
try {
|
|
2788
2816
|
const content = await buildContext(tool, stg, variables);
|
|
@@ -2805,6 +2833,7 @@ async function deployContext(options) {
|
|
|
2805
2833
|
if (merged) {
|
|
2806
2834
|
console.log(` [merged] ${path6.relative(outputDir, absolutePath)}`);
|
|
2807
2835
|
}
|
|
2836
|
+
deployedStages.push(stg);
|
|
2808
2837
|
} catch (error) {
|
|
2809
2838
|
results.push({
|
|
2810
2839
|
tool,
|
|
@@ -2815,6 +2844,24 @@ async function deployContext(options) {
|
|
|
2815
2844
|
});
|
|
2816
2845
|
}
|
|
2817
2846
|
}
|
|
2847
|
+
if (deployedStages.length > 0) {
|
|
2848
|
+
const pointerResult = await writeSplitPointer(
|
|
2849
|
+
tool,
|
|
2850
|
+
deployedStages,
|
|
2851
|
+
outputDir
|
|
2852
|
+
);
|
|
2853
|
+
results.push({
|
|
2854
|
+
tool,
|
|
2855
|
+
filePath: pointerResult.filePath,
|
|
2856
|
+
created: true,
|
|
2857
|
+
skipped: false
|
|
2858
|
+
});
|
|
2859
|
+
if (pointerResult.merged) {
|
|
2860
|
+
console.log(
|
|
2861
|
+
` [merged] ${path6.relative(outputDir, pointerResult.filePath)}`
|
|
2862
|
+
);
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2818
2865
|
}
|
|
2819
2866
|
}
|
|
2820
2867
|
return results;
|