@chiendt/ack-cli 1.3.0-dev.5 → 1.3.0-dev.6

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/cli-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "1.3.0-dev.5",
3
- "generatedAt": "2026-06-10T04:30:16.913Z",
2
+ "version": "1.3.0-dev.6",
3
+ "generatedAt": "2026-06-10T16:46:45.876Z",
4
4
  "commands": {
5
5
  "agents": {
6
6
  "name": "agents",
package/dist/index.js CHANGED
@@ -63756,7 +63756,7 @@ var package_default;
63756
63756
  var init_package = __esm(() => {
63757
63757
  package_default = {
63758
63758
  name: "@chiendt/ack-cli",
63759
- version: "1.3.0-dev.5",
63759
+ version: "1.3.0-dev.6",
63760
63760
  description: "ACK CLI - tool for bootstrapping and updating ACK kits (Claude Code agent kits)",
63761
63761
  type: "module",
63762
63762
  repository: {
@@ -72527,6 +72527,221 @@ var init_github_api_checker = __esm(() => {
72527
72527
  init_types3();
72528
72528
  });
72529
72529
 
72530
+ // src/domains/installation/npmrc-bootstrap.ts
72531
+ import { promises as fs10 } from "node:fs";
72532
+ import { dirname as dirname29 } from "node:path";
72533
+ function mergeNpmrcEntries(existing, entries) {
72534
+ const keys = new Set(Object.keys(entries));
72535
+ const seenKeys = new Set;
72536
+ const lines = existing.split(`
72537
+ `);
72538
+ const out = [];
72539
+ for (const line of lines) {
72540
+ const stripped = line.trim();
72541
+ if (stripped === "" || stripped.startsWith(";") || stripped.startsWith("#")) {
72542
+ out.push(line);
72543
+ continue;
72544
+ }
72545
+ const eq = line.indexOf("=");
72546
+ if (eq < 0) {
72547
+ out.push(line);
72548
+ continue;
72549
+ }
72550
+ const key = line.slice(0, eq).trim();
72551
+ if (keys.has(key)) {
72552
+ seenKeys.add(key);
72553
+ out.push(`${key}=${entries[key]}`);
72554
+ } else {
72555
+ out.push(line);
72556
+ }
72557
+ }
72558
+ const additions = [];
72559
+ for (const key of keys) {
72560
+ if (!seenKeys.has(key)) {
72561
+ additions.push(`${key}=${entries[key]}`);
72562
+ }
72563
+ }
72564
+ let result = out.join(`
72565
+ `);
72566
+ if (additions.length > 0) {
72567
+ if (result.length > 0 && !result.endsWith(`
72568
+ `))
72569
+ result += `
72570
+ `;
72571
+ result += `${additions.join(`
72572
+ `)}
72573
+ `;
72574
+ } else if (result.length > 0 && !result.endsWith(`
72575
+ `)) {
72576
+ result += `
72577
+ `;
72578
+ }
72579
+ return result;
72580
+ }
72581
+ async function writeNpmrc(path8, entries, opts = {}) {
72582
+ let existing = "";
72583
+ let hadFile = false;
72584
+ try {
72585
+ existing = await fs10.readFile(path8, "utf8");
72586
+ hadFile = true;
72587
+ } catch (err) {
72588
+ if (err.code !== "ENOENT")
72589
+ throw err;
72590
+ }
72591
+ const merged = mergeNpmrcEntries(existing, entries);
72592
+ if (merged === existing) {
72593
+ return { written: false, backupPath: null, finalPath: path8, noChange: true };
72594
+ }
72595
+ let backupPath = null;
72596
+ if (hadFile) {
72597
+ const now = opts.now?.() ?? new Date;
72598
+ const stamp = now.toISOString().replace(/[:.]/g, "-");
72599
+ backupPath = `${path8}.bak.${stamp}`;
72600
+ await fs10.copyFile(path8, backupPath);
72601
+ }
72602
+ await fs10.mkdir(dirname29(path8), { recursive: true });
72603
+ const tmp = `${path8}.tmp.${process.pid}`;
72604
+ await fs10.writeFile(tmp, merged, { mode: 384 });
72605
+ await fs10.rename(tmp, path8);
72606
+ try {
72607
+ await fs10.chmod(path8, 384);
72608
+ } catch {}
72609
+ return { written: true, backupPath, finalPath: path8, noChange: false };
72610
+ }
72611
+ function buildGitHubPackagesEntries(pat) {
72612
+ const trimmed = pat.trim();
72613
+ return {
72614
+ [SCOPE_REGISTRY_KEY]: GITHUB_PACKAGES_REGISTRY_URL,
72615
+ [AUTH_TOKEN_KEY]: trimmed
72616
+ };
72617
+ }
72618
+ function isValidGitHubPat(value) {
72619
+ const v2 = value.trim();
72620
+ if (v2.length < 8)
72621
+ return false;
72622
+ if (/\s/.test(v2))
72623
+ return false;
72624
+ return /^(ghp_|github_pat_|ghs_|gho_|ghu_|ghr_)/.test(v2);
72625
+ }
72626
+ var GITHUB_PACKAGES_REGISTRY_URL = "https://npm.pkg.github.com", GITHUB_PACKAGES_SCOPE = "@chiendt1108", SCOPE_REGISTRY_KEY, AUTH_TOKEN_KEY = "//npm.pkg.github.com/:_authToken";
72627
+ var init_npmrc_bootstrap = __esm(() => {
72628
+ SCOPE_REGISTRY_KEY = `${GITHUB_PACKAGES_SCOPE}:registry`;
72629
+ });
72630
+
72631
+ // src/commands/fqc-qa/npmrc-setup-step.ts
72632
+ var exports_npmrc_setup_step = {};
72633
+ __export(exports_npmrc_setup_step, {
72634
+ runNpmrcSetupStep: () => runNpmrcSetupStep
72635
+ });
72636
+ import { existsSync as existsSync66, readFileSync as readFileSync20 } from "node:fs";
72637
+ import { homedir as homedir45 } from "node:os";
72638
+ import { join as join96 } from "node:path";
72639
+ function resolveTokenFromEnv() {
72640
+ const fromProcess = process.env[TOKEN_ENV_KEY];
72641
+ if (fromProcess && fromProcess.length > 0) {
72642
+ return { token: fromProcess, source: "env" };
72643
+ }
72644
+ const dotenvPath = join96(process.cwd(), ".env");
72645
+ if (!existsSync66(dotenvPath))
72646
+ return null;
72647
+ let contents;
72648
+ try {
72649
+ contents = readFileSync20(dotenvPath, "utf8");
72650
+ } catch {
72651
+ return null;
72652
+ }
72653
+ for (const rawLine of contents.split(`
72654
+ `)) {
72655
+ const line = rawLine.trim();
72656
+ if (line.length === 0 || line.startsWith("#"))
72657
+ continue;
72658
+ const eq = line.indexOf("=");
72659
+ if (eq < 0)
72660
+ continue;
72661
+ const key = line.slice(0, eq).trim();
72662
+ if (key !== TOKEN_ENV_KEY)
72663
+ continue;
72664
+ let value = line.slice(eq + 1).trim();
72665
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
72666
+ value = value.slice(1, -1);
72667
+ }
72668
+ if (value.length === 0)
72669
+ return null;
72670
+ return { token: value, source: "dotenv" };
72671
+ }
72672
+ return null;
72673
+ }
72674
+ async function writeNpmrcWithToken(pat, source) {
72675
+ const npmrcPath = join96(homedir45(), ".npmrc");
72676
+ try {
72677
+ const result = await writeNpmrc(npmrcPath, buildGitHubPackagesEntries(pat));
72678
+ if (result.noChange) {
72679
+ logger.info(import_picocolors19.default.dim("~/.npmrc already up to date"));
72680
+ return { status: "no-change", source };
72681
+ }
72682
+ logger.info(import_picocolors19.default.green(`Wrote GitHub Packages config → ${npmrcPath}`));
72683
+ if (result.backupPath)
72684
+ logger.info(import_picocolors19.default.dim(` backup: ${result.backupPath}`));
72685
+ return { status: "written", backupPath: result.backupPath, source };
72686
+ } catch (err) {
72687
+ const msg = err instanceof Error ? err.message : String(err);
72688
+ logger.error(`Failed to write ~/.npmrc: ${msg}`);
72689
+ return { status: "error", error: msg, source };
72690
+ }
72691
+ }
72692
+ async function runNpmrcSetupStep(opts = {}) {
72693
+ if (process.env.FQC_QA_SKIP_NPMRC === "1") {
72694
+ logger.info(import_picocolors19.default.dim("Skipping ~/.npmrc bootstrap (FQC_QA_SKIP_NPMRC=1)"));
72695
+ return { status: "skipped-env" };
72696
+ }
72697
+ const fromEnv = resolveTokenFromEnv();
72698
+ if (fromEnv) {
72699
+ if (!isValidGitHubPat(fromEnv.token)) {
72700
+ logger.info(import_picocolors19.default.yellow(`${TOKEN_ENV_KEY} (from ${fromEnv.source === "env" ? "process.env" : ".env"}) is not a valid GitHub PAT — falling back to interactive prompt.`));
72701
+ } else {
72702
+ logger.info(import_picocolors19.default.dim(`Using ${TOKEN_ENV_KEY} from ${fromEnv.source === "env" ? "process.env" : "<cwd>/.env"} — skipping prompt.`));
72703
+ return writeNpmrcWithToken(fromEnv.token, fromEnv.source);
72704
+ }
72705
+ }
72706
+ console.log("");
72707
+ le([
72708
+ "To resolve @chiendt1108/fqc-mcp-servers from GitHub Packages, ~/.npmrc",
72709
+ "needs a scope mapping and a GitHub PAT with the `read:packages` scope.",
72710
+ "Create one at: https://github.com/settings/tokens (classic) or",
72711
+ "https://github.com/settings/personal-access-tokens/new (fine-grained).",
72712
+ "",
72713
+ "Press Enter / Esc to skip — rerun later with `ack fqc-qa-setup --npmrc-only`."
72714
+ ].join(`
72715
+ `), "GitHub Packages auth");
72716
+ if (opts.yes) {
72717
+ logger.info(import_picocolors19.default.yellow("--yes given — skipping interactive PAT prompt."));
72718
+ return { status: "skipped-cancel" };
72719
+ }
72720
+ const pat = await re({
72721
+ message: "GitHub Personal Access Token (read:packages):",
72722
+ validate: (value) => {
72723
+ if (!value)
72724
+ return;
72725
+ if (!isValidGitHubPat(value)) {
72726
+ return "Token must start with ghp_, github_pat_, ghs_, gho_, ghu_, or ghr_.";
72727
+ }
72728
+ return;
72729
+ }
72730
+ });
72731
+ if (lD(pat) || !pat) {
72732
+ logger.info(import_picocolors19.default.yellow("Skipped PAT entry. Rerun with `ack fqc-qa-setup --npmrc-only` when ready."));
72733
+ return { status: "skipped-cancel" };
72734
+ }
72735
+ return writeNpmrcWithToken(pat, "prompt");
72736
+ }
72737
+ var import_picocolors19, TOKEN_ENV_KEY = "FQC_GITHUB_PACKAGES_TOKEN";
72738
+ var init_npmrc_setup_step = __esm(() => {
72739
+ init_npmrc_bootstrap();
72740
+ init_logger();
72741
+ init_dist2();
72742
+ import_picocolors19 = __toESM(require_picocolors(), 1);
72743
+ });
72744
+
72530
72745
  // node_modules/picomatch/lib/constants.js
72531
72746
  var require_constants3 = __commonJS((exports, module) => {
72532
72747
  var WIN_SLASH = "\\\\/";
@@ -74482,7 +74697,7 @@ var init_opencode_installer = __esm(() => {
74482
74697
  var PARTIAL_INSTALL_VERSION = "partial", EXIT_CODE_CRITICAL_FAILURE = 1, EXIT_CODE_PARTIAL_SUCCESS = 2;
74483
74698
 
74484
74699
  // src/services/package-installer/install-error-handler.ts
74485
- import { existsSync as existsSync66, readFileSync as readFileSync20, unlinkSync as unlinkSync4 } from "node:fs";
74700
+ import { existsSync as existsSync67, readFileSync as readFileSync21, unlinkSync as unlinkSync4 } from "node:fs";
74486
74701
  import { join as join100 } from "node:path";
74487
74702
  function parseNameReason(str2) {
74488
74703
  const colonIndex = str2.indexOf(":");
@@ -74547,13 +74762,13 @@ function getSystemPackageCommands(summary, systemFailures) {
74547
74762
  }
74548
74763
  function displayInstallErrors(skillsDir) {
74549
74764
  const summaryPath = join100(skillsDir, ".install-error-summary.json");
74550
- if (!existsSync66(summaryPath)) {
74765
+ if (!existsSync67(summaryPath)) {
74551
74766
  logger.error("Skills installation failed. Run with --verbose for details.");
74552
74767
  return;
74553
74768
  }
74554
74769
  let summary;
74555
74770
  try {
74556
- summary = JSON.parse(readFileSync20(summaryPath, "utf-8"));
74771
+ summary = JSON.parse(readFileSync21(summaryPath, "utf-8"));
74557
74772
  } catch (parseError) {
74558
74773
  logger.error("Failed to parse error summary. File may be corrupted.");
74559
74774
  logger.debug(`Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
@@ -74646,7 +74861,7 @@ async function checkNeedsSudoPackages() {
74646
74861
  }
74647
74862
  function hasInstallState(skillsDir) {
74648
74863
  const stateFilePath = join100(skillsDir, ".install-state.json");
74649
- return existsSync66(stateFilePath);
74864
+ return existsSync67(stateFilePath);
74650
74865
  }
74651
74866
  var WHICH_COMMAND_TIMEOUT_MS = 5000, WINDOWS_SYSTEM_PACKAGES, SYSTEM_TOOL_KEYS, WINDOWS_RSVG_COMMANDS;
74652
74867
  var init_install_error_handler = __esm(() => {
@@ -74685,7 +74900,7 @@ async function installSkillsDependencies(skillsDir, options2 = {}) {
74685
74900
  };
74686
74901
  }
74687
74902
  try {
74688
- const { existsSync: existsSync67 } = await import("node:fs");
74903
+ const { existsSync: existsSync68 } = await import("node:fs");
74689
74904
  const clack = await Promise.resolve().then(() => (init_dist2(), exports_dist));
74690
74905
  const platform9 = process.platform;
74691
74906
  const scriptName = platform9 === "win32" ? "install.ps1" : "install.sh";
@@ -74701,7 +74916,7 @@ async function installSkillsDependencies(skillsDir, options2 = {}) {
74701
74916
  error: `Path validation failed: ${errorMessage}`
74702
74917
  };
74703
74918
  }
74704
- if (!existsSync67(scriptPath)) {
74919
+ if (!existsSync68(scriptPath)) {
74705
74920
  logger.warning(`Skills installation script not found: ${scriptPath}`);
74706
74921
  logger.info("");
74707
74922
  logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
@@ -74917,7 +75132,7 @@ var init_skills_installer2 = __esm(() => {
74917
75132
  });
74918
75133
 
74919
75134
  // src/services/package-installer/gemini-mcp/config-manager.ts
74920
- import { existsSync as existsSync67 } from "node:fs";
75135
+ import { existsSync as existsSync68 } from "node:fs";
74921
75136
  import { mkdir as mkdir24, readFile as readFile50, writeFile as writeFile25 } from "node:fs/promises";
74922
75137
  import { dirname as dirname33, join as join102 } from "node:path";
74923
75138
  async function readJsonFile(filePath) {
@@ -74935,7 +75150,7 @@ async function addGeminiToGitignore(projectDir) {
74935
75150
  const geminiPattern = ".gemini/";
74936
75151
  try {
74937
75152
  let content = "";
74938
- if (existsSync67(gitignorePath)) {
75153
+ if (existsSync68(gitignorePath)) {
74939
75154
  content = await readFile50(gitignorePath, "utf-8");
74940
75155
  const lines = content.split(`
74941
75156
  `).map((line) => line.trim()).filter((line) => !line.startsWith("#"));
@@ -74960,7 +75175,7 @@ ${geminiPattern}
74960
75175
  }
74961
75176
  async function createNewSettingsWithMerge(geminiSettingsPath, mcpConfigPath) {
74962
75177
  const linkDir = dirname33(geminiSettingsPath);
74963
- if (!existsSync67(linkDir)) {
75178
+ if (!existsSync68(linkDir)) {
74964
75179
  await mkdir24(linkDir, { recursive: true });
74965
75180
  logger.debug(`Created directory: ${linkDir}`);
74966
75181
  }
@@ -75021,7 +75236,7 @@ var init_config_manager2 = __esm(() => {
75021
75236
  });
75022
75237
 
75023
75238
  // src/services/package-installer/gemini-mcp/validation.ts
75024
- import { existsSync as existsSync68, lstatSync, readlinkSync } from "node:fs";
75239
+ import { existsSync as existsSync69, lstatSync, readlinkSync } from "node:fs";
75025
75240
  import { homedir as homedir46 } from "node:os";
75026
75241
  import { join as join103 } from "node:path";
75027
75242
  function getGlobalMcpConfigPath() {
@@ -75032,12 +75247,12 @@ function getLocalMcpConfigPath(projectDir) {
75032
75247
  }
75033
75248
  function findMcpConfigPath(projectDir) {
75034
75249
  const localPath = getLocalMcpConfigPath(projectDir);
75035
- if (existsSync68(localPath)) {
75250
+ if (existsSync69(localPath)) {
75036
75251
  logger.debug(`Found local MCP config: ${localPath}`);
75037
75252
  return localPath;
75038
75253
  }
75039
75254
  const globalPath = getGlobalMcpConfigPath();
75040
- if (existsSync68(globalPath)) {
75255
+ if (existsSync69(globalPath)) {
75041
75256
  logger.debug(`Found global MCP config: ${globalPath}`);
75042
75257
  return globalPath;
75043
75258
  }
@@ -75052,7 +75267,7 @@ function getGeminiSettingsPath(projectDir, isGlobal) {
75052
75267
  }
75053
75268
  function checkExistingGeminiConfig(projectDir, isGlobal = false) {
75054
75269
  const geminiSettingsPath = getGeminiSettingsPath(projectDir, isGlobal);
75055
- if (!existsSync68(geminiSettingsPath)) {
75270
+ if (!existsSync69(geminiSettingsPath)) {
75056
75271
  return { exists: false, isSymlink: false, settingsPath: geminiSettingsPath };
75057
75272
  }
75058
75273
  try {
@@ -75076,12 +75291,12 @@ var init_validation = __esm(() => {
75076
75291
  });
75077
75292
 
75078
75293
  // src/services/package-installer/gemini-mcp/linker-core.ts
75079
- import { existsSync as existsSync69 } from "node:fs";
75294
+ import { existsSync as existsSync70 } from "node:fs";
75080
75295
  import { mkdir as mkdir25, symlink as symlink3 } from "node:fs/promises";
75081
75296
  import { dirname as dirname34, join as join104 } from "node:path";
75082
75297
  async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
75083
75298
  const linkDir = dirname34(linkPath);
75084
- if (!existsSync69(linkDir)) {
75299
+ if (!existsSync70(linkDir)) {
75085
75300
  await mkdir25(linkDir, { recursive: true });
75086
75301
  logger.debug(`Created directory: ${linkDir}`);
75087
75302
  }
@@ -77504,7 +77719,7 @@ __export(exports_worktree_manager, {
77504
77719
  createWorktree: () => createWorktree,
77505
77720
  cleanupAllWorktrees: () => cleanupAllWorktrees
77506
77721
  });
77507
- import { existsSync as existsSync78 } from "node:fs";
77722
+ import { existsSync as existsSync79 } from "node:fs";
77508
77723
  import { readFile as readFile70, writeFile as writeFile40 } from "node:fs/promises";
77509
77724
  import { join as join162 } from "node:path";
77510
77725
  async function createWorktree(projectDir, issueNumber, baseBranch) {
@@ -77570,7 +77785,7 @@ async function cleanupAllWorktrees(projectDir) {
77570
77785
  async function ensureGitignore(projectDir) {
77571
77786
  const gitignorePath = join162(projectDir, ".gitignore");
77572
77787
  try {
77573
- const content = existsSync78(gitignorePath) ? await readFile70(gitignorePath, "utf-8") : "";
77788
+ const content = existsSync79(gitignorePath) ? await readFile70(gitignorePath, "utf-8") : "";
77574
77789
  if (!content.includes(".worktrees")) {
77575
77790
  const newContent = content.endsWith(`
77576
77791
  `) ? `${content}.worktrees/
@@ -77672,16 +77887,16 @@ var init_content_validator = __esm(() => {
77672
77887
 
77673
77888
  // src/commands/content/phases/context-cache-manager.ts
77674
77889
  import { createHash as createHash10 } from "node:crypto";
77675
- import { existsSync as existsSync84, mkdirSync as mkdirSync5, readFileSync as readFileSync21, readdirSync as readdirSync12, statSync as statSync15 } from "node:fs";
77890
+ import { existsSync as existsSync85, mkdirSync as mkdirSync5, readFileSync as readFileSync22, readdirSync as readdirSync12, statSync as statSync15 } from "node:fs";
77676
77891
  import { rename as rename17, writeFile as writeFile42 } from "node:fs/promises";
77677
77892
  import { homedir as homedir56 } from "node:os";
77678
77893
  import { basename as basename34, join as join169 } from "node:path";
77679
77894
  function getCachedContext(repoPath) {
77680
77895
  const cachePath = getCacheFilePath(repoPath);
77681
- if (!existsSync84(cachePath))
77896
+ if (!existsSync85(cachePath))
77682
77897
  return null;
77683
77898
  try {
77684
- const raw = readFileSync21(cachePath, "utf-8");
77899
+ const raw = readFileSync22(cachePath, "utf-8");
77685
77900
  const cache4 = JSON.parse(raw);
77686
77901
  const age = Date.now() - new Date(cache4.createdAt).getTime();
77687
77902
  if (age >= CACHE_TTL_MS5)
@@ -77695,7 +77910,7 @@ function getCachedContext(repoPath) {
77695
77910
  }
77696
77911
  }
77697
77912
  async function saveCachedContext(repoPath, cache4) {
77698
- if (!existsSync84(CACHE_DIR)) {
77913
+ if (!existsSync85(CACHE_DIR)) {
77699
77914
  mkdirSync5(CACHE_DIR, { recursive: true });
77700
77915
  }
77701
77916
  const cachePath = getCacheFilePath(repoPath);
@@ -77719,7 +77934,7 @@ function computeSourceHash(repoPath) {
77719
77934
  function getDocSourcePaths(repoPath) {
77720
77935
  const paths = [];
77721
77936
  const docsDir = join169(repoPath, "docs");
77722
- if (existsSync84(docsDir)) {
77937
+ if (existsSync85(docsDir)) {
77723
77938
  try {
77724
77939
  const files = readdirSync12(docsDir);
77725
77940
  for (const f4 of files) {
@@ -77729,10 +77944,10 @@ function getDocSourcePaths(repoPath) {
77729
77944
  } catch {}
77730
77945
  }
77731
77946
  const readme = join169(repoPath, "README.md");
77732
- if (existsSync84(readme))
77947
+ if (existsSync85(readme))
77733
77948
  paths.push(readme);
77734
77949
  const stylesDir = join169(repoPath, "assets", "writing-styles");
77735
- if (existsSync84(stylesDir)) {
77950
+ if (existsSync85(stylesDir)) {
77736
77951
  try {
77737
77952
  const files = readdirSync12(stylesDir);
77738
77953
  for (const f4 of files) {
@@ -77929,7 +78144,7 @@ function extractContentFromResponse(response) {
77929
78144
 
77930
78145
  // src/commands/content/phases/docs-summarizer.ts
77931
78146
  import { execSync as execSync6 } from "node:child_process";
77932
- import { existsSync as existsSync85, readFileSync as readFileSync22, readdirSync as readdirSync13 } from "node:fs";
78147
+ import { existsSync as existsSync86, readFileSync as readFileSync23, readdirSync as readdirSync13 } from "node:fs";
77933
78148
  import { join as join170 } from "node:path";
77934
78149
  async function summarizeProjectDocs(repoPath, contentLogger) {
77935
78150
  const rawContent = collectRawDocs(repoPath);
@@ -77974,18 +78189,18 @@ async function summarizeProjectDocs(repoPath, contentLogger) {
77974
78189
  function collectRawDocs(repoPath) {
77975
78190
  let totalChars = 0;
77976
78191
  const readCapped = (filePath, maxChars) => {
77977
- if (!existsSync85(filePath))
78192
+ if (!existsSync86(filePath))
77978
78193
  return "";
77979
78194
  if (totalChars >= MAX_RAW_CONTENT_CHARS)
77980
78195
  return "";
77981
- const content = readFileSync22(filePath, "utf-8");
78196
+ const content = readFileSync23(filePath, "utf-8");
77982
78197
  const capped = content.slice(0, Math.min(maxChars, MAX_RAW_CONTENT_CHARS - totalChars));
77983
78198
  totalChars += capped.length;
77984
78199
  return capped;
77985
78200
  };
77986
78201
  const docsContent = [];
77987
78202
  const docsDir = join170(repoPath, "docs");
77988
- if (existsSync85(docsDir)) {
78203
+ if (existsSync86(docsDir)) {
77989
78204
  try {
77990
78205
  const files = readdirSync13(docsDir).filter((f4) => f4.endsWith(".md")).sort();
77991
78206
  for (const f4 of files) {
@@ -78009,7 +78224,7 @@ ${content}`);
78009
78224
  }
78010
78225
  let styles3 = "";
78011
78226
  const stylesDir = join170(repoPath, "assets", "writing-styles");
78012
- if (existsSync85(stylesDir)) {
78227
+ if (existsSync86(stylesDir)) {
78013
78228
  try {
78014
78229
  const files = readdirSync13(stylesDir).slice(0, 3);
78015
78230
  styles3 = files.map((f4) => readCapped(join170(stylesDir, f4), 1000)).filter(Boolean).join(`
@@ -78202,12 +78417,12 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
78202
78417
 
78203
78418
  // src/commands/content/phases/photo-generator.ts
78204
78419
  import { execSync as execSync7 } from "node:child_process";
78205
- import { existsSync as existsSync86, mkdirSync as mkdirSync6, readdirSync as readdirSync14 } from "node:fs";
78420
+ import { existsSync as existsSync87, mkdirSync as mkdirSync6, readdirSync as readdirSync14 } from "node:fs";
78206
78421
  import { homedir as homedir57 } from "node:os";
78207
78422
  import { join as join171 } from "node:path";
78208
78423
  async function generatePhoto(_content, context, config, platform14, contentId, contentLogger) {
78209
78424
  const mediaDir = join171(config.contentDir.replace(/^~/, homedir57()), "media", String(contentId));
78210
- if (!existsSync86(mediaDir)) {
78425
+ if (!existsSync87(mediaDir)) {
78211
78426
  mkdirSync6(mediaDir, { recursive: true });
78212
78427
  }
78213
78428
  const prompt = buildPhotoPrompt(context, platform14);
@@ -78223,7 +78438,7 @@ async function generatePhoto(_content, context, config, platform14, contentId, c
78223
78438
  const parsed = parseClaudeJsonOutput(result);
78224
78439
  if (parsed && typeof parsed === "object" && "imagePath" in parsed) {
78225
78440
  const imagePath = String(parsed.imagePath);
78226
- if (existsSync86(imagePath)) {
78441
+ if (existsSync87(imagePath)) {
78227
78442
  return { path: imagePath, ...dimensions, format: "png" };
78228
78443
  }
78229
78444
  }
@@ -78319,7 +78534,7 @@ var init_content_creator = __esm(() => {
78319
78534
  });
78320
78535
 
78321
78536
  // src/commands/content/phases/content-logger.ts
78322
- import { createWriteStream as createWriteStream4, existsSync as existsSync87, mkdirSync as mkdirSync7, statSync as statSync16 } from "node:fs";
78537
+ import { createWriteStream as createWriteStream4, existsSync as existsSync88, mkdirSync as mkdirSync7, statSync as statSync16 } from "node:fs";
78323
78538
  import { homedir as homedir58 } from "node:os";
78324
78539
  import { join as join172 } from "node:path";
78325
78540
 
@@ -78333,7 +78548,7 @@ class ContentLogger {
78333
78548
  this.maxBytes = maxBytes;
78334
78549
  }
78335
78550
  init() {
78336
- if (!existsSync87(this.logDir)) {
78551
+ if (!existsSync88(this.logDir)) {
78337
78552
  mkdirSync7(this.logDir, { recursive: true });
78338
78553
  }
78339
78554
  this.rotateIfNeeded();
@@ -78426,7 +78641,7 @@ function openDatabase(dbPath) {
78426
78641
  var init_sqlite_client = () => {};
78427
78642
 
78428
78643
  // src/commands/content/phases/db-manager.ts
78429
- import { existsSync as existsSync88, mkdirSync as mkdirSync8 } from "node:fs";
78644
+ import { existsSync as existsSync89, mkdirSync as mkdirSync8 } from "node:fs";
78430
78645
  import { dirname as dirname51 } from "node:path";
78431
78646
  function initDatabase(dbPath) {
78432
78647
  ensureParentDir(dbPath);
@@ -78449,7 +78664,7 @@ function runRetentionCleanup(db, retentionDays = 90) {
78449
78664
  }
78450
78665
  function ensureParentDir(dbPath) {
78451
78666
  const dir = dirname51(dbPath);
78452
- if (dir && !existsSync88(dir)) {
78667
+ if (dir && !existsSync89(dir)) {
78453
78668
  mkdirSync8(dir, { recursive: true });
78454
78669
  }
78455
78670
  }
@@ -78614,7 +78829,7 @@ function isNoiseCommit(title, author) {
78614
78829
 
78615
78830
  // src/commands/content/phases/change-detector.ts
78616
78831
  import { execFileSync as execFileSync4, spawnSync as spawnSync9 } from "node:child_process";
78617
- import { existsSync as existsSync89, readFileSync as readFileSync23, readdirSync as readdirSync15, statSync as statSync17 } from "node:fs";
78832
+ import { existsSync as existsSync90, readFileSync as readFileSync24, readdirSync as readdirSync15, statSync as statSync17 } from "node:fs";
78618
78833
  import { join as join173 } from "node:path";
78619
78834
  function detectCommits(repo, since) {
78620
78835
  try {
@@ -78747,7 +78962,7 @@ function detectTags(repo, since) {
78747
78962
  }
78748
78963
  function detectCompletedPlans(repo, since) {
78749
78964
  const plansDir = join173(repo.path, "plans");
78750
- if (!existsSync89(plansDir))
78965
+ if (!existsSync90(plansDir))
78751
78966
  return [];
78752
78967
  const sinceMs = new Date(since).getTime();
78753
78968
  const events = [];
@@ -78757,13 +78972,13 @@ function detectCompletedPlans(repo, since) {
78757
78972
  if (!entry.isDirectory())
78758
78973
  continue;
78759
78974
  const planFile = join173(plansDir, entry.name, "plan.md");
78760
- if (!existsSync89(planFile))
78975
+ if (!existsSync90(planFile))
78761
78976
  continue;
78762
78977
  try {
78763
78978
  const stat26 = statSync17(planFile);
78764
78979
  if (stat26.mtimeMs < sinceMs)
78765
78980
  continue;
78766
- const content = readFileSync23(planFile, "utf-8");
78981
+ const content = readFileSync24(planFile, "utf-8");
78767
78982
  const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
78768
78983
  if (!frontmatterMatch)
78769
78984
  continue;
@@ -79795,7 +80010,7 @@ var init_platform_setup_x = __esm(() => {
79795
80010
  });
79796
80011
 
79797
80012
  // src/commands/content/phases/setup-wizard.ts
79798
- import { existsSync as existsSync90 } from "node:fs";
80013
+ import { existsSync as existsSync91 } from "node:fs";
79799
80014
  import { join as join176 } from "node:path";
79800
80015
  async function runSetupWizard2(cwd2, contentLogger) {
79801
80016
  console.log();
@@ -79864,8 +80079,8 @@ async function showRepoSummary(cwd2) {
79864
80079
  function detectBrandAssets(cwd2, contentLogger) {
79865
80080
  const repos = discoverRepos2(cwd2);
79866
80081
  for (const repo of repos) {
79867
- const hasGuidelines = existsSync90(join176(repo.path, "docs", "brand-guidelines.md"));
79868
- const hasStyles = existsSync90(join176(repo.path, "assets", "writing-styles"));
80082
+ const hasGuidelines = existsSync91(join176(repo.path, "docs", "brand-guidelines.md"));
80083
+ const hasStyles = existsSync91(join176(repo.path, "assets", "writing-styles"));
79869
80084
  if (!hasGuidelines) {
79870
80085
  f2.warning(`${repo.name}: No docs/brand-guidelines.md — content will use generic tone.`);
79871
80086
  contentLogger.warn(`${repo.name}: missing docs/brand-guidelines.md`);
@@ -79931,13 +80146,13 @@ var init_setup_wizard = __esm(() => {
79931
80146
  });
79932
80147
 
79933
80148
  // src/commands/content/content-review-commands.ts
79934
- import { existsSync as existsSync91 } from "node:fs";
80149
+ import { existsSync as existsSync92 } from "node:fs";
79935
80150
  import { homedir as homedir59 } from "node:os";
79936
80151
  async function queueContent() {
79937
80152
  const cwd2 = process.cwd();
79938
80153
  const config = await loadContentConfig(cwd2);
79939
80154
  const dbPath = config.dbPath.replace(/^~/, homedir59());
79940
- if (!existsSync91(dbPath)) {
80155
+ if (!existsSync92(dbPath)) {
79941
80156
  logger.info("No content database found. Run 'ack content setup' first.");
79942
80157
  return;
79943
80158
  }
@@ -80005,15 +80220,15 @@ __export(exports_content_subcommands, {
80005
80220
  logsContent: () => logsContent,
80006
80221
  approveContentCmd: () => approveContentCmd
80007
80222
  });
80008
- import { existsSync as existsSync92, readFileSync as readFileSync24, unlinkSync as unlinkSync7 } from "node:fs";
80223
+ import { existsSync as existsSync93, readFileSync as readFileSync25, unlinkSync as unlinkSync7 } from "node:fs";
80009
80224
  import { homedir as homedir60 } from "node:os";
80010
80225
  import { join as join177 } from "node:path";
80011
80226
  function isDaemonRunning() {
80012
80227
  const lockFile = join177(LOCK_DIR, `${LOCK_NAME2}.lock`);
80013
- if (!existsSync92(lockFile))
80228
+ if (!existsSync93(lockFile))
80014
80229
  return { running: false, pid: null };
80015
80230
  try {
80016
- const pidStr = readFileSync24(lockFile, "utf-8").trim();
80231
+ const pidStr = readFileSync25(lockFile, "utf-8").trim();
80017
80232
  const pid = Number.parseInt(pidStr, 10);
80018
80233
  if (Number.isNaN(pid)) {
80019
80234
  unlinkSync7(lockFile);
@@ -80042,12 +80257,12 @@ async function startContent(options2) {
80042
80257
  }
80043
80258
  async function stopContent() {
80044
80259
  const lockFile = join177(LOCK_DIR, `${LOCK_NAME2}.lock`);
80045
- if (!existsSync92(lockFile)) {
80260
+ if (!existsSync93(lockFile)) {
80046
80261
  logger.info("Content daemon is not running.");
80047
80262
  return;
80048
80263
  }
80049
80264
  try {
80050
- const pidStr = readFileSync24(lockFile, "utf-8").trim();
80265
+ const pidStr = readFileSync25(lockFile, "utf-8").trim();
80051
80266
  const pid = Number.parseInt(pidStr, 10);
80052
80267
  if (!Number.isNaN(pid)) {
80053
80268
  process.kill(pid, "SIGTERM");
@@ -80083,7 +80298,7 @@ async function logsContent(options2) {
80083
80298
  const logDir = join177(homedir60(), ".ack", "logs");
80084
80299
  const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
80085
80300
  const logPath = join177(logDir, `content-${dateStr}.log`);
80086
- if (!existsSync92(logPath)) {
80301
+ if (!existsSync93(logPath)) {
80087
80302
  logger.info("No content logs found for today.");
80088
80303
  return;
80089
80304
  }
@@ -80095,7 +80310,7 @@ async function logsContent(options2) {
80095
80310
  process.exit(0);
80096
80311
  });
80097
80312
  } else {
80098
- const content = readFileSync24(logPath, "utf-8");
80313
+ const content = readFileSync25(logPath, "utf-8");
80099
80314
  console.log(content);
80100
80315
  }
80101
80316
  }
@@ -80118,7 +80333,7 @@ var init_content_subcommands = __esm(() => {
80118
80333
  });
80119
80334
 
80120
80335
  // src/commands/content/content-command.ts
80121
- import { existsSync as existsSync93, mkdirSync as mkdirSync9, unlinkSync as unlinkSync8, writeFileSync as writeFileSync10 } from "node:fs";
80336
+ import { existsSync as existsSync94, mkdirSync as mkdirSync9, unlinkSync as unlinkSync8, writeFileSync as writeFileSync10 } from "node:fs";
80122
80337
  import { homedir as homedir61 } from "node:os";
80123
80338
  import { join as join178 } from "node:path";
80124
80339
  async function contentCommand(options2) {
@@ -80149,7 +80364,7 @@ async function contentCommand(options2) {
80149
80364
  }
80150
80365
  contentLogger.info("Setup complete. Starting daemon...");
80151
80366
  }
80152
- if (!existsSync93(LOCK_DIR2))
80367
+ if (!existsSync94(LOCK_DIR2))
80153
80368
  mkdirSync9(LOCK_DIR2, { recursive: true });
80154
80369
  writeFileSync10(LOCK_FILE, String(process.pid), "utf-8");
80155
80370
  const dbPath = config.dbPath.replace(/^~/, homedir61());
@@ -90791,114 +91006,12 @@ function buildCheckResult(result) {
90791
91006
  };
90792
91007
  }
90793
91008
  // src/domains/health-checks/checkers/npmrc-github-packages-checker.ts
91009
+ init_npmrc_bootstrap();
91010
+ init_environment();
90794
91011
  import { spawn as spawn4 } from "node:child_process";
90795
91012
  import { promises as fs11 } from "node:fs";
90796
91013
  import { homedir as homedir44 } from "node:os";
90797
91014
  import { join as join89 } from "node:path";
90798
-
90799
- // src/domains/installation/npmrc-bootstrap.ts
90800
- import { promises as fs10 } from "node:fs";
90801
- import { dirname as dirname29 } from "node:path";
90802
- var GITHUB_PACKAGES_REGISTRY_URL = "https://npm.pkg.github.com";
90803
- var GITHUB_PACKAGES_SCOPE = "@chiendt1108";
90804
- var SCOPE_REGISTRY_KEY = `${GITHUB_PACKAGES_SCOPE}:registry`;
90805
- var AUTH_TOKEN_KEY = "//npm.pkg.github.com/:_authToken";
90806
- function mergeNpmrcEntries(existing, entries) {
90807
- const keys = new Set(Object.keys(entries));
90808
- const seenKeys = new Set;
90809
- const lines = existing.split(`
90810
- `);
90811
- const out = [];
90812
- for (const line of lines) {
90813
- const stripped = line.trim();
90814
- if (stripped === "" || stripped.startsWith(";") || stripped.startsWith("#")) {
90815
- out.push(line);
90816
- continue;
90817
- }
90818
- const eq = line.indexOf("=");
90819
- if (eq < 0) {
90820
- out.push(line);
90821
- continue;
90822
- }
90823
- const key = line.slice(0, eq).trim();
90824
- if (keys.has(key)) {
90825
- seenKeys.add(key);
90826
- out.push(`${key}=${entries[key]}`);
90827
- } else {
90828
- out.push(line);
90829
- }
90830
- }
90831
- const additions = [];
90832
- for (const key of keys) {
90833
- if (!seenKeys.has(key)) {
90834
- additions.push(`${key}=${entries[key]}`);
90835
- }
90836
- }
90837
- let result = out.join(`
90838
- `);
90839
- if (additions.length > 0) {
90840
- if (result.length > 0 && !result.endsWith(`
90841
- `))
90842
- result += `
90843
- `;
90844
- result += `${additions.join(`
90845
- `)}
90846
- `;
90847
- } else if (result.length > 0 && !result.endsWith(`
90848
- `)) {
90849
- result += `
90850
- `;
90851
- }
90852
- return result;
90853
- }
90854
- async function writeNpmrc(path8, entries, opts = {}) {
90855
- let existing = "";
90856
- let hadFile = false;
90857
- try {
90858
- existing = await fs10.readFile(path8, "utf8");
90859
- hadFile = true;
90860
- } catch (err) {
90861
- if (err.code !== "ENOENT")
90862
- throw err;
90863
- }
90864
- const merged = mergeNpmrcEntries(existing, entries);
90865
- if (merged === existing) {
90866
- return { written: false, backupPath: null, finalPath: path8, noChange: true };
90867
- }
90868
- let backupPath = null;
90869
- if (hadFile) {
90870
- const now = opts.now?.() ?? new Date;
90871
- const stamp = now.toISOString().replace(/[:.]/g, "-");
90872
- backupPath = `${path8}.bak.${stamp}`;
90873
- await fs10.copyFile(path8, backupPath);
90874
- }
90875
- await fs10.mkdir(dirname29(path8), { recursive: true });
90876
- const tmp = `${path8}.tmp.${process.pid}`;
90877
- await fs10.writeFile(tmp, merged, { mode: 384 });
90878
- await fs10.rename(tmp, path8);
90879
- try {
90880
- await fs10.chmod(path8, 384);
90881
- } catch {}
90882
- return { written: true, backupPath, finalPath: path8, noChange: false };
90883
- }
90884
- function buildGitHubPackagesEntries(pat) {
90885
- const trimmed = pat.trim();
90886
- return {
90887
- [SCOPE_REGISTRY_KEY]: GITHUB_PACKAGES_REGISTRY_URL,
90888
- [AUTH_TOKEN_KEY]: trimmed
90889
- };
90890
- }
90891
- function isValidGitHubPat(value) {
90892
- const v2 = value.trim();
90893
- if (v2.length < 8)
90894
- return false;
90895
- if (/\s/.test(v2))
90896
- return false;
90897
- return /^(ghp_|github_pat_|ghs_|gho_|ghu_|ghr_)/.test(v2);
90898
- }
90899
-
90900
- // src/domains/health-checks/checkers/npmrc-github-packages-checker.ts
90901
- init_environment();
90902
91015
  var SETUP_HINT = "Run: ack fqc-qa-setup to write GitHub Packages config to ~/.npmrc";
90903
91016
  var PROBE_PACKAGE = "@chiendt1108/fqc-mcp-servers";
90904
91017
  var PROBE_TIMEOUT_MS = 5000;
@@ -92174,67 +92287,8 @@ function countFailures(states) {
92174
92287
  // src/commands/fqc-qa/fqc-qa-setup-command.ts
92175
92288
  init_logger();
92176
92289
  init_dist2();
92290
+ init_npmrc_setup_step();
92177
92291
  var import_picocolors20 = __toESM(require_picocolors(), 1);
92178
-
92179
- // src/commands/fqc-qa/npmrc-setup-step.ts
92180
- import { homedir as homedir45 } from "node:os";
92181
- import { join as join96 } from "node:path";
92182
- init_logger();
92183
- init_dist2();
92184
- var import_picocolors19 = __toESM(require_picocolors(), 1);
92185
- async function runNpmrcSetupStep(opts = {}) {
92186
- if (process.env.FQC_QA_SKIP_NPMRC === "1") {
92187
- logger.info(import_picocolors19.default.dim("Skipping ~/.npmrc bootstrap (FQC_QA_SKIP_NPMRC=1)"));
92188
- return { status: "skipped-env" };
92189
- }
92190
- console.log("");
92191
- le([
92192
- "To resolve @chiendt1108/fqc-mcp-servers from GitHub Packages, ~/.npmrc",
92193
- "needs a scope mapping and a GitHub PAT with the `read:packages` scope.",
92194
- "Create one at: https://github.com/settings/tokens (classic) or",
92195
- "https://github.com/settings/personal-access-tokens/new (fine-grained).",
92196
- "",
92197
- "Press Enter / Esc to skip — rerun later with `ack fqc-qa-setup --npmrc-only`."
92198
- ].join(`
92199
- `), "GitHub Packages auth");
92200
- if (opts.yes) {
92201
- logger.info(import_picocolors19.default.yellow("--yes given — skipping interactive PAT prompt."));
92202
- return { status: "skipped-cancel" };
92203
- }
92204
- const pat = await re({
92205
- message: "GitHub Personal Access Token (read:packages):",
92206
- validate: (value) => {
92207
- if (!value)
92208
- return;
92209
- if (!isValidGitHubPat(value)) {
92210
- return "Token must start with ghp_, github_pat_, ghs_, gho_, ghu_, or ghr_.";
92211
- }
92212
- return;
92213
- }
92214
- });
92215
- if (lD(pat) || !pat) {
92216
- logger.info(import_picocolors19.default.yellow("Skipped PAT entry. Rerun with `ack fqc-qa-setup --npmrc-only` when ready."));
92217
- return { status: "skipped-cancel" };
92218
- }
92219
- const npmrcPath = join96(homedir45(), ".npmrc");
92220
- try {
92221
- const result = await writeNpmrc(npmrcPath, buildGitHubPackagesEntries(pat));
92222
- if (result.noChange) {
92223
- logger.info(import_picocolors19.default.dim("~/.npmrc already up to date"));
92224
- return { status: "no-change" };
92225
- }
92226
- logger.info(import_picocolors19.default.green(`Wrote GitHub Packages config → ${npmrcPath}`));
92227
- if (result.backupPath)
92228
- logger.info(import_picocolors19.default.dim(` backup: ${result.backupPath}`));
92229
- return { status: "written", backupPath: result.backupPath };
92230
- } catch (err) {
92231
- const msg = err instanceof Error ? err.message : String(err);
92232
- logger.error(`Failed to write ~/.npmrc: ${msg}`);
92233
- return { status: "error", error: msg };
92234
- }
92235
- }
92236
-
92237
- // src/commands/fqc-qa/fqc-qa-setup-command.ts
92238
92292
  async function fqcQaSetupCommand(opts) {
92239
92293
  if (opts.npmrcOnly) {
92240
92294
  await runNpmrcSetupStep({ yes: opts.yes });
@@ -99632,7 +99686,7 @@ async function handleDownload(ctx) {
99632
99686
  import { join as join129 } from "node:path";
99633
99687
 
99634
99688
  // src/domains/installation/deletion-handler.ts
99635
- import { existsSync as existsSync70, lstatSync as lstatSync3, readdirSync as readdirSync8, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync5 } from "node:fs";
99689
+ import { existsSync as existsSync71, lstatSync as lstatSync3, readdirSync as readdirSync8, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync5 } from "node:fs";
99636
99690
  import { dirname as dirname36, join as join115, relative as relative22, resolve as resolve41, sep as sep11 } from "node:path";
99637
99691
 
99638
99692
  // src/services/file-operations/manifest/manifest-reader.ts
@@ -99823,7 +99877,7 @@ function shouldDeletePath(path10, metadata, kitType) {
99823
99877
  }
99824
99878
  function collectFilesRecursively(dir, baseDir) {
99825
99879
  const results = [];
99826
- if (!existsSync70(dir))
99880
+ if (!existsSync71(dir))
99827
99881
  return results;
99828
99882
  try {
99829
99883
  const entries = readdirSync8(dir, { withFileTypes: true });
@@ -99964,7 +100018,7 @@ async function handleDeletions(sourceMetadata, claudeDir3, kitType) {
99964
100018
  logger.verbose(`Preserved user file: ${path10}`);
99965
100019
  continue;
99966
100020
  }
99967
- if (existsSync70(fullPath)) {
100021
+ if (existsSync71(fullPath)) {
99968
100022
  try {
99969
100023
  deletePath(fullPath, claudeDir3);
99970
100024
  result.deletedPaths.push(path10);
@@ -101911,7 +101965,7 @@ import { dirname as dirname38, join as join118 } from "node:path";
101911
101965
 
101912
101966
  // src/domains/config/installed-settings-tracker.ts
101913
101967
  init_shared();
101914
- import { existsSync as existsSync71 } from "node:fs";
101968
+ import { existsSync as existsSync72 } from "node:fs";
101915
101969
  import { mkdir as mkdir31, readFile as readFile53, writeFile as writeFile27 } from "node:fs/promises";
101916
101970
  import { dirname as dirname37, join as join117 } from "node:path";
101917
101971
  var CK_JSON_FILE = ".ck.json";
@@ -101933,7 +101987,7 @@ class InstalledSettingsTracker {
101933
101987
  }
101934
101988
  async loadInstalledSettings() {
101935
101989
  const ckJsonPath = this.getCkJsonPath();
101936
- if (!existsSync71(ckJsonPath)) {
101990
+ if (!existsSync72(ckJsonPath)) {
101937
101991
  return { hooks: [], mcpServers: [] };
101938
101992
  }
101939
101993
  try {
@@ -101953,7 +102007,7 @@ class InstalledSettingsTracker {
101953
102007
  const ckJsonPath = this.getCkJsonPath();
101954
102008
  try {
101955
102009
  let data = {};
101956
- if (existsSync71(ckJsonPath)) {
102010
+ if (existsSync72(ckJsonPath)) {
101957
102011
  const content = await readFile53(ckJsonPath, "utf-8");
101958
102012
  data = JSON.parse(content);
101959
102013
  }
@@ -105609,6 +105663,10 @@ async function handlePostInstall(ctx) {
105609
105663
  withSudo: ctx.options.withSudo
105610
105664
  });
105611
105665
  }
105666
+ if (ctx.kitType === "fqc-qa") {
105667
+ const { runNpmrcSetupStep: runNpmrcSetupStep2 } = await Promise.resolve().then(() => (init_npmrc_setup_step(), exports_npmrc_setup_step));
105668
+ await runNpmrcSetupStep2({ yes: ctx.isNonInteractive });
105669
+ }
105612
105670
  if (!ctx.isNonInteractive) {
105613
105671
  const { isGeminiInstalled: isGeminiInstalled2 } = await Promise.resolve().then(() => (init_package_installer(), exports_package_installer));
105614
105672
  const { checkExistingGeminiConfig: checkExistingGeminiConfig2, findMcpConfigPath: findMcpConfigPath2, processGeminiMcpLinking: processGeminiMcpLinking2 } = await Promise.resolve().then(() => (init_gemini_mcp_linker(), exports_gemini_mcp_linker));
@@ -105828,7 +105886,7 @@ async function runPreflightChecks() {
105828
105886
 
105829
105887
  // src/domains/installation/fresh-installer.ts
105830
105888
  init_metadata_migration();
105831
- import { existsSync as existsSync72, readdirSync as readdirSync9, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync6 } from "node:fs";
105889
+ import { existsSync as existsSync73, readdirSync as readdirSync9, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync6 } from "node:fs";
105832
105890
  import { basename as basename28, dirname as dirname40, join as join141, resolve as resolve45 } from "node:path";
105833
105891
  init_logger();
105834
105892
  init_safe_spinner();
@@ -105912,7 +105970,7 @@ async function removeFilesByOwnership(claudeDir3, analysis, includeModified) {
105912
105970
  }
105913
105971
  for (const file of filesToRemove) {
105914
105972
  const fullPath = join141(claudeDir3, file.path);
105915
- if (!existsSync72(fullPath)) {
105973
+ if (!existsSync73(fullPath)) {
105916
105974
  continue;
105917
105975
  }
105918
105976
  try {
@@ -105970,8 +106028,8 @@ function getFreshBackupTargets(claudeDir3, analysis, includeModified) {
105970
106028
  mutatePaths: filesToRemove.length > 0 ? ["metadata.json"] : []
105971
106029
  };
105972
106030
  }
105973
- const deletePaths = ACK_SUBDIRECTORIES.filter((subdir) => existsSync72(join141(claudeDir3, subdir)));
105974
- if (existsSync72(join141(claudeDir3, "metadata.json"))) {
106031
+ const deletePaths = ACK_SUBDIRECTORIES.filter((subdir) => existsSync73(join141(claudeDir3, subdir)));
106032
+ if (existsSync73(join141(claudeDir3, "metadata.json"))) {
105975
106033
  deletePaths.push("metadata.json");
105976
106034
  }
105977
106035
  return {
@@ -107660,7 +107718,7 @@ async function initCommand(options2) {
107660
107718
  // src/commands/migrate/migrate-command.ts
107661
107719
  init_dist2();
107662
107720
  var import_picocolors35 = __toESM(require_picocolors(), 1);
107663
- import { existsSync as existsSync73 } from "node:fs";
107721
+ import { existsSync as existsSync74 } from "node:fs";
107664
107722
  import { readFile as readFile68, rm as rm20, unlink as unlink15 } from "node:fs/promises";
107665
107723
  import { homedir as homedir54 } from "node:os";
107666
107724
  import { basename as basename30, join as join152, resolve as resolve50 } from "node:path";
@@ -109303,7 +109361,7 @@ async function executeDeleteAction(action, options2) {
109303
109361
  const preservePaths = options2?.preservePaths ?? new Set;
109304
109362
  const shouldPreserveTarget = action.targetPath.length > 0 && preservePaths.has(resolve50(action.targetPath));
109305
109363
  try {
109306
- if (!shouldPreserveTarget && action.targetPath && existsSync73(action.targetPath)) {
109364
+ if (!shouldPreserveTarget && action.targetPath && existsSync74(action.targetPath)) {
109307
109365
  await rm20(action.targetPath, { recursive: true, force: true });
109308
109366
  }
109309
109367
  await removePortableInstallation(action.item, action.type, action.provider, action.global, action.targetPath ? { path: action.targetPath } : undefined);
@@ -109335,7 +109393,7 @@ async function processMetadataDeletions(skillSourcePath, installGlobally) {
109335
109393
  if (!skillSourcePath)
109336
109394
  return;
109337
109395
  const sourceMetadataPath = join152(resolve50(skillSourcePath, ".."), "metadata.json");
109338
- if (!existsSync73(sourceMetadataPath))
109396
+ if (!existsSync74(sourceMetadataPath))
109339
109397
  return;
109340
109398
  let sourceMetadata;
109341
109399
  try {
@@ -109348,7 +109406,7 @@ async function processMetadataDeletions(skillSourcePath, installGlobally) {
109348
109406
  if (!sourceMetadata.deletions || sourceMetadata.deletions.length === 0)
109349
109407
  return;
109350
109408
  const claudeDir3 = installGlobally ? join152(homedir54(), ".claude") : join152(process.cwd(), ".claude");
109351
- if (!existsSync73(claudeDir3))
109409
+ if (!existsSync74(claudeDir3))
109352
109410
  return;
109353
109411
  try {
109354
109412
  const result = await handleDeletions(sourceMetadata, claudeDir3, inferKitTypeFromSourceMetadata(sourceMetadata));
@@ -109640,7 +109698,7 @@ async function migrateCommand(options2) {
109640
109698
  const interactive = process.stdout.isTTY && !options2.yes;
109641
109699
  const conflictActions = plan.actions.filter((a3) => a3.action === "conflict");
109642
109700
  for (const action of conflictActions) {
109643
- if (!action.diff && action.targetPath && existsSync73(action.targetPath)) {
109701
+ if (!action.diff && action.targetPath && existsSync74(action.targetPath)) {
109644
109702
  try {
109645
109703
  const targetContent = await readFile68(action.targetPath, "utf-8");
109646
109704
  const sourceItem = effectiveAgents.find((a3) => a3.name === action.item) || effectiveCommands.find((c2) => c2.name === action.item) || (effectiveConfigItem?.name === action.item ? effectiveConfigItem : null) || effectiveRuleItems.find((r2) => r2.name === action.item) || effectiveHookItems.find((h2) => h2.name === action.item);
@@ -109956,7 +110014,7 @@ async function migrateCommand(options2) {
109956
110014
  async function rollbackResults(results) {
109957
110015
  const rolledBackPaths = new Set;
109958
110016
  for (const result of results) {
109959
- if (!result.path || !existsSync73(result.path))
110017
+ if (!result.path || !existsSync74(result.path))
109960
110018
  continue;
109961
110019
  try {
109962
110020
  if (result.overwritten)
@@ -110523,7 +110581,7 @@ Please use only one download method.`);
110523
110581
  }
110524
110582
  // src/commands/plan/plan-command.ts
110525
110583
  init_output_manager();
110526
- import { existsSync as existsSync76, statSync as statSync13 } from "node:fs";
110584
+ import { existsSync as existsSync77, statSync as statSync13 } from "node:fs";
110527
110585
  import { dirname as dirname48, isAbsolute as isAbsolute13, join as join157, parse as parse3, resolve as resolve55 } from "node:path";
110528
110586
 
110529
110587
  // src/commands/plan/plan-read-handlers.ts
@@ -110533,14 +110591,14 @@ init_plans_registry();
110533
110591
  init_logger();
110534
110592
  init_output_manager();
110535
110593
  var import_picocolors37 = __toESM(require_picocolors(), 1);
110536
- import { existsSync as existsSync75, statSync as statSync12 } from "node:fs";
110594
+ import { existsSync as existsSync76, statSync as statSync12 } from "node:fs";
110537
110595
  import { basename as basename31, dirname as dirname46, join as join156, relative as relative32, resolve as resolve53 } from "node:path";
110538
110596
 
110539
110597
  // src/commands/plan/plan-dependencies.ts
110540
110598
  init_config();
110541
110599
  init_plan_parser();
110542
110600
  init_plans_registry();
110543
- import { existsSync as existsSync74 } from "node:fs";
110601
+ import { existsSync as existsSync75 } from "node:fs";
110544
110602
  import { dirname as dirname45, join as join155 } from "node:path";
110545
110603
  async function resolvePlanDependencies(references, currentPlanFile, options2 = {}) {
110546
110604
  if (references.length === 0)
@@ -110563,7 +110621,7 @@ async function resolvePlanDependencies(references, currentPlanFile, options2 = {
110563
110621
  const scopeRoot = resolvePlanDirForScope(scope, projectRoot, config);
110564
110622
  const planFile = join155(scopeRoot, planId, "plan.md");
110565
110623
  const isSelfReference = planFile === currentPlanFile;
110566
- if (!existsSync74(planFile)) {
110624
+ if (!existsSync75(planFile)) {
110567
110625
  return {
110568
110626
  reference,
110569
110627
  scope,
@@ -110703,7 +110761,7 @@ async function handleStatus(target, options2) {
110703
110761
  }
110704
110762
  const effectiveTarget = !resolvedTarget && globalBaseDir ? globalBaseDir : resolvedTarget;
110705
110763
  const t = effectiveTarget ? resolve53(effectiveTarget) : null;
110706
- const plansDir = t && existsSync75(t) && statSync12(t).isDirectory() && !existsSync75(join156(t, "plan.md")) ? t : null;
110764
+ const plansDir = t && existsSync76(t) && statSync12(t).isDirectory() && !existsSync76(join156(t, "plan.md")) ? t : null;
110707
110765
  if (plansDir) {
110708
110766
  const planFiles = scanPlanDir(plansDir);
110709
110767
  if (planFiles.length === 0) {
@@ -111107,19 +111165,19 @@ function resolveTargetPath(target, baseDir) {
111107
111165
  return resolve55(target);
111108
111166
  }
111109
111167
  const cwdCandidate = resolve55(target);
111110
- if (existsSync76(cwdCandidate)) {
111168
+ if (existsSync77(cwdCandidate)) {
111111
111169
  return cwdCandidate;
111112
111170
  }
111113
111171
  return resolve55(baseDir, target);
111114
111172
  }
111115
111173
  function resolvePlanFile(target, baseDir) {
111116
111174
  const t = target ? resolveTargetPath(target, baseDir) : baseDir ? resolve55(baseDir) : process.cwd();
111117
- if (existsSync76(t)) {
111175
+ if (existsSync77(t)) {
111118
111176
  const stat24 = statSync13(t);
111119
111177
  if (stat24.isFile())
111120
111178
  return t;
111121
111179
  const candidate = join157(t, "plan.md");
111122
- if (existsSync76(candidate))
111180
+ if (existsSync77(candidate))
111123
111181
  return candidate;
111124
111182
  }
111125
111183
  if (!target && !baseDir) {
@@ -111127,7 +111185,7 @@ function resolvePlanFile(target, baseDir) {
111127
111185
  const root = parse3(dir).root;
111128
111186
  while (dir !== root) {
111129
111187
  const candidate = join157(dir, "plan.md");
111130
- if (existsSync76(candidate))
111188
+ if (existsSync77(candidate))
111131
111189
  return candidate;
111132
111190
  dir = dirname48(dir);
111133
111191
  }
@@ -111177,7 +111235,7 @@ async function planCommand(action, target, options2) {
111177
111235
  let resolvedTarget = target;
111178
111236
  if (resolvedAction && !knownActions.has(resolvedAction)) {
111179
111237
  const looksLikePath = resolvedAction.includes("/") || resolvedAction.includes("\\") || resolvedAction.endsWith(".md") || resolvedAction === "." || resolvedAction === "..";
111180
- const existsOnDisk = !looksLikePath && existsSync76(resolve55(resolvedAction));
111238
+ const existsOnDisk = !looksLikePath && existsSync77(resolve55(resolvedAction));
111181
111239
  if (looksLikePath || existsOnDisk) {
111182
111240
  resolvedTarget = resolvedAction;
111183
111241
  resolvedAction = undefined;
@@ -111219,13 +111277,13 @@ init_ack_data2();
111219
111277
  init_logger();
111220
111278
  init_safe_prompts();
111221
111279
  var import_picocolors39 = __toESM(require_picocolors(), 1);
111222
- import { existsSync as existsSync77 } from "node:fs";
111280
+ import { existsSync as existsSync78 } from "node:fs";
111223
111281
  import { resolve as resolve56 } from "node:path";
111224
111282
  async function handleAdd(projectPath, options2) {
111225
111283
  logger.debug(`Adding project: ${projectPath}, options: ${JSON.stringify(options2)}`);
111226
111284
  intro("Add Project");
111227
111285
  const absolutePath = resolve56(projectPath);
111228
- if (!existsSync77(absolutePath)) {
111286
+ if (!existsSync78(absolutePath)) {
111229
111287
  log.error(`Path does not exist: ${absolutePath}`);
111230
111288
  process.exitCode = 1;
111231
111289
  return;
@@ -113080,7 +113138,7 @@ ${import_picocolors45.default.bold(import_picocolors45.default.cyan(result.kitCo
113080
113138
 
113081
113139
  // src/commands/watch/watch-command.ts
113082
113140
  init_logger();
113083
- import { existsSync as existsSync83 } from "node:fs";
113141
+ import { existsSync as existsSync84 } from "node:fs";
113084
113142
  import { rm as rm21 } from "node:fs/promises";
113085
113143
  import { join as join168 } from "node:path";
113086
113144
  var import_picocolors46 = __toESM(require_picocolors(), 1);
@@ -114379,14 +114437,14 @@ function cleanExpiredIssues(state, ttlDays) {
114379
114437
  init_ck_config_manager();
114380
114438
  init_file_io();
114381
114439
  init_logger();
114382
- import { existsSync as existsSync79 } from "node:fs";
114440
+ import { existsSync as existsSync80 } from "node:fs";
114383
114441
  import { mkdir as mkdir41, readFile as readFile71 } from "node:fs/promises";
114384
114442
  import { dirname as dirname50 } from "node:path";
114385
114443
  var PROCESSED_ISSUES_CAP = 500;
114386
114444
  async function readCkJson(projectDir) {
114387
114445
  const configPath = CkConfigManager.getProjectConfigPath(projectDir);
114388
114446
  try {
114389
- if (!existsSync79(configPath))
114447
+ if (!existsSync80(configPath))
114390
114448
  return {};
114391
114449
  const content = await readFile71(configPath, "utf-8");
114392
114450
  return JSON.parse(content);
@@ -114412,7 +114470,7 @@ async function loadWatchState(projectDir) {
114412
114470
  async function saveWatchState(projectDir, state) {
114413
114471
  const configPath = CkConfigManager.getProjectConfigPath(projectDir);
114414
114472
  const configDir = dirname50(configPath);
114415
- if (!existsSync79(configDir)) {
114473
+ if (!existsSync80(configDir)) {
114416
114474
  await mkdir41(configDir, { recursive: true });
114417
114475
  }
114418
114476
  const raw = await readCkJson(projectDir);
@@ -114539,7 +114597,7 @@ async function processImplementationQueue(state, config, setup, options2, watchL
114539
114597
  // src/commands/watch/phases/repo-scanner.ts
114540
114598
  init_logger();
114541
114599
  import { spawnSync as spawnSync7 } from "node:child_process";
114542
- import { existsSync as existsSync80 } from "node:fs";
114600
+ import { existsSync as existsSync81 } from "node:fs";
114543
114601
  import { readdir as readdir47, stat as stat25 } from "node:fs/promises";
114544
114602
  import { join as join165 } from "node:path";
114545
114603
  async function scanForRepos(parentDir) {
@@ -114553,7 +114611,7 @@ async function scanForRepos(parentDir) {
114553
114611
  if (!entryStat.isDirectory())
114554
114612
  continue;
114555
114613
  const gitDir = join165(fullPath, ".git");
114556
- if (!existsSync80(gitDir))
114614
+ if (!existsSync81(gitDir))
114557
114615
  continue;
114558
114616
  const result = spawnSync7("gh", ["repo", "view", "--json", "owner,name"], {
114559
114617
  encoding: "utf-8",
@@ -114577,7 +114635,7 @@ async function scanForRepos(parentDir) {
114577
114635
  // src/commands/watch/phases/setup-validator.ts
114578
114636
  init_logger();
114579
114637
  import { spawnSync as spawnSync8 } from "node:child_process";
114580
- import { existsSync as existsSync81 } from "node:fs";
114638
+ import { existsSync as existsSync82 } from "node:fs";
114581
114639
  import { homedir as homedir55 } from "node:os";
114582
114640
  import { join as join166 } from "node:path";
114583
114641
  async function validateSetup(cwd2) {
@@ -114611,7 +114669,7 @@ Run this command from a directory with a GitHub remote.`);
114611
114669
  throw new Error(`Failed to parse repository info: ${ghRepo.stdout}`);
114612
114670
  }
114613
114671
  const skillsPath = join166(homedir55(), ".claude", "skills");
114614
- const skillsAvailable = existsSync81(skillsPath);
114672
+ const skillsAvailable = existsSync82(skillsPath);
114615
114673
  if (!skillsAvailable) {
114616
114674
  logger.warning(`AckKit Engineer skills not found at ${skillsPath}`);
114617
114675
  }
@@ -114627,7 +114685,7 @@ Run this command from a directory with a GitHub remote.`);
114627
114685
  init_logger();
114628
114686
  init_path_resolver();
114629
114687
  import { createWriteStream as createWriteStream3, statSync as statSync14 } from "node:fs";
114630
- import { existsSync as existsSync82 } from "node:fs";
114688
+ import { existsSync as existsSync83 } from "node:fs";
114631
114689
  import { mkdir as mkdir42, rename as rename16 } from "node:fs/promises";
114632
114690
  import { join as join167 } from "node:path";
114633
114691
 
@@ -114642,7 +114700,7 @@ class WatchLogger {
114642
114700
  }
114643
114701
  async init() {
114644
114702
  try {
114645
- if (!existsSync82(this.logDir)) {
114703
+ if (!existsSync83(this.logDir)) {
114646
114704
  await mkdir42(this.logDir, { recursive: true });
114647
114705
  }
114648
114706
  const dateStr = formatDate(new Date);
@@ -114828,7 +114886,7 @@ async function watchCommand(options2) {
114828
114886
  }
114829
114887
  async function discoverRepos(options2, watchLog) {
114830
114888
  const cwd2 = process.cwd();
114831
- const isGitRepo = existsSync83(join168(cwd2, ".git"));
114889
+ const isGitRepo = existsSync84(join168(cwd2, ".git"));
114832
114890
  if (options2.force) {
114833
114891
  await forceRemoveLock(watchLog);
114834
114892
  }
@@ -115131,7 +115189,7 @@ init_logger();
115131
115189
  init_path_resolver();
115132
115190
  init_types3();
115133
115191
  init_types3();
115134
- import { existsSync as existsSync94, readFileSync as readFileSync25 } from "node:fs";
115192
+ import { existsSync as existsSync95, readFileSync as readFileSync26 } from "node:fs";
115135
115193
  import { join as join179 } from "node:path";
115136
115194
  var packageVersion2 = package_default.version;
115137
115195
  function formatInstalledKits(metadata) {
@@ -115201,9 +115259,9 @@ async function displayVersion() {
115201
115259
  const prefix = PathResolver.getPathPrefix(false);
115202
115260
  const localMetadataPath = prefix ? join179(process.cwd(), prefix, "metadata.json") : join179(process.cwd(), "metadata.json");
115203
115261
  const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
115204
- if (!isLocalSameAsGlobal && existsSync94(localMetadataPath)) {
115262
+ if (!isLocalSameAsGlobal && existsSync95(localMetadataPath)) {
115205
115263
  try {
115206
- const rawMetadata = JSON.parse(readFileSync25(localMetadataPath, "utf-8"));
115264
+ const rawMetadata = JSON.parse(readFileSync26(localMetadataPath, "utf-8"));
115207
115265
  const metadata = MetadataSchema.parse(rawMetadata);
115208
115266
  const kitsDisplay = formatInstalledKits(metadata);
115209
115267
  if (kitsDisplay) {
@@ -115215,9 +115273,9 @@ async function displayVersion() {
115215
115273
  logger.verbose("Failed to parse local metadata.json", { error });
115216
115274
  }
115217
115275
  }
115218
- if (existsSync94(globalMetadataPath)) {
115276
+ if (existsSync95(globalMetadataPath)) {
115219
115277
  try {
115220
- const rawMetadata = JSON.parse(readFileSync25(globalMetadataPath, "utf-8"));
115278
+ const rawMetadata = JSON.parse(readFileSync26(globalMetadataPath, "utf-8"));
115221
115279
  const metadata = MetadataSchema.parse(rawMetadata);
115222
115280
  const kitsDisplay = formatInstalledKits(metadata);
115223
115281
  if (kitsDisplay) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chiendt/ack-cli",
3
- "version": "1.3.0-dev.5",
3
+ "version": "1.3.0-dev.6",
4
4
  "description": "ACK CLI - tool for bootstrapping and updating ACK kits (Claude Code agent kits)",
5
5
  "type": "module",
6
6
  "repository": {