phasegate 0.145.0 → 0.145.1

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/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.145.1] - 2026-05-11
11
+
12
+ ### Fixed
13
+
14
+ - **WI-145 post-publish dogfood** — `npx phasegate@0.145.0 init` 直後の `doctor` が `package-json-devdep-missing` で RED になる問題を修正した。
15
+ - `init` が `package.json` を作成または更新し、`devDependencies.phasegate` を現在の harness version で登録するようにした。
16
+
10
17
  ## [0.145.0] - 2026-05-11
11
18
 
12
19
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phasegate",
3
- "version": "0.145.0",
3
+ "version": "0.145.1",
4
4
  "packageManager": "pnpm@10.30.1",
5
5
  "description": "Phasegate — AI-agnostic quality defense toolkit. Enforces structural integrity between design intent and code.",
6
6
  "license": "MIT",
@@ -8,7 +8,7 @@
8
8
  * 起動時に config-foundation で設定を解決し、他Unit に注入する(Cross-unit wiring)。
9
9
  */
10
10
 
11
- import { access, readFile as fsReadFile, readlink as fsReadlink } from "node:fs/promises";
11
+ import { access, readFile as fsReadFile, readlink as fsReadlink, writeFile as fsWriteFile } from "node:fs/promises";
12
12
  import { dirname, join, resolve } from "node:path";
13
13
  import { createAdrFoundationModule } from "./adr-foundation/composition-root.js";
14
14
  import { createBiomeAstEngineModule } from "./biome-ast-engine/composition-root.js";
@@ -87,6 +87,60 @@ async function pathExists(path: string): Promise<boolean> {
87
87
  }
88
88
  }
89
89
 
90
+ interface PackageJsonDocument {
91
+ readonly [key: string]: unknown;
92
+ readonly dependencies?: unknown;
93
+ readonly devDependencies?: unknown;
94
+ }
95
+
96
+ interface PackageDependencyResult {
97
+ readonly created: boolean;
98
+ readonly updated: boolean;
99
+ readonly alreadyPresent: boolean;
100
+ readonly skipped: boolean;
101
+ }
102
+
103
+ function isJsonRecord(value: unknown): value is Record<string, unknown> {
104
+ return typeof value === "object" && value !== null && !Array.isArray(value);
105
+ }
106
+
107
+ async function ensurePhasegatePackageDependency(rootDir: string, version: string): Promise<PackageDependencyResult> {
108
+ const packageJsonPath = join(rootDir, "package.json");
109
+ let pkg: PackageJsonDocument = {};
110
+ let created = false;
111
+
112
+ try {
113
+ const raw = await fsReadFile(packageJsonPath, "utf-8");
114
+ const parsed = JSON.parse(raw) as unknown;
115
+ if (!isJsonRecord(parsed)) {
116
+ return { created: false, updated: false, alreadyPresent: false, skipped: true };
117
+ }
118
+ pkg = parsed;
119
+ } catch (error) {
120
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
121
+ return { created: false, updated: false, alreadyPresent: false, skipped: true };
122
+ }
123
+ created = true;
124
+ }
125
+
126
+ if (
127
+ (isJsonRecord(pkg.devDependencies) && pkg.devDependencies.phasegate !== undefined) ||
128
+ (isJsonRecord(pkg.dependencies) && pkg.dependencies.phasegate !== undefined)
129
+ ) {
130
+ return { created: false, updated: false, alreadyPresent: true, skipped: false };
131
+ }
132
+
133
+ pkg = {
134
+ ...pkg,
135
+ devDependencies: {
136
+ ...(isJsonRecord(pkg.devDependencies) ? pkg.devDependencies : {}),
137
+ phasegate: `^${version}`,
138
+ },
139
+ };
140
+ await fsWriteFile(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`, "utf-8");
141
+ return { created, updated: !created, alreadyPresent: false, skipped: false };
142
+ }
143
+
90
144
  function printUsage(): void {
91
145
  const usage = `
92
146
  Usage: phasegate <command> [options]
@@ -741,6 +795,7 @@ async function main(): Promise<void> {
741
795
  const deployClaude = agent === "claude" || agent === "both";
742
796
  const deployCodex = agent === "codex" || agent === "both";
743
797
  const result = await deploySkills(harnessRoot, rootDir, skillSet);
798
+ const packageResult = await ensurePhasegatePackageDependency(rootDir, result.version);
744
799
  const skillLinkResult = await deployAgentSkillLinks(rootDir, {
745
800
  claude: deployClaude,
746
801
  codex: deployCodex,
@@ -770,6 +825,7 @@ async function main(): Promise<void> {
770
825
  contentForHash: `${result.version}:${skill}`,
771
826
  })),
772
827
  await createFileManifestRecord(rootDir, join("skills", ".harness-version")),
828
+ packageResult.created || packageResult.updated ? await createFileManifestRecord(rootDir, "package.json") : null,
773
829
  configResult.created ? await createFileManifestRecord(rootDir, "phasegate.config.json") : null,
774
830
  hooksResult.settingsCreated ? await createFileManifestRecord(rootDir, join(".claude", "settings.json")) : null,
775
831
  hooksResult.hookConfigGenerated
@@ -787,6 +843,15 @@ async function main(): Promise<void> {
787
843
  console.log(
788
844
  `✓ Skills deployed to ${result.targetDir} (${result.deployedSkills.length} skills, set: ${skillSet})`,
789
845
  );
846
+ if (packageResult.created) {
847
+ console.log(`✓ package.json created with phasegate devDependency`);
848
+ } else if (packageResult.updated) {
849
+ console.log(`✓ package.json updated with phasegate devDependency`);
850
+ } else if (packageResult.alreadyPresent) {
851
+ console.log(` package.json already declares phasegate, skipped`);
852
+ } else if (packageResult.skipped) {
853
+ console.log(` package.json could not be updated, skipped`);
854
+ }
790
855
  if (configResult.created) {
791
856
  console.log(`✓ phasegate.config.json created`);
792
857
  } else {