@powerhousedao/ph-clint-cli 0.1.0-dev.16 → 0.1.0-dev.18

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.
@@ -3,7 +3,7 @@
3
3
  * `@clint:begin`/`@clint:end` markers so the code generator can patch
4
4
  * specific regions on subsequent runs (delta mode — future phase).
5
5
  */
6
- import { phAtLeast } from '../../spec/types.js';
6
+ import { getAppPackageName, phAtLeast } from '../../spec/types.js';
7
7
  export function buildCliTs(spec) {
8
8
  const { mastra, routine, powerhouse } = spec.features;
9
9
  const ph = powerhouse;
@@ -28,7 +28,7 @@ export function buildCliTs(spec) {
28
28
  lines.push('');
29
29
  lines.push('// @clint:begin imports');
30
30
  if (phAtLeast(ph, 'Reactor')) {
31
- lines.push(`import { documentModels } from '${spec.name}-app';`);
31
+ lines.push(`import { documentModels } from '${getAppPackageName(spec)}';`);
32
32
  }
33
33
  if (mastra.enabled) {
34
34
  lines.push(`import { createAgent } from './agents/agent.js';`);
@@ -1,18 +1,21 @@
1
1
  export function buildPublishConfigTs(spec) {
2
2
  const app = `${spec.name}-app`;
3
3
  const cli = `${spec.name}-cli`;
4
- return `import { definePublishConfig } from '@powerhousedao/ph-clint-dev/publish';
5
-
6
- export default definePublishConfig({
4
+ // The publish pipeline appends the prerelease suffix (e.g. -dev.0), so we
5
+ // only store the base semver (M.m.p) here.
6
+ const baseVersion = spec.version.replace(/-.*$/, '');
7
+ return `// Publish config — loaded by ph-clint's publish pipeline.
8
+ // definePublishConfig is an identity function; a plain export is equivalent.
9
+ export default {
7
10
  groups: {
8
11
  '${spec.name}': {
9
- version: '${spec.version}',
12
+ version: '${baseVersion}',
10
13
  packages: [
11
14
  { path: '${app}', category: 'app' },
12
15
  { path: '${cli}', category: 'cli' },
13
16
  ],
14
17
  },
15
18
  },
16
- });
19
+ };
17
20
  `;
18
21
  }
@@ -201,13 +201,20 @@ async function runUpdate(options, warn, migrated) {
201
201
  for (const p of planned) {
202
202
  if (p.initOnly) {
203
203
  // User-owned files (e.g. `src/framework.ts` with its `configSchema`)
204
- // are emitted only on create. In update mode we never overwrite them
205
- // and never re-create them if missing — the user may have deliberately
206
- // deleted or inlined them. Keep whatever hash the previous run stored
207
- // so the deletion pass (step 2) still considers them "ours".
208
- const stored = previous[p.relativePath];
209
- if (stored !== undefined)
210
- next[p.relativePath] = stored;
204
+ // are emitted only on create. In update mode we never overwrite them —
205
+ // but we DO create them if they don't yet exist on disk (e.g. first
206
+ // spec-change trigger run where no explicit `init` was run before).
207
+ const onDisk = await hashFile(p.absolutePath);
208
+ if (onDisk === null && p.content) {
209
+ await writeFileEnsuringDir(p.absolutePath, p.content);
210
+ next[p.relativePath] = hashContent(p.content);
211
+ files.push({ absolutePath: p.absolutePath, relativePath: p.relativePath });
212
+ }
213
+ else {
214
+ const stored = previous[p.relativePath];
215
+ if (stored !== undefined)
216
+ next[p.relativePath] = stored;
217
+ }
211
218
  continue;
212
219
  }
213
220
  const existing = await hashFile(p.absolutePath);
@@ -32,6 +32,27 @@ export async function runPhInit(options) {
32
32
  log(`\`${binName} init\` exited with code ${result.exitCode}. ` +
33
33
  'You can re-run it manually after resolving the issue.');
34
34
  }
