@percepta/create 4.1.9 → 4.1.10
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/index.js +15 -16
- package/dist/index.js.map +1 -1
- package/dist/{init-CsuO_mu2.js → init-CP3IzRa6.js} +2 -2
- package/dist/{init-CsuO_mu2.js.map → init-CP3IzRa6.js.map} +1 -1
- package/dist/{register-app-B9vKTkoI.js → register-app-Dmnocuuy.js} +2 -2
- package/dist/{register-app-B9vKTkoI.js.map → register-app-Dmnocuuy.js.map} +1 -1
- package/dist/{register-os-blueprint-Gdyn0pN1.js → register-os-blueprint-Byf69wrl.js} +2 -2
- package/dist/{register-os-blueprint-Gdyn0pN1.js.map → register-os-blueprint-Byf69wrl.js.map} +1 -1
- package/dist/status-C8SBzB-K.js +27 -0
- package/dist/status-C8SBzB-K.js.map +1 -0
- package/dist/sync-Lsfz8ZH4.js +280 -0
- package/dist/sync-Lsfz8ZH4.js.map +1 -0
- package/dist/{upstream-PNL6DGtl.js → upstream-R8YDvUue.js} +6 -6
- package/dist/upstream-R8YDvUue.js.map +1 -0
- package/package.json +1 -1
- package/templates/monorepo/README.md +13 -0
- package/templates/webapp/.claude/commands/sync.md +11 -10
- package/templates/webapp/.claude/commands/upstream.md +2 -2
- package/templates/webapp/AGENTS.md +3 -3
- package/dist/status-BrK9v1yb.js +0 -48
- package/dist/status-BrK9v1yb.js.map +0 -1
- package/dist/sync-DC5DhIBT.js +0 -101
- package/dist/sync-DC5DhIBT.js.map +0 -1
- package/dist/upstream-PNL6DGtl.js.map +0 -1
package/package.json
CHANGED
|
@@ -98,6 +98,19 @@ pnpm mosaic add library my-lib
|
|
|
98
98
|
|
|
99
99
|
The customer slug and compatibility metadata live in `.mosaic-workspace.json`.
|
|
100
100
|
|
|
101
|
+
## Syncing from Mosaic
|
|
102
|
+
|
|
103
|
+
Run sync from the monorepo root to pull both workspace-level template updates
|
|
104
|
+
and package-level template updates:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
pnpm mosaic sync
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
By default, the command checks out `git@github.com:Percepta-Core/mosaic.git` at
|
|
111
|
+
`main` into a temporary local directory, generates `.mosaic-sync-context.md`
|
|
112
|
+
files for changed targets, and leaves the merge for your coding agent to apply.
|
|
113
|
+
|
|
101
114
|
## Registering the customer OS blueprint
|
|
102
115
|
|
|
103
116
|
To register this customer monorepo's OS blueprint in `Percepta-Core/infra`,
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
Sync downstream template changes into this app.
|
|
1
|
+
Sync downstream template changes into this app or its containing Mosaic monorepo.
|
|
2
2
|
|
|
3
3
|
## Steps
|
|
4
4
|
|
|
5
|
-
1.
|
|
6
|
-
2.
|
|
7
|
-
3. Run: `
|
|
5
|
+
1. Prefer running from the monorepo root so workspace-level template changes and package-level template changes are discovered together.
|
|
6
|
+
2. Read `.mosaic-workspace.json` at the monorepo root and any package `.mosaic-template.json` files to understand template versions and placeholder mappings.
|
|
7
|
+
3. Run: `pnpm mosaic sync`
|
|
8
|
+
- The CLI checks out `git@github.com:Percepta-Core/mosaic.git` at `main` into a temporary local directory.
|
|
8
9
|
4. If the command reports "Already up to date" or "No template file changes", inform the user and stop.
|
|
9
|
-
5. Read
|
|
10
|
-
6. Apply the template changes described in the context
|
|
10
|
+
5. Read every generated `.mosaic-sync-context.md` file.
|
|
11
|
+
6. Apply the template changes described in the context files:
|
|
11
12
|
- Replace placeholder tokens (e.g. `__APP_NAME__`) with actual values from the mapping table
|
|
12
|
-
- Check `mosaic-template-notes.md` for intentional divergences — preserve them
|
|
13
|
+
- Check package `mosaic-template-notes.md` files for intentional divergences — preserve them
|
|
13
14
|
- For files not modified locally, apply changes directly
|
|
14
15
|
- For files modified locally, merge intelligently, preserving local customizations
|
|
15
16
|
7. Run `pnpm install && pnpm build && pnpm lint` to verify the changes.
|
|
16
|
-
8. Update `.mosaic-
|
|
17
|
-
9. If you made decisions about merge conflicts, add notes to `mosaic-template-notes.md`.
|
|
18
|
-
10. Delete `.mosaic-sync-context.md
|
|
17
|
+
8. Update `.mosaic-workspace.json` and package `.mosaic-template.json` files as instructed by the sync contexts.
|
|
18
|
+
9. If you made decisions about merge conflicts, add notes to the relevant `mosaic-template-notes.md`.
|
|
19
|
+
10. Delete generated `.mosaic-sync-context.md` files.
|
|
19
20
|
11. Summarize what changed and ask the user to review before committing.
|
|
@@ -4,8 +4,8 @@ Propose app improvements upstream to the mosaic template.
|
|
|
4
4
|
|
|
5
5
|
1. Read `.mosaic-template.json` in the current package directory to get the template type, current version, and placeholder mappings.
|
|
6
6
|
2. Determine which files to propose upstream: use `$ARGUMENTS` if provided (space-separated file paths), otherwise ask the user which files contain improvements they want to contribute back to the template.
|
|
7
|
-
3.
|
|
8
|
-
4. Run: `npx @percepta/create upstream --mosaic-
|
|
7
|
+
3. Ask the user for the path to the local mosaic repo checkout they want to edit.
|
|
8
|
+
4. Run: `npx @percepta/create upstream --mosaic-repo-path <path> --files <file1> <file2> ...`
|
|
9
9
|
5. Read the generated `.mosaic-upstream-context.md` file.
|
|
10
10
|
6. For each file listed in the context:
|
|
11
11
|
- Compare the app version against the template version
|
|
@@ -276,9 +276,9 @@ use Ryvn releases.
|
|
|
276
276
|
|
|
277
277
|
## Template Sync
|
|
278
278
|
|
|
279
|
-
This app tracks its template origin in `.mosaic-template.json`. Two Claude commands are available:
|
|
279
|
+
This app tracks its template origin in `.mosaic-template.json`. The monorepo root tracks workspace template compatibility in `.mosaic-workspace.json`. Two Claude commands are available:
|
|
280
280
|
|
|
281
|
-
- **`/sync`** — pull downstream changes from the
|
|
281
|
+
- **`/sync`** — pull downstream changes from the Mosaic monorepo template and package templates
|
|
282
282
|
- **`/upstream`** — propose app improvements back to the mosaic template
|
|
283
283
|
|
|
284
|
-
Both commands use `@percepta/create` CLI under the hood. Check `mosaic-template-notes.md` for documented intentional divergences from the template.
|
|
284
|
+
Both commands use `@percepta/create` CLI under the hood. `sync` uses a temporary checkout of `git@github.com:Percepta-Core/mosaic.git` at `main`. Check `mosaic-template-notes.md` for documented intentional divergences from the template.
|
package/dist/status-BrK9v1yb.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { c as readManifest } from "./index.js";
|
|
2
|
-
import { i as getTemplateVersionFromTag, n as getLatestTemplateTag } from "./git-ops-BNpQnEc1.js";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import chalk from "chalk";
|
|
5
|
-
//#region src/commands/status.ts
|
|
6
|
-
async function statusCommand(options) {
|
|
7
|
-
const cwd = process.cwd();
|
|
8
|
-
try {
|
|
9
|
-
const manifest = await readManifest(cwd);
|
|
10
|
-
console.log();
|
|
11
|
-
console.log(chalk.bold("Mosaic Template Status"));
|
|
12
|
-
console.log();
|
|
13
|
-
console.log(chalk.dim(" Template type:"), manifest.templateType);
|
|
14
|
-
console.log(chalk.dim(" Current version:"), manifest.templateVersion);
|
|
15
|
-
console.log(chalk.dim(" Template commit:"), manifest.templateCommit);
|
|
16
|
-
console.log(chalk.dim(" Created:"), manifest.createdAt);
|
|
17
|
-
if (manifest.lastSyncedAt) console.log(chalk.dim(" Last synced:"), manifest.lastSyncedAt);
|
|
18
|
-
const rawPath = options.mosaicTemplatePath || process.env.MOSAIC_TEMPLATE_PATH;
|
|
19
|
-
const mosaicTemplatePath = rawPath ? path.resolve(rawPath) : void 0;
|
|
20
|
-
if (mosaicTemplatePath) {
|
|
21
|
-
const latestTag = getLatestTemplateTag(manifest.templateType, mosaicTemplatePath);
|
|
22
|
-
if (latestTag) {
|
|
23
|
-
const latestVersion = getTemplateVersionFromTag(latestTag);
|
|
24
|
-
console.log(chalk.dim(" Latest version:"), latestVersion);
|
|
25
|
-
console.log();
|
|
26
|
-
if (latestVersion !== manifest.templateVersion) {
|
|
27
|
-
console.log(chalk.yellow(` Update available: ${manifest.templateVersion} → ${latestVersion}`));
|
|
28
|
-
console.log(chalk.dim(" Run:"), `create sync --mosaic-template-path ${mosaicTemplatePath}`);
|
|
29
|
-
} else console.log(chalk.green(" Up to date"));
|
|
30
|
-
} else {
|
|
31
|
-
console.log();
|
|
32
|
-
console.log(chalk.yellow(" No template tags found in mosaic repo."));
|
|
33
|
-
console.log(chalk.dim(" Run:"), `cd ${mosaicTemplatePath} && pnpm template:tag`);
|
|
34
|
-
}
|
|
35
|
-
} else {
|
|
36
|
-
console.log();
|
|
37
|
-
console.log(chalk.dim(" Use --mosaic-template-path or set MOSAIC_TEMPLATE_PATH to check for updates"));
|
|
38
|
-
}
|
|
39
|
-
console.log();
|
|
40
|
-
} catch (error) {
|
|
41
|
-
console.error(chalk.red(error.message));
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
//#endregion
|
|
46
|
-
export { statusCommand };
|
|
47
|
-
|
|
48
|
-
//# sourceMappingURL=status-BrK9v1yb.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"status-BrK9v1yb.js","names":[],"sources":["../src/commands/status.ts"],"sourcesContent":["import path from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n getLatestTemplateTag,\n getTemplateVersionFromTag,\n} from \"../utils/git-ops.js\";\nimport { readManifest } from \"../utils/manifest.js\";\n\nexport interface StatusOptions {\n mosaicTemplatePath?: string;\n}\n\nexport async function statusCommand(options: StatusOptions): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const manifest = await readManifest(cwd);\n\n console.log();\n console.log(chalk.bold(\"Mosaic Template Status\"));\n console.log();\n console.log(chalk.dim(\" Template type:\"), manifest.templateType);\n console.log(chalk.dim(\" Current version:\"), manifest.templateVersion);\n console.log(chalk.dim(\" Template commit:\"), manifest.templateCommit);\n console.log(chalk.dim(\" Created:\"), manifest.createdAt);\n if (manifest.lastSyncedAt) {\n console.log(chalk.dim(\" Last synced:\"), manifest.lastSyncedAt);\n }\n\n const rawPath =\n options.mosaicTemplatePath || process.env.MOSAIC_TEMPLATE_PATH;\n const mosaicTemplatePath = rawPath ? path.resolve(rawPath) : undefined;\n\n if (mosaicTemplatePath) {\n const latestTag = getLatestTemplateTag(\n manifest.templateType,\n mosaicTemplatePath,\n );\n if (latestTag) {\n const latestVersion = getTemplateVersionFromTag(latestTag);\n console.log(chalk.dim(\" Latest version:\"), latestVersion);\n console.log();\n\n if (latestVersion !== manifest.templateVersion) {\n console.log(\n chalk.yellow(\n ` Update available: ${manifest.templateVersion} → ${latestVersion}`,\n ),\n );\n console.log(\n chalk.dim(\" Run:\"),\n `create sync --mosaic-template-path ${mosaicTemplatePath}`,\n );\n } else {\n console.log(chalk.green(\" Up to date\"));\n }\n } else {\n console.log();\n console.log(chalk.yellow(\" No template tags found in mosaic repo.\"));\n console.log(\n chalk.dim(\" Run:\"),\n `cd ${mosaicTemplatePath} && pnpm template:tag`,\n );\n }\n } else {\n console.log();\n console.log(\n chalk.dim(\n \" Use --mosaic-template-path or set MOSAIC_TEMPLATE_PATH to check for updates\",\n ),\n );\n }\n\n console.log();\n } catch (error) {\n console.error(chalk.red((error as Error).message));\n process.exit(1);\n }\n}\n"],"mappings":";;;;;AAYA,eAAsB,cAAc,SAAuC;CACzE,MAAM,MAAM,QAAQ,IAAI;CAExB,IAAI;EACF,MAAM,WAAW,MAAM,aAAa,GAAG;EAEvC,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,KAAK,wBAAwB,CAAC;EAChD,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,IAAI,kBAAkB,GAAG,SAAS,YAAY;EAChE,QAAQ,IAAI,MAAM,IAAI,oBAAoB,GAAG,SAAS,eAAe;EACrE,QAAQ,IAAI,MAAM,IAAI,oBAAoB,GAAG,SAAS,cAAc;EACpE,QAAQ,IAAI,MAAM,IAAI,YAAY,GAAG,SAAS,SAAS;EACvD,IAAI,SAAS,cACX,QAAQ,IAAI,MAAM,IAAI,gBAAgB,GAAG,SAAS,YAAY;EAGhE,MAAM,UACJ,QAAQ,sBAAsB,QAAQ,IAAI;EAC5C,MAAM,qBAAqB,UAAU,KAAK,QAAQ,OAAO,IAAI,KAAA;EAE7D,IAAI,oBAAoB;GACtB,MAAM,YAAY,qBAChB,SAAS,cACT,kBACF;GACA,IAAI,WAAW;IACb,MAAM,gBAAgB,0BAA0B,SAAS;IACzD,QAAQ,IAAI,MAAM,IAAI,mBAAmB,GAAG,aAAa;IACzD,QAAQ,IAAI;IAEZ,IAAI,kBAAkB,SAAS,iBAAiB;KAC9C,QAAQ,IACN,MAAM,OACJ,uBAAuB,SAAS,gBAAgB,KAAK,eACvD,CACF;KACA,QAAQ,IACN,MAAM,IAAI,QAAQ,GAClB,sCAAsC,oBACxC;IACF,OACE,QAAQ,IAAI,MAAM,MAAM,cAAc,CAAC;GAE3C,OAAO;IACL,QAAQ,IAAI;IACZ,QAAQ,IAAI,MAAM,OAAO,0CAA0C,CAAC;IACpE,QAAQ,IACN,MAAM,IAAI,QAAQ,GAClB,MAAM,mBAAmB,sBAC3B;GACF;EACF,OAAO;GACL,QAAQ,IAAI;GACZ,QAAQ,IACN,MAAM,IACJ,+EACF,CACF;EACF;EAEA,QAAQ,IAAI;CACd,SAAS,OAAO;EACd,QAAQ,MAAM,MAAM,IAAK,MAAgB,OAAO,CAAC;EACjD,QAAQ,KAAK,CAAC;CAChB;AACF"}
|
package/dist/sync-DC5DhIBT.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { c as readManifest, l as resolveMosaicTemplatePath } from "./index.js";
|
|
2
|
-
import { i as getTemplateVersionFromTag, n as getLatestTemplateTag, r as getTemplateDiff } from "./git-ops-BNpQnEc1.js";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import chalk from "chalk";
|
|
5
|
-
import fs from "fs-extra";
|
|
6
|
-
//#region src/commands/sync.ts
|
|
7
|
-
function generateSyncContext(manifest, toVersion, diff, notes) {
|
|
8
|
-
let content = `# Mosaic Sync Context
|
|
9
|
-
|
|
10
|
-
## App Info
|
|
11
|
-
- **Template:** ${manifest.templateType}
|
|
12
|
-
- **Current version:** ${manifest.templateVersion}
|
|
13
|
-
- **Target version:** ${toVersion}
|
|
14
|
-
|
|
15
|
-
## Placeholder Mappings
|
|
16
|
-
|
|
17
|
-
When applying template changes, replace these placeholder tokens with the actual values:
|
|
18
|
-
|
|
19
|
-
| Placeholder | Value |
|
|
20
|
-
|------------|-------|
|
|
21
|
-
${Object.entries(manifest.placeholders).map(([k, v]) => `| \`${k}\` | \`${v}\` |`).join("\n")}
|
|
22
|
-
|
|
23
|
-
## Template Changes (${manifest.templateVersion} → ${toVersion})
|
|
24
|
-
|
|
25
|
-
\`\`\`diff
|
|
26
|
-
${diff}
|
|
27
|
-
\`\`\`
|
|
28
|
-
`;
|
|
29
|
-
if (notes.trim()) content += `
|
|
30
|
-
## Divergence Notes (from mosaic-template-notes.md)
|
|
31
|
-
|
|
32
|
-
${notes}
|
|
33
|
-
`;
|
|
34
|
-
content += `
|
|
35
|
-
## Instructions
|
|
36
|
-
|
|
37
|
-
1. Apply the template changes above to this app
|
|
38
|
-
2. When you see placeholder tokens (e.g. \`__APP_NAME__\`), replace them with the actual values from the mapping table
|
|
39
|
-
3. Check the divergence notes — preserve intentional divergences
|
|
40
|
-
4. For files not modified locally: apply changes directly
|
|
41
|
-
5. For files modified locally: merge intelligently, preserving local customizations
|
|
42
|
-
6. After applying all changes, run: \`pnpm install && pnpm build && pnpm lint\`
|
|
43
|
-
7. Update \`.mosaic-template.json\`: set \`templateVersion\` to \`"${toVersion}"\` and update \`templateCommit\`
|
|
44
|
-
8. If you made decisions about merge conflicts, add notes to \`mosaic-template-notes.md\`
|
|
45
|
-
9. Delete this file (\`.mosaic-sync-context.md\`) when done
|
|
46
|
-
`;
|
|
47
|
-
return content;
|
|
48
|
-
}
|
|
49
|
-
async function syncCommand(options) {
|
|
50
|
-
const cwd = process.cwd();
|
|
51
|
-
try {
|
|
52
|
-
const manifest = await readManifest(cwd);
|
|
53
|
-
const mosaicTemplatePath = resolveMosaicTemplatePath(options);
|
|
54
|
-
const fromTag = `template/${manifest.templateType}/${manifest.templateVersion}`;
|
|
55
|
-
let toTag;
|
|
56
|
-
if (options.to) toTag = `template/${manifest.templateType}/${options.to}`;
|
|
57
|
-
else {
|
|
58
|
-
const latest = getLatestTemplateTag(manifest.templateType, mosaicTemplatePath);
|
|
59
|
-
if (!latest) {
|
|
60
|
-
console.error(chalk.red("No template tags found. Run 'pnpm template:tag' in the mosaic repo first."));
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
toTag = latest;
|
|
64
|
-
}
|
|
65
|
-
const toVersion = getTemplateVersionFromTag(toTag);
|
|
66
|
-
if (toVersion === manifest.templateVersion) {
|
|
67
|
-
console.log(chalk.green("Already up to date."));
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
const diff = getTemplateDiff(mosaicTemplatePath, manifest.source.templatePath, fromTag, toTag);
|
|
71
|
-
if (!diff.trim()) {
|
|
72
|
-
console.log(chalk.green("No template file changes between versions."));
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
const notesPath = path.join(cwd, "mosaic-template-notes.md");
|
|
76
|
-
let notes = "";
|
|
77
|
-
if (await fs.pathExists(notesPath)) notes = await fs.readFile(notesPath, "utf-8");
|
|
78
|
-
const context = generateSyncContext(manifest, toVersion, diff, notes);
|
|
79
|
-
const contextPath = path.join(cwd, ".mosaic-sync-context.md");
|
|
80
|
-
await fs.writeFile(contextPath, context);
|
|
81
|
-
console.log();
|
|
82
|
-
console.log(chalk.bold("Sync Context Generated"));
|
|
83
|
-
console.log();
|
|
84
|
-
console.log(chalk.dim(" From:"), manifest.templateVersion);
|
|
85
|
-
console.log(chalk.dim(" To:"), toVersion);
|
|
86
|
-
console.log(chalk.dim(" Context file:"), ".mosaic-sync-context.md");
|
|
87
|
-
console.log();
|
|
88
|
-
console.log("Next steps:");
|
|
89
|
-
console.log(chalk.dim(" 1."), "Open Claude Code in this directory");
|
|
90
|
-
console.log(chalk.dim(" 2."), "Tell Claude: \"Read .mosaic-sync-context.md and apply the template changes\"");
|
|
91
|
-
console.log(chalk.dim(" 3."), "Review Claude's changes, then delete .mosaic-sync-context.md");
|
|
92
|
-
console.log();
|
|
93
|
-
} catch (error) {
|
|
94
|
-
console.error(chalk.red(error.message));
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
//#endregion
|
|
99
|
-
export { syncCommand };
|
|
100
|
-
|
|
101
|
-
//# sourceMappingURL=sync-DC5DhIBT.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sync-DC5DhIBT.js","names":[],"sources":["../src/commands/sync.ts"],"sourcesContent":["import path from \"node:path\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport {\n getLatestTemplateTag,\n getTemplateVersionFromTag,\n getTemplateDiff,\n} from \"../utils/git-ops.js\";\nimport {\n readManifest,\n resolveMosaicTemplatePath,\n type MosaicManifest,\n} from \"../utils/manifest.js\";\n\nexport interface SyncOptions {\n mosaicTemplatePath?: string;\n to?: string;\n}\n\nfunction generateSyncContext(\n manifest: MosaicManifest,\n toVersion: string,\n diff: string,\n notes: string,\n): string {\n let content = `# Mosaic Sync Context\n\n## App Info\n- **Template:** ${manifest.templateType}\n- **Current version:** ${manifest.templateVersion}\n- **Target version:** ${toVersion}\n\n## Placeholder Mappings\n\nWhen applying template changes, replace these placeholder tokens with the actual values:\n\n| Placeholder | Value |\n|------------|-------|\n${Object.entries(manifest.placeholders)\n .map(([k, v]) => `| \\`${k}\\` | \\`${v}\\` |`)\n .join(\"\\n\")}\n\n## Template Changes (${manifest.templateVersion} → ${toVersion})\n\n\\`\\`\\`diff\n${diff}\n\\`\\`\\`\n`;\n\n if (notes.trim()) {\n content += `\n## Divergence Notes (from mosaic-template-notes.md)\n\n${notes}\n`;\n }\n\n content += `\n## Instructions\n\n1. Apply the template changes above to this app\n2. When you see placeholder tokens (e.g. \\`__APP_NAME__\\`), replace them with the actual values from the mapping table\n3. Check the divergence notes — preserve intentional divergences\n4. For files not modified locally: apply changes directly\n5. For files modified locally: merge intelligently, preserving local customizations\n6. After applying all changes, run: \\`pnpm install && pnpm build && pnpm lint\\`\n7. Update \\`.mosaic-template.json\\`: set \\`templateVersion\\` to \\`\"${toVersion}\"\\` and update \\`templateCommit\\`\n8. If you made decisions about merge conflicts, add notes to \\`mosaic-template-notes.md\\`\n9. Delete this file (\\`.mosaic-sync-context.md\\`) when done\n`;\n\n return content;\n}\n\nexport async function syncCommand(options: SyncOptions): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const manifest = await readManifest(cwd);\n const mosaicTemplatePath = resolveMosaicTemplatePath(options);\n\n const fromTag = `template/${manifest.templateType}/${manifest.templateVersion}`;\n\n let toTag: string;\n if (options.to) {\n toTag = `template/${manifest.templateType}/${options.to}`;\n } else {\n const latest = getLatestTemplateTag(\n manifest.templateType,\n mosaicTemplatePath,\n );\n if (!latest) {\n console.error(\n chalk.red(\n \"No template tags found. Run 'pnpm template:tag' in the mosaic repo first.\",\n ),\n );\n process.exit(1);\n }\n toTag = latest;\n }\n\n const toVersion = getTemplateVersionFromTag(toTag);\n\n if (toVersion === manifest.templateVersion) {\n console.log(chalk.green(\"Already up to date.\"));\n return;\n }\n\n const diff = getTemplateDiff(\n mosaicTemplatePath,\n manifest.source.templatePath,\n fromTag,\n toTag,\n );\n\n if (!diff.trim()) {\n console.log(chalk.green(\"No template file changes between versions.\"));\n return;\n }\n\n // Read mosaic-template-notes.md if it exists\n const notesPath = path.join(cwd, \"mosaic-template-notes.md\");\n let notes = \"\";\n if (await fs.pathExists(notesPath)) {\n notes = await fs.readFile(notesPath, \"utf-8\");\n }\n\n const context = generateSyncContext(manifest, toVersion, diff, notes);\n const contextPath = path.join(cwd, \".mosaic-sync-context.md\");\n await fs.writeFile(contextPath, context);\n\n console.log();\n console.log(chalk.bold(\"Sync Context Generated\"));\n console.log();\n console.log(chalk.dim(\" From:\"), manifest.templateVersion);\n console.log(chalk.dim(\" To:\"), toVersion);\n console.log(chalk.dim(\" Context file:\"), \".mosaic-sync-context.md\");\n console.log();\n console.log(\"Next steps:\");\n console.log(chalk.dim(\" 1.\"), \"Open Claude Code in this directory\");\n console.log(\n chalk.dim(\" 2.\"),\n 'Tell Claude: \"Read .mosaic-sync-context.md and apply the template changes\"',\n );\n console.log(\n chalk.dim(\" 3.\"),\n \"Review Claude's changes, then delete .mosaic-sync-context.md\",\n );\n console.log();\n } catch (error) {\n console.error(chalk.red((error as Error).message));\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;AAmBA,SAAS,oBACP,UACA,WACA,MACA,OACQ;CACR,IAAI,UAAU;;;kBAGE,SAAS,aAAa;yBACf,SAAS,gBAAgB;wBAC1B,UAAU;;;;;;;;EAQhC,OAAO,QAAQ,SAAS,YAAY,EACnC,KAAK,CAAC,GAAG,OAAO,OAAO,EAAE,SAAS,EAAE,KAAK,EACzC,KAAK,IAAI,EAAE;;uBAES,SAAS,gBAAgB,KAAK,UAAU;;;EAG7D,KAAK;;;CAIL,IAAI,MAAM,KAAK,GACb,WAAW;;;EAGb,MAAM;;CAIN,WAAW;;;;;;;;;qEASwD,UAAU;;;;CAK7E,OAAO;AACT;AAEA,eAAsB,YAAY,SAAqC;CACrE,MAAM,MAAM,QAAQ,IAAI;CAExB,IAAI;EACF,MAAM,WAAW,MAAM,aAAa,GAAG;EACvC,MAAM,qBAAqB,0BAA0B,OAAO;EAE5D,MAAM,UAAU,YAAY,SAAS,aAAa,GAAG,SAAS;EAE9D,IAAI;EACJ,IAAI,QAAQ,IACV,QAAQ,YAAY,SAAS,aAAa,GAAG,QAAQ;OAChD;GACL,MAAM,SAAS,qBACb,SAAS,cACT,kBACF;GACA,IAAI,CAAC,QAAQ;IACX,QAAQ,MACN,MAAM,IACJ,2EACF,CACF;IACA,QAAQ,KAAK,CAAC;GAChB;GACA,QAAQ;EACV;EAEA,MAAM,YAAY,0BAA0B,KAAK;EAEjD,IAAI,cAAc,SAAS,iBAAiB;GAC1C,QAAQ,IAAI,MAAM,MAAM,qBAAqB,CAAC;GAC9C;EACF;EAEA,MAAM,OAAO,gBACX,oBACA,SAAS,OAAO,cAChB,SACA,KACF;EAEA,IAAI,CAAC,KAAK,KAAK,GAAG;GAChB,QAAQ,IAAI,MAAM,MAAM,4CAA4C,CAAC;GACrE;EACF;EAGA,MAAM,YAAY,KAAK,KAAK,KAAK,0BAA0B;EAC3D,IAAI,QAAQ;EACZ,IAAI,MAAM,GAAG,WAAW,SAAS,GAC/B,QAAQ,MAAM,GAAG,SAAS,WAAW,OAAO;EAG9C,MAAM,UAAU,oBAAoB,UAAU,WAAW,MAAM,KAAK;EACpE,MAAM,cAAc,KAAK,KAAK,KAAK,yBAAyB;EAC5D,MAAM,GAAG,UAAU,aAAa,OAAO;EAEvC,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,KAAK,wBAAwB,CAAC;EAChD,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,IAAI,SAAS,GAAG,SAAS,eAAe;EAC1D,QAAQ,IAAI,MAAM,IAAI,OAAO,GAAG,SAAS;EACzC,QAAQ,IAAI,MAAM,IAAI,iBAAiB,GAAG,yBAAyB;EACnE,QAAQ,IAAI;EACZ,QAAQ,IAAI,aAAa;EACzB,QAAQ,IAAI,MAAM,IAAI,MAAM,GAAG,oCAAoC;EACnE,QAAQ,IACN,MAAM,IAAI,MAAM,GAChB,8EACF;EACA,QAAQ,IACN,MAAM,IAAI,MAAM,GAChB,8DACF;EACA,QAAQ,IAAI;CACd,SAAS,OAAO;EACd,QAAQ,MAAM,MAAM,IAAK,MAAgB,OAAO,CAAC;EACjD,QAAQ,KAAK,CAAC;CAChB;AACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"upstream-PNL6DGtl.js","names":[],"sources":["../src/commands/upstream.ts"],"sourcesContent":["import path from \"node:path\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport { getFileAtTag } from \"../utils/git-ops.js\";\nimport {\n readManifest,\n resolveMosaicTemplatePath,\n type MosaicManifest,\n} from \"../utils/manifest.js\";\n\nexport interface UpstreamOptions {\n mosaicTemplatePath?: string;\n files?: string[];\n}\n\nasync function generateUpstreamContext(\n manifest: MosaicManifest,\n mosaicTemplatePath: string,\n tag: string,\n appDir: string,\n files: string[],\n): Promise<string> {\n let content = `# Mosaic Upstream Context\n\n## App Info\n- **App name:** ${manifest.placeholders.__APP_NAME__ || \"unknown\"}\n- **Template:** ${manifest.templateType}\n- **Template version:** ${manifest.templateVersion}\n\n## Placeholder Mappings\n\nWhen generalizing app code back to template, replace these values with placeholder tokens:\n\n| Value | Placeholder |\n|-------|------------|\n${Object.entries(manifest.placeholders)\n .sort((a, b) => b[1].length - a[1].length) // longest first to avoid partial matches\n .map(([k, v]) => `| \\`${v}\\` | \\`${k}\\` |`)\n .join(\"\\n\")}\n\n## Files to Review\n\n`;\n\n for (const file of files) {\n const appFilePath = path.resolve(appDir, file);\n const templateRelPath = `${manifest.source.templatePath}/${file}`;\n\n const appContent = (await fs.pathExists(appFilePath))\n ? await fs.readFile(appFilePath, \"utf-8\")\n : null;\n const templateContent = getFileAtTag(\n mosaicTemplatePath,\n tag,\n templateRelPath,\n );\n\n content += `### ${file}\\n\\n`;\n\n if (!templateContent && appContent) {\n content += `**New file** (not in template at ${manifest.templateVersion})\\n\\n`;\n content += `\\`\\`\\`\\n${appContent}\\n\\`\\`\\`\\n\\n`;\n } else if (templateContent && !appContent) {\n content += `**Deleted** (exists in template but not in app)\\n\\n`;\n } else if (appContent && templateContent) {\n content += `**App version:**\\n\\`\\`\\`\\n${appContent}\\n\\`\\`\\`\\n\\n`;\n content += `**Template version (at ${manifest.templateVersion}):**\\n\\`\\`\\`\\n${templateContent}\\n\\`\\`\\`\\n\\n`;\n } else {\n content += `**Not found** (file does not exist in app or template)\\n\\n`;\n }\n }\n\n content += `## Instructions\n\n1. Review each file above\n2. Determine which changes are generalizable (useful for all apps) vs app-specific\n3. For generalizable changes: apply them to the template at \\`${manifest.source.templatePath}/\\`\n4. When applying, replace app-specific values with placeholders using the mapping table above (replace longest values first)\n5. After applying, bump the version in \\`packages/blueberry/template-versions.json\\`\n6. Run \\`pnpm template:tag\\` to create the new version tag\n7. Delete this file (\\`.mosaic-upstream-context.md\\`) when done\n`;\n\n return content;\n}\n\nexport async function upstreamCommand(options: UpstreamOptions): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const manifest = await readManifest(cwd);\n const mosaicTemplatePath = resolveMosaicTemplatePath(options);\n\n if (!options.files || options.files.length === 0) {\n console.error(\n chalk.red(\"Specify files with --files <file1> <file2> ...\"),\n );\n console.log(\n chalk.dim(\n \" Example: create upstream --files src/config/getEnvConfig.ts\",\n ),\n );\n process.exit(1);\n }\n\n const tag = `template/${manifest.templateType}/${manifest.templateVersion}`;\n\n const context = await generateUpstreamContext(\n manifest,\n mosaicTemplatePath,\n tag,\n cwd,\n options.files,\n );\n const contextPath = path.join(cwd, \".mosaic-upstream-context.md\");\n await fs.writeFile(contextPath, context);\n\n console.log();\n console.log(chalk.bold(\"Upstream Context Generated\"));\n console.log();\n console.log(chalk.dim(\" Files:\"), options.files.join(\", \"));\n console.log(chalk.dim(\" Context file:\"), \".mosaic-upstream-context.md\");\n console.log();\n console.log(\"Next steps:\");\n console.log(chalk.dim(\" 1.\"), \"Open Claude Code in the mosaic repo\");\n console.log(\n chalk.dim(\" 2.\"),\n `Tell Claude: \"Read ${path.resolve(cwd, \".mosaic-upstream-context.md\")} and apply generalizable changes to the template\"`,\n );\n console.log(chalk.dim(\" 3.\"), \"Review Claude's changes to the template\");\n console.log();\n } catch (error) {\n console.error(chalk.red((error as Error).message));\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;AAeA,eAAe,wBACb,UACA,oBACA,KACA,QACA,OACiB;CACjB,IAAI,UAAU;;;kBAGE,SAAS,aAAa,gBAAgB,UAAU;kBAChD,SAAS,aAAa;0BACd,SAAS,gBAAgB;;;;;;;;EAQjD,OAAO,QAAQ,SAAS,YAAY,EACnC,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,EAAE,GAAG,MAAM,EACxC,KAAK,CAAC,GAAG,OAAO,OAAO,EAAE,SAAS,EAAE,KAAK,EACzC,KAAK,IAAI,EAAE;;;;;CAMZ,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,cAAc,KAAK,QAAQ,QAAQ,IAAI;EAC7C,MAAM,kBAAkB,GAAG,SAAS,OAAO,aAAa,GAAG;EAE3D,MAAM,aAAc,MAAM,GAAG,WAAW,WAAW,IAC/C,MAAM,GAAG,SAAS,aAAa,OAAO,IACtC;EACJ,MAAM,kBAAkB,aACtB,oBACA,KACA,eACF;EAEA,WAAW,OAAO,KAAK;EAEvB,IAAI,CAAC,mBAAmB,YAAY;GAClC,WAAW,oCAAoC,SAAS,gBAAgB;GACxE,WAAW,WAAW,WAAW;EACnC,OAAO,IAAI,mBAAmB,CAAC,YAC7B,WAAW;OACN,IAAI,cAAc,iBAAiB;GACxC,WAAW,6BAA6B,WAAW;GACnD,WAAW,0BAA0B,SAAS,gBAAgB,gBAAgB,gBAAgB;EAChG,OACE,WAAW;CAEf;CAEA,WAAW;;;;gEAImD,SAAS,OAAO,aAAa;;;;;;CAO3F,OAAO;AACT;AAEA,eAAsB,gBAAgB,SAAyC;CAC7E,MAAM,MAAM,QAAQ,IAAI;CAExB,IAAI;EACF,MAAM,WAAW,MAAM,aAAa,GAAG;EACvC,MAAM,qBAAqB,0BAA0B,OAAO;EAE5D,IAAI,CAAC,QAAQ,SAAS,QAAQ,MAAM,WAAW,GAAG;GAChD,QAAQ,MACN,MAAM,IAAI,gDAAgD,CAC5D;GACA,QAAQ,IACN,MAAM,IACJ,+DACF,CACF;GACA,QAAQ,KAAK,CAAC;EAChB;EAIA,MAAM,UAAU,MAAM,wBACpB,UACA,oBACA,YALsB,SAAS,aAAa,GAAG,SAAS,mBAMxD,KACA,QAAQ,KACV;EACA,MAAM,cAAc,KAAK,KAAK,KAAK,6BAA6B;EAChE,MAAM,GAAG,UAAU,aAAa,OAAO;EAEvC,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,KAAK,4BAA4B,CAAC;EACpD,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,IAAI,UAAU,GAAG,QAAQ,MAAM,KAAK,IAAI,CAAC;EAC3D,QAAQ,IAAI,MAAM,IAAI,iBAAiB,GAAG,6BAA6B;EACvE,QAAQ,IAAI;EACZ,QAAQ,IAAI,aAAa;EACzB,QAAQ,IAAI,MAAM,IAAI,MAAM,GAAG,qCAAqC;EACpE,QAAQ,IACN,MAAM,IAAI,MAAM,GAChB,sBAAsB,KAAK,QAAQ,KAAK,6BAA6B,EAAE,kDACzE;EACA,QAAQ,IAAI,MAAM,IAAI,MAAM,GAAG,yCAAyC;EACxE,QAAQ,IAAI;CACd,SAAS,OAAO;EACd,QAAQ,MAAM,MAAM,IAAK,MAAgB,OAAO,CAAC;EACjD,QAAQ,KAAK,CAAC;CAChB;AACF"}
|