35
+ // ph init creates an unscoped package name. If the spec has a scope, patch
36
+ // the app's package.json to use the scoped name so `file:` deps and publish
37
+ // both resolve correctly. Run even on non-zero exit — ph init may have
38
+ // partially succeeded and created package.json.
39
+ if (options.spec.scope) {
40
+ const appPkgJsonPath = path.join(options.appDir, 'package.json');
41
+ try {
42
+ const raw = await fs.readFile(appPkgJsonPath, 'utf8');
43
+ const pkg = JSON.parse(raw);
44
+ const scopedName = `@${options.spec.scope}/${appFolder}`;
45
+ if (pkg.name !== scopedName) {
46
+ pkg.name = scopedName;
47
+ pkg.publishConfig = { access: 'public' };
48
+ await fs.writeFile(appPkgJsonPath, JSON.stringify(pkg, null, 2) + '\n');
49
+ log(`Patched app package name to ${scopedName}`);
50
+ }
51
+ }
52
+ catch (err) {
53
+ log(`Warning: could not patch app package name: ${err instanceof Error ? err.message : String(err)}`);
54
+ }
55
+ }
35
56
  return { ran: true, exitCode: result.exitCode };
36
57
  }
37
58
  export async function runPnpmInstall(options) {
@@ -35,10 +35,11 @@ export const clintProjectPublish = defineCommand({
35
35
  logLines.push(msg);
36
36
  stdout(msg + '\n');
37
37
  };
38
- // 1. Resolve plan
38
+ // 1. Resolve plan — discover config from the target dir, not process.cwd().
39
+ const configFile = path.join(dir, 'publish.config.ts');
39
40
  const plan = await resolvePublishPlan({
40
41
  tag: input.tag,
41
- configPath: undefined, // auto-discover from dir
42
+ configPath: configFile,
42
43
  skipGitCheck: input.dryRun || input.skipGitCheck,
43
44
  log,
44
45
  });
@@ -186,6 +186,25 @@ export const specChangeTrigger = createDocumentChangeTrigger({
186
186
  log?.warn(`${TAG} ph init exited with code ${phResult.exitCode}`);
187
187
  }
188
188
  }
189
+ // Always ensure the app package name matches the spec's scope,
190
+ // even if ph init ran in a previous trigger cycle without scope.
191
+ if (spec.scope) {
192
+ try {
193
+ const raw = await fs.readFile(appPkgJson, 'utf8');
194
+ const pkg = JSON.parse(raw);
195
+ const appFolder = path.basename(result.appDir);
196
+ const scopedName = `@${spec.scope}/${appFolder}`;
197
+ if (pkg.name !== scopedName) {
198
+ pkg.name = scopedName;
199
+ pkg.publishConfig = { access: 'public' };
200
+ await fs.writeFile(appPkgJson, JSON.stringify(pkg, null, 2) + '\n');
201
+ log?.info(`${TAG} patched app package name to ${scopedName}`);
202
+ }
203
+ }
204
+ catch (err) {
205
+ log?.warn(`${TAG} could not patch app package name: ${err instanceof Error ? err.message : String(err)}`);
206
+ }
207
+ }
189
208
  }
190
209
  // Sync external skills after codegen.
191
210
  if (spec.externalSkills.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerhousedao/ph-clint-cli",
3
- "version": "0.1.0-dev.16",
3
+ "version": "0.1.0-dev.18",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@powerhousedao/ph-clint": "^0.1.0-dev.15",
29
- "@powerhousedao/ph-clint-app": "^0.1.0-dev.16",
29
+ "@powerhousedao/ph-clint-app": "^0.1.0-dev.18",
30
30
  "@mastra/core": "^1.22.0",
31
31
  "@mastra/libsql": "^1.7.4",
32
32
  "@mastra/memory": "^1.13.1",