@hasna/instructions 0.4.11 → 0.4.13

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=add-duplicate-target.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-duplicate-target.test.d.ts","sourceRoot":"","sources":["../../src/cli/add-duplicate-target.test.ts"],"names":[],"mappings":""}
package/dist/cli/index.js CHANGED
@@ -7550,6 +7550,9 @@ function scanSecrets(content, format) {
7550
7550
  const r = redactContent(content, format);
7551
7551
  return r.redacted;
7552
7552
  }
7553
+ function isSecretVarName(name) {
7554
+ return SECRET_KEY_PATTERN.test(name);
7555
+ }
7553
7556
  var SECRET_KEY_PATTERN, VALUE_PATTERNS, MIN_SECRET_VALUE_LEN = 8;
7554
7557
  var init_redact = __esm(() => {
7555
7558
  SECRET_KEY_PATTERN = /^(.*_?API_?KEY|.*_?TOKEN|.*_?SECRET|.*_?PASSWORD|.*_?PASSWD|.*_?CREDENTIAL|.*_?AUTH(?:_TOKEN|_KEY|ORIZATION)?|.*_?PRIVATE_?KEY|.*_?ACCESS_?KEY|.*_?CLIENT_?SECRET|.*_?SIGNING_?KEY|.*_?ENCRYPTION_?KEY|.*_AUTH_TOKEN)$/i;
@@ -11606,6 +11609,7 @@ async function writeConfigResult(config, targetPath, content, opts, meta = {}) {
11606
11609
  new_content: renderedContent,
11607
11610
  dry_run: opts.dryRun ?? false,
11608
11611
  changed,
11612
+ primary_changed: changed,
11609
11613
  unresolved_template_vars: [...new Set([
11610
11614
  ...renderedTarget.unresolved,
11611
11615
  ...rendered.unresolved
@@ -11672,7 +11676,7 @@ async function applyPreparedConfig(config, opts) {
11672
11676
  if (config.target_path && shouldApplyPrimary) {
11673
11677
  result = await writeConfigResult(config, config.target_path, config.content, opts);
11674
11678
  result.outputs = outputResults;
11675
- result.changed = result.changed || outputResults.some((output) => output.changed);
11679
+ result.changed = result.primary_changed || outputResults.some((output) => output.changed);
11676
11680
  result.unresolved_template_vars = [...new Set([
11677
11681
  ...result.unresolved_template_vars ?? [],
11678
11682
  ...outputResults.flatMap((output) => output.unresolved_template_vars ?? [])
@@ -12111,7 +12115,8 @@ async function syncProject(opts) {
12111
12115
  }
12112
12116
  for (const ruleDir of [
12113
12117
  { dir: join9(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
12114
- { dir: join9(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" }
12118
+ { dir: join9(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" },
12119
+ { dir: join9(absDir, ".cursor", "rules"), agent: "cursor", namePrefix: "cursor-rules" }
12115
12120
  ]) {
12116
12121
  if (!existsSync9(ruleDir.dir))
12117
12122
  continue;
@@ -12289,30 +12294,86 @@ async function syncToDisk(opts = {}) {
12289
12294
  }
12290
12295
  return result;
12291
12296
  }
12292
- function buildDiff(expectedContent, targetPath) {
12297
+ function redactionPlaceholders(storedLine) {
12298
+ const found = [...storedLine.match(CERTAIN_PLACEHOLDER_RE) ?? []];
12299
+ const assigned = storedLine.match(ASSIGNED_PLACEHOLDER_RE);
12300
+ if (assigned) {
12301
+ const name = assigned[3] ?? assigned[4] ?? assigned[5];
12302
+ if (name && isSecretVarName(name))
12303
+ found.push(assigned[2]);
12304
+ }
12305
+ return found;
12306
+ }
12307
+ function redactFormatForTarget(targetPath, storedFormat) {
12308
+ const p = targetPath.toLowerCase();
12309
+ if (/(^|\/)\.(zshrc|zprofile|bashrc|bash_profile|profile|zshenv|env)$/.test(p) || p.endsWith(".env"))
12310
+ return "shell";
12311
+ if (/(^|\/)\.(npmrc|yarnrc|curlrc|netrc)$/.test(p))
12312
+ return "ini";
12313
+ return storedFormat;
12314
+ }
12315
+ function storedPlaceholderIsLiteralOnDisk(storedLine, diskLine) {
12316
+ return redactionPlaceholders(storedLine).some((p) => !diskLine.includes(p));
12317
+ }
12318
+ function buildDiff(expectedContent, targetPath, storedFormat, showSecrets) {
12293
12319
  const path = expandPath(targetPath);
12294
12320
  if (!existsSync9(path))
12295
12321
  return `(file not found on disk: ${path})`;
12296
12322
  const diskContent = readFileSync6(path, "utf-8");
12297
12323
  if (diskContent === expectedContent)
12298
12324
  return "(no diff \u2014 identical)";
12325
+ const format = redactFormatForTarget(targetPath, storedFormat);
12299
12326
  const stored = expectedContent.split(`
12300
12327
  `);
12301
12328
  const disk = diskContent.split(`
12302
12329
  `);
12330
+ const { content: redactedDiskContent, redacted } = showSecrets ? { content: diskContent, redacted: [] } : redactContent(diskContent, format);
12331
+ const redactedDisk = redactedDiskContent.split(`
12332
+ `);
12333
+ const reasonByLine = new Map;
12334
+ for (const r of redacted)
12335
+ if (!reasonByLine.has(r.line))
12336
+ reasonByLine.set(r.line, r.reason);
12303
12337
  const lines = [`--- stored (DB)`, `+++ disk (${path})`];
12304
12338
  const maxLen = Math.max(stored.length, disk.length);
12305
12339
  for (let i = 0;i < maxLen; i++) {
12340
+ const lineNo = i + 1;
12306
12341
  const s = stored[i];
12307
12342
  const dk = disk[i];
12308
12343
  if (s === dk) {
12309
12344
  if (s !== undefined)
12310
12345
  lines.push(` ${s}`);
12311
- } else {
12346
+ continue;
12347
+ }
12348
+ if (showSecrets || dk === undefined) {
12312
12349
  if (s !== undefined)
12313
12350
  lines.push(`-${s}`);
12314
12351
  if (dk !== undefined)
12315
12352
  lines.push(`+${dk}`);
12353
+ continue;
12354
+ }
12355
+ const structural = s !== undefined && storedPlaceholderIsLiteralOnDisk(s, dk);
12356
+ const patterned = reasonByLine.has(lineNo);
12357
+ if (!structural && !patterned) {
12358
+ if (s !== undefined)
12359
+ lines.push(`-${s}`);
12360
+ lines.push(`+${dk}`);
12361
+ continue;
12362
+ }
12363
+ if (structural) {
12364
+ const placeholder = redactionPlaceholders(s).find((p) => !dk.includes(p)) ?? "a placeholder";
12365
+ lines.push(`~line ${lineNo} differs: stored \`${s}\`, disk holds a literal value for ${placeholder} \u2014 redacted (use --show-secrets on a TTY to reveal)`);
12366
+ continue;
12367
+ }
12368
+ const safe = redactedDisk[i] ?? "";
12369
+ const reason = reasonByLine.get(lineNo);
12370
+ if (s !== undefined && safe === s) {
12371
+ lines.push(`~line ${lineNo} differs: stored \`${s}\`, disk holds a literal value (${reason}) \u2014 redacted (use --show-secrets on a TTY to reveal)`);
12372
+ } else {
12373
+ if (s !== undefined)
12374
+ lines.push(`-${s}`);
12375
+ lines.push(`+${safe}`);
12376
+ lines.push(`~line ${lineNo}: disk value redacted (${reason}) \u2014 use --show-secrets on a TTY to reveal`);
12316
12377
  }
12317
12378
  }
12318
12379
  return lines.join(`
@@ -12327,15 +12388,16 @@ async function diffConfig(config, opts = {}) {
12327
12388
  if (isGeneratedOutputTarget2(config, outputOwnerIdsByTarget(contextConfigs))) {
12328
12389
  return "(generated output \u2014 managed by fan-out)";
12329
12390
  }
12391
+ const showSecrets = opts.showSecrets ?? false;
12330
12392
  if (config.target_path) {
12331
- const diff = buildDiff(config.content, config.target_path);
12393
+ const diff = buildDiff(config.content, config.target_path, config.format, showSecrets);
12332
12394
  if (!diff.includes("no diff"))
12333
12395
  diffs.push(diff);
12334
12396
  }
12335
12397
  if (config.outputs.length > 0) {
12336
12398
  for (const output of config.outputs) {
12337
12399
  const expected = applyTransform(config, output, { configs: contextConfigs });
12338
- const diff = buildDiff(expected, output.target_path);
12400
+ const diff = buildDiff(expected, output.target_path, detectFormat(output.target_path), showSecrets);
12339
12401
  if (!diff.includes("no diff"))
12340
12402
  diffs.push(diff);
12341
12403
  }
@@ -12406,7 +12468,7 @@ function detectFormat(filePath) {
12406
12468
  return "ini";
12407
12469
  return "text";
12408
12470
  }
12409
- var CLAUDE_PROMPT_OUTPUTS, KNOWN_CONFIGS, PROJECT_CONFIG_FILES;
12471
+ var CLAUDE_PROMPT_OUTPUTS, KNOWN_CONFIGS, PROJECT_CONFIG_FILES, CERTAIN_PLACEHOLDER_RE, ASSIGNED_PLACEHOLDER_RE;
12410
12472
  var init_sync = __esm(() => {
12411
12473
  init_config_store();
12412
12474
  init_apply();
@@ -12462,6 +12524,7 @@ var init_sync = __esm(() => {
12462
12524
  { file: "AGENTS.md", category: "rules", agent: "codex", format: "markdown" },
12463
12525
  { file: ".codex/AGENTS.md", category: "rules", agent: "codex", format: "markdown" },
12464
12526
  { file: ".opencode/AGENTS.md", category: "rules", agent: "opencode", format: "markdown" },
12527
+ { file: "CODEWITH.md", category: "rules", agent: "codewith", format: "markdown" },
12465
12528
  { file: ".codewith/CODEWITH.md", category: "rules", agent: "codewith", format: "markdown" },
12466
12529
  { file: ".aicopilot/AICOPILOT.md", category: "rules", agent: "aicopilot", format: "markdown" },
12467
12530
  { file: "AICOPILOT.md", category: "rules", agent: "aicopilot", format: "markdown" },
@@ -12470,6 +12533,8 @@ var init_sync = __esm(() => {
12470
12533
  { file: ".agents/mcp_config.json", category: "mcp", agent: "antigravity", format: "json" },
12471
12534
  { file: ".qwen/settings.json", category: "agent", agent: "qwen", format: "json" }
12472
12535
  ];
12536
+ CERTAIN_PLACEHOLDER_RE = /\{\{[A-Za-z_][A-Za-z0-9_]*\}\}/g;
12537
+ ASSIGNED_PLACEHOLDER_RE = /[=:]\s*(["']?)(\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Z][A-Z0-9_]*)|%([A-Za-z_][A-Za-z0-9_]*)%)\1\s*,?\s*$/;
12473
12538
  });
12474
12539
 
12475
12540
  // src/lib/package-manager-guard.ts
@@ -13566,13 +13631,38 @@ var {
13566
13631
 
13567
13632
  // src/cli/index.tsx
13568
13633
  init_apply();
13569
- init_sync();
13570
- init_redact();
13571
13634
  import chalk from "chalk";
13572
13635
  import { existsSync as existsSync16, lstatSync as lstatSync4, readFileSync as readFileSync12, readSync, writeSync } from "fs";
13573
13636
  import { homedir as homedir7 } from "os";
13574
13637
  import { basename as basename7, join as join15, resolve as resolve8 } from "path";
13575
13638
 
13639
+ // src/lib/config-target-identity.ts
13640
+ init_apply();
13641
+ function findConfigsByTargetPath(configs, targetPath) {
13642
+ const wanted = normalizeTargetPath(targetPath);
13643
+ return configs.filter((config) => {
13644
+ if (config.kind === "reference")
13645
+ return false;
13646
+ if (!config.target_path)
13647
+ return false;
13648
+ return normalizeTargetPath(config.target_path) === wanted;
13649
+ });
13650
+ }
13651
+ function findDuplicateTargetPathGroups(configs) {
13652
+ const groups = new Map;
13653
+ for (const config of configs) {
13654
+ if (config.kind === "reference" || !config.target_path)
13655
+ continue;
13656
+ const key = normalizeTargetPath(config.target_path);
13657
+ groups.set(key, [...groups.get(key) ?? [], config]);
13658
+ }
13659
+ return [...groups.entries()].filter(([, rows]) => rows.length > 1).map(([target_path, rows]) => ({ target_path, configs: rows }));
13660
+ }
13661
+
13662
+ // src/cli/index.tsx
13663
+ init_sync();
13664
+ init_redact();
13665
+
13576
13666
  // src/lib/export.ts
13577
13667
  init_config_store();
13578
13668
  import { existsSync as existsSync10, mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
@@ -15356,7 +15446,7 @@ program.command("show <id>").alias("inspect").description("Show a config's conte
15356
15446
  process.exit(1);
15357
15447
  }
15358
15448
  });
15359
- program.command("add <path>").description("Ingest a file into the config DB").option("-n, --name <name>", "config name (defaults to filename)").option("-c, --category <cat>", "category override").option("-a, --agent <agent>", "agent override").option("-k, --kind <kind>", "kind: file|reference", "file").option("--template", "mark as template (has {{VAR}} placeholders)").action(async (filePath, opts) => {
15449
+ program.command("add <path>").description("Ingest a file into the config DB").option("-n, --name <name>", "config name (defaults to filename)").option("-c, --category <cat>", "category override").option("-a, --agent <agent>", "agent override").option("-k, --kind <kind>", "kind: file|reference", "file").option("--template", "mark as template (has {{VAR}} placeholders)").option("--update", "if a config already owns this path, update that row in place instead of refusing").action(async (filePath, opts) => {
15360
15450
  const abs = resolve8(filePath);
15361
15451
  if (!existsSync16(abs)) {
15362
15452
  console.error(chalk.red(`File not found: ${abs}`));
@@ -15367,7 +15457,39 @@ program.command("add <path>").description("Ingest a file into the config DB").op
15367
15457
  const { content, redacted, isTemplate: isTemplate2 } = redactContent(rawContent, fmt);
15368
15458
  const targetPath = abs.startsWith(homedir7()) ? abs.replace(homedir7(), "~") : abs;
15369
15459
  const name = opts.name || filePath.split("/").pop();
15370
- const config = await resolveConfigStore().createConfig({
15460
+ const store = resolveConfigStore();
15461
+ const existingOwners = opts.kind === "reference" ? [] : findConfigsByTargetPath(await store.listConfigs(), targetPath);
15462
+ if (existingOwners.length > 0 && !opts.update) {
15463
+ const owners = existingOwners.map((owner) => `${owner.slug} (${owner.id})`).join(", ");
15464
+ console.error(chalk.red(`${targetPath} is already tracked by: ${owners}`));
15465
+ if (existingOwners.length > 1) {
15466
+ console.error(chalk.red(` ${existingOwners.length} rows already collide on this path \u2014 apply order between them is undefined.`));
15467
+ }
15468
+ console.error(chalk.dim(" Use `instructions add <path> --update` to refresh that row in place,"));
15469
+ console.error(chalk.dim(" `instructions sync` to pull disk changes in, or `instructions delete <id>` first."));
15470
+ process.exit(1);
15471
+ }
15472
+ let config;
15473
+ if (existingOwners.length > 0) {
15474
+ const [target, ...rest] = existingOwners;
15475
+ config = await store.updateConfig(target.id, {
15476
+ content,
15477
+ format: fmt,
15478
+ is_template: (opts.template ?? false) || isTemplate2,
15479
+ ...opts.category ? { category: opts.category } : {},
15480
+ ...opts.agent ? { agent: opts.agent } : {}
15481
+ });
15482
+ console.log(chalk.green("\u2713") + ` Updated: ${chalk.bold(config.name)} ${chalk.dim(`(${config.slug})`)}`);
15483
+ if (rest.length > 0) {
15484
+ console.log(chalk.yellow(` \u26A0 ${rest.length} other row(s) still target ${targetPath}: ${rest.map((r) => r.slug).join(", ")}`));
15485
+ console.log(chalk.yellow(" Apply order between them is undefined. Delete the extras."));
15486
+ }
15487
+ if (redacted.length > 0) {
15488
+ console.log(chalk.yellow(` \u26A0 Redacted ${redacted.length} secret(s).`));
15489
+ }
15490
+ return;
15491
+ }
15492
+ config = await store.createConfig({
15371
15493
  name,
15372
15494
  kind: opts.kind ?? "file",
15373
15495
  category: opts.category ?? detectCategory(abs),
@@ -15413,12 +15535,12 @@ program.command("apply <id>").description("Apply a config to its target_path and
15413
15535
  throw new Error(report.failures.map((failure) => failure.message).join("; "));
15414
15536
  }
15415
15537
  for (const result of report.results) {
15416
- const status = opts.dryRun ? chalk.yellow("[dry-run]") : result.changed ? chalk.green("\u2713") : chalk.dim("=");
15417
- const change = result.changed ? "changed" : "unchanged";
15538
+ const status = opts.dryRun ? chalk.yellow("[dry-run]") : result.primary_changed ? chalk.green("\u2713") : chalk.dim("=");
15539
+ const change = result.primary_changed ? "changed" : "unchanged";
15418
15540
  console.log(`${status} ${result.path} ${chalk.dim(`(${change})`)}`);
15419
15541
  for (const output of result.outputs ?? []) {
15420
- const outputStatus = opts.dryRun ? chalk.yellow("[dry-run]") : output.changed ? chalk.green("\u2713") : chalk.dim("=");
15421
- const outputChange = output.changed ? "changed" : "unchanged";
15542
+ const outputStatus = opts.dryRun ? chalk.yellow("[dry-run]") : output.primary_changed ? chalk.green("\u2713") : chalk.dim("=");
15543
+ const outputChange = output.primary_changed ? "changed" : "unchanged";
15422
15544
  console.log(` ${outputStatus} ${output.path} ${chalk.dim(`[${output.agent}/${output.transform}] (${outputChange})`)}`);
15423
15545
  }
15424
15546
  }
@@ -15430,12 +15552,18 @@ program.command("apply <id>").description("Apply a config to its target_path and
15430
15552
  process.exit(1);
15431
15553
  }
15432
15554
  });
15433
- program.command("diff [id]").description("Show diff between stored config and disk (omit id for --all)").option("--all", "diff every known config against disk").action(async (id, opts) => {
15555
+ program.command("diff [id]").description("Show diff between stored config and disk (omit id for --all). Credential values on disk are redacted.").option("--all", "diff every known config against disk").option("--show-secrets", "render credential values from disk verbatim (interactive TTY only)").action(async (id, opts) => {
15434
15556
  try {
15557
+ if (opts.showSecrets && !process.stdout.isTTY) {
15558
+ console.error(chalk.red("--show-secrets refuses to run on a non-TTY: the output would be captured verbatim into a log or transcript."));
15559
+ console.error(chalk.dim("Run it in an interactive terminal, or use the redacted default."));
15560
+ process.exit(1);
15561
+ }
15562
+ const showSecrets = Boolean(opts.showSecrets);
15435
15563
  const store = resolveConfigStore();
15436
15564
  if (id) {
15437
15565
  const config = await store.getConfig(id);
15438
- console.log(await diffConfig(config, { store }));
15566
+ console.log(await diffConfig(config, { store, showSecrets }));
15439
15567
  return;
15440
15568
  }
15441
15569
  const configs = await store.listConfigs({ kind: "file" });
@@ -15443,7 +15571,7 @@ program.command("diff [id]").description("Show diff between stored config and di
15443
15571
  for (const c of configs) {
15444
15572
  if (!c.target_path)
15445
15573
  continue;
15446
- const diff = await diffConfig(c, { store });
15574
+ const diff = await diffConfig(c, { store, showSecrets });
15447
15575
  if (diff.includes("no diff") || diff.includes("not found"))
15448
15576
  continue;
15449
15577
  drifted++;
@@ -15682,7 +15810,7 @@ profileCmd.command("apply [id]").description("Apply all configs in a profile to
15682
15810
  const results = report.results;
15683
15811
  let changed = 0;
15684
15812
  for (const r of results) {
15685
- const status = opts.dryRun ? chalk.yellow("[dry-run]") : r.changed ? chalk.green("\u2713") : chalk.dim("=");
15813
+ const status = opts.dryRun ? chalk.yellow("[dry-run]") : r.primary_changed ? chalk.green("\u2713") : chalk.dim("=");
15686
15814
  console.log(`${status} ${r.path}`);
15687
15815
  if (r.changed)
15688
15816
  changed++;
@@ -16351,6 +16479,20 @@ Stored configs (${allConfigs.length}):`));
16351
16479
  secretCount += found.length;
16352
16480
  }
16353
16481
  secretCount === 0 ? pass("No unredacted secrets") : fail(`${secretCount} unredacted secret(s) \u2014 run \`configs scan --fix\``);
16482
+ const duplicateTargets = findDuplicateTargetPathGroups(allConfigs);
16483
+ if (duplicateTargets.length === 0) {
16484
+ pass("No target path is claimed by more than one config");
16485
+ } else {
16486
+ const rowCount = duplicateTargets.reduce((total, group) => total + group.configs.length, 0);
16487
+ fail(`${duplicateTargets.length} target path(s) claimed by more than one config (${rowCount} rows) \u2014 apply order between them is undefined`);
16488
+ for (const group of duplicateTargets) {
16489
+ console.log(chalk.yellow(` ${group.target_path}`));
16490
+ for (const c of group.configs) {
16491
+ console.log(chalk.dim(` ${c.slug} (${c.id}) updated ${c.updated_at}`));
16492
+ }
16493
+ }
16494
+ console.log(chalk.dim(" Keep one row per path: `instructions delete <id>` for the extras."));
16495
+ }
16354
16496
  console.log(`
16355
16497
  ${issues === 0 ? chalk.green("\u2713 All checks passed") : chalk.yellow(`${issues} issue(s) found`)}`);
16356
16498
  });
package/dist/index.js CHANGED
@@ -5515,6 +5515,9 @@ function scanSecrets(content, format) {
5515
5515
  function hasSecrets(content, format) {
5516
5516
  return scanSecrets(content, format).length > 0;
5517
5517
  }
5518
+ function isSecretVarName(name) {
5519
+ return SECRET_KEY_PATTERN.test(name);
5520
+ }
5518
5521
 
5519
5522
  // src/lib/session-render-contract.ts
5520
5523
  var CODEWITH_NATIVE_IMPORTS_ENV = "HASNA_CONFIGS_CODEWITH_NATIVE_IMPORTS";
@@ -9620,6 +9623,7 @@ async function writeConfigResult(config, targetPath, content, opts, meta = {}) {
9620
9623
  new_content: renderedContent,
9621
9624
  dry_run: opts.dryRun ?? false,
9622
9625
  changed,
9626
+ primary_changed: changed,
9623
9627
  unresolved_template_vars: [...new Set([
9624
9628
  ...renderedTarget.unresolved,
9625
9629
  ...rendered.unresolved
@@ -9686,7 +9690,7 @@ async function applyPreparedConfig(config, opts) {
9686
9690
  if (config.target_path && shouldApplyPrimary) {
9687
9691
  result = await writeConfigResult(config, config.target_path, config.content, opts);
9688
9692
  result.outputs = outputResults;
9689
- result.changed = result.changed || outputResults.some((output) => output.changed);
9693
+ result.changed = result.primary_changed || outputResults.some((output) => output.changed);
9690
9694
  result.unresolved_template_vars = [...new Set([
9691
9695
  ...result.unresolved_template_vars ?? [],
9692
9696
  ...outputResults.flatMap((output) => output.unresolved_template_vars ?? [])
@@ -11452,6 +11456,7 @@ var PROJECT_CONFIG_FILES = [
11452
11456
  { file: "AGENTS.md", category: "rules", agent: "codex", format: "markdown" },
11453
11457
  { file: ".codex/AGENTS.md", category: "rules", agent: "codex", format: "markdown" },
11454
11458
  { file: ".opencode/AGENTS.md", category: "rules", agent: "opencode", format: "markdown" },
11459
+ { file: "CODEWITH.md", category: "rules", agent: "codewith", format: "markdown" },
11455
11460
  { file: ".codewith/CODEWITH.md", category: "rules", agent: "codewith", format: "markdown" },
11456
11461
  { file: ".aicopilot/AICOPILOT.md", category: "rules", agent: "aicopilot", format: "markdown" },
11457
11462
  { file: "AICOPILOT.md", category: "rules", agent: "aicopilot", format: "markdown" },
@@ -11502,7 +11507,8 @@ async function syncProject(opts) {
11502
11507
  }
11503
11508
  for (const ruleDir of [
11504
11509
  { dir: join10(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
11505
- { dir: join10(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" }
11510
+ { dir: join10(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" },
11511
+ { dir: join10(absDir, ".cursor", "rules"), agent: "cursor", namePrefix: "cursor-rules" }
11506
11512
  ]) {
11507
11513
  if (!existsSync11(ruleDir.dir))
11508
11514
  continue;
@@ -11680,30 +11686,88 @@ async function syncToDisk(opts = {}) {
11680
11686
  }
11681
11687
  return result;
11682
11688
  }
11683
- function buildDiff(expectedContent, targetPath) {
11689
+ var CERTAIN_PLACEHOLDER_RE = /\{\{[A-Za-z_][A-Za-z0-9_]*\}\}/g;
11690
+ var ASSIGNED_PLACEHOLDER_RE = /[=:]\s*(["']?)(\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Z][A-Z0-9_]*)|%([A-Za-z_][A-Za-z0-9_]*)%)\1\s*,?\s*$/;
11691
+ function redactionPlaceholders(storedLine) {
11692
+ const found = [...storedLine.match(CERTAIN_PLACEHOLDER_RE) ?? []];
11693
+ const assigned = storedLine.match(ASSIGNED_PLACEHOLDER_RE);
11694
+ if (assigned) {
11695
+ const name = assigned[3] ?? assigned[4] ?? assigned[5];
11696
+ if (name && isSecretVarName(name))
11697
+ found.push(assigned[2]);
11698
+ }
11699
+ return found;
11700
+ }
11701
+ function redactFormatForTarget(targetPath, storedFormat) {
11702
+ const p = targetPath.toLowerCase();
11703
+ if (/(^|\/)\.(zshrc|zprofile|bashrc|bash_profile|profile|zshenv|env)$/.test(p) || p.endsWith(".env"))
11704
+ return "shell";
11705
+ if (/(^|\/)\.(npmrc|yarnrc|curlrc|netrc)$/.test(p))
11706
+ return "ini";
11707
+ return storedFormat;
11708
+ }
11709
+ function storedPlaceholderIsLiteralOnDisk(storedLine, diskLine) {
11710
+ return redactionPlaceholders(storedLine).some((p) => !diskLine.includes(p));
11711
+ }
11712
+ function buildDiff(expectedContent, targetPath, storedFormat, showSecrets) {
11684
11713
  const path = expandPath(targetPath);
11685
11714
  if (!existsSync11(path))
11686
11715
  return `(file not found on disk: ${path})`;
11687
11716
  const diskContent = readFileSync9(path, "utf-8");
11688
11717
  if (diskContent === expectedContent)
11689
11718
  return "(no diff \u2014 identical)";
11719
+ const format = redactFormatForTarget(targetPath, storedFormat);
11690
11720
  const stored = expectedContent.split(`
11691
11721
  `);
11692
11722
  const disk = diskContent.split(`
11693
11723
  `);
11724
+ const { content: redactedDiskContent, redacted } = showSecrets ? { content: diskContent, redacted: [] } : redactContent(diskContent, format);
11725
+ const redactedDisk = redactedDiskContent.split(`
11726
+ `);
11727
+ const reasonByLine = new Map;
11728
+ for (const r of redacted)
11729
+ if (!reasonByLine.has(r.line))
11730
+ reasonByLine.set(r.line, r.reason);
11694
11731
  const lines = [`--- stored (DB)`, `+++ disk (${path})`];
11695
11732
  const maxLen = Math.max(stored.length, disk.length);
11696
11733
  for (let i = 0;i < maxLen; i++) {
11734
+ const lineNo = i + 1;
11697
11735
  const s = stored[i];
11698
11736
  const dk = disk[i];
11699
11737
  if (s === dk) {
11700
11738
  if (s !== undefined)
11701
11739
  lines.push(` ${s}`);
11702
- } else {
11740
+ continue;
11741
+ }
11742
+ if (showSecrets || dk === undefined) {
11703
11743
  if (s !== undefined)
11704
11744
  lines.push(`-${s}`);
11705
11745
  if (dk !== undefined)
11706
11746
  lines.push(`+${dk}`);
11747
+ continue;
11748
+ }
11749
+ const structural = s !== undefined && storedPlaceholderIsLiteralOnDisk(s, dk);
11750
+ const patterned = reasonByLine.has(lineNo);
11751
+ if (!structural && !patterned) {
11752
+ if (s !== undefined)
11753
+ lines.push(`-${s}`);
11754
+ lines.push(`+${dk}`);
11755
+ continue;
11756
+ }
11757
+ if (structural) {
11758
+ const placeholder = redactionPlaceholders(s).find((p) => !dk.includes(p)) ?? "a placeholder";
11759
+ lines.push(`~line ${lineNo} differs: stored \`${s}\`, disk holds a literal value for ${placeholder} \u2014 redacted (use --show-secrets on a TTY to reveal)`);
11760
+ continue;
11761
+ }
11762
+ const safe = redactedDisk[i] ?? "";
11763
+ const reason = reasonByLine.get(lineNo);
11764
+ if (s !== undefined && safe === s) {
11765
+ lines.push(`~line ${lineNo} differs: stored \`${s}\`, disk holds a literal value (${reason}) \u2014 redacted (use --show-secrets on a TTY to reveal)`);
11766
+ } else {
11767
+ if (s !== undefined)
11768
+ lines.push(`-${s}`);
11769
+ lines.push(`+${safe}`);
11770
+ lines.push(`~line ${lineNo}: disk value redacted (${reason}) \u2014 use --show-secrets on a TTY to reveal`);
11707
11771
  }
11708
11772
  }
11709
11773
  return lines.join(`
@@ -11718,15 +11782,16 @@ async function diffConfig(config, opts = {}) {
11718
11782
  if (isGeneratedOutputTarget2(config, outputOwnerIdsByTarget(contextConfigs))) {
11719
11783
  return "(generated output \u2014 managed by fan-out)";
11720
11784
  }
11785
+ const showSecrets = opts.showSecrets ?? false;
11721
11786
  if (config.target_path) {
11722
- const diff = buildDiff(config.content, config.target_path);
11787
+ const diff = buildDiff(config.content, config.target_path, config.format, showSecrets);
11723
11788
  if (!diff.includes("no diff"))
11724
11789
  diffs.push(diff);
11725
11790
  }
11726
11791
  if (config.outputs.length > 0) {
11727
11792
  for (const output of config.outputs) {
11728
11793
  const expected = applyTransform(config, output, { configs: contextConfigs });
11729
- const diff = buildDiff(expected, output.target_path);
11794
+ const diff = buildDiff(expected, output.target_path, detectFormat(output.target_path), showSecrets);
11730
11795
  if (!diff.includes("no diff"))
11731
11796
  diffs.push(diff);
11732
11797
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=apply-dry-run-verdict.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-dry-run-verdict.test.d.ts","sourceRoot":"","sources":["../../src/lib/apply-dry-run-verdict.test.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/lib/apply.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAgB,MAAM,mBAAmB,CAAC;AAE3E,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EAGL,yBAAyB,EAC1B,MAAM,qBAAqB,CAAC;AAI7B,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK5C;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAsBrD;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,yBAAyB,GAAG,2BAA2B,GAAG,yBAAyB,CAAC;IAClG,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,QAAQ,EAAE,yBAAyB,EAAE,CAAC;CACvC;AAsHD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,WAAW,CAAC,CA+BtB;AAoED,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,WAAW,EAAE,CAAC,CAMxB;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,kBAAkB,CAAC,CA4B7B;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAM,GACtC,OAAO,CAAC,kBAAkB,CAAC,CAE7B"}
1
+ {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/lib/apply.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAgB,MAAM,mBAAmB,CAAC;AAE3E,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EAGL,yBAAyB,EAC1B,MAAM,qBAAqB,CAAC;AAI7B,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK5C;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAsBrD;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,yBAAyB,GAAG,2BAA2B,GAAG,yBAAyB,CAAC;IAClG,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,QAAQ,EAAE,yBAAyB,EAAE,CAAC;CACvC;AAuHD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,WAAW,CAAC,CA+BtB;AA2ED,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,WAAW,EAAE,CAAC,CAMxB;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,kBAAkB,CAAC,CA4B7B;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAM,GACtC,OAAO,CAAC,kBAAkB,CAAC,CAE7B"}
@@ -69,6 +69,8 @@ export interface ApplyResultSummary {
69
69
  path: string;
70
70
  dry_run: boolean;
71
71
  changed: boolean;
72
+ /** This target's own verdict; `changed` is the config-wide aggregate. */
73
+ primary_changed: boolean;
72
74
  agent?: ApplyResult["agent"];
73
75
  transform?: ApplyResult["transform"];
74
76
  output_count: number;
@@ -1 +1 @@
1
- {"version":3,"file":"compact-output.d.ts","sourceRoot":"","sources":["../../src/lib/compact-output.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compact-output.d.ts","sourceRoot":"","sources":["../../src/lib/compact-output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Config } from "../types/index.js";
2
+ /**
3
+ * Every config row that already writes to `targetPath`.
4
+ *
5
+ * A target path is the config's identity on disk: two rows pointing at one file
6
+ * means an apply races itself, last writer wins, and nothing reports the
7
+ * conflict. Callers use this to refuse creating a second owner.
8
+ *
9
+ * Comparison is on the NORMALIZED path, not the stored string, because the same
10
+ * file is spelled several ways across the store — `~/.claude/CLAUDE.md` from
11
+ * `sync`, an absolute path from `add`, and either of those through a symlinked
12
+ * ancestor. Matching on the raw string is what let a twin row in through a
13
+ * different spelling of a path that was already owned.
14
+ *
15
+ * Reference configs (`kind: "reference"`) own no target path and never match.
16
+ */
17
+ export declare function findConfigsByTargetPath(configs: Config[], targetPath: string): Config[];
18
+ /**
19
+ * Groups of rows that collide on one normalized target path. Only groups with
20
+ * more than one member are returned, so an empty result means the store is
21
+ * clean. Used by the store audit and by anything that needs to report existing
22
+ * corruption rather than merely prevent new corruption.
23
+ */
24
+ export declare function findDuplicateTargetPathGroups(configs: Config[]): Array<{
25
+ target_path: string;
26
+ configs: Config[];
27
+ }>;
28
+ //# sourceMappingURL=config-target-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-target-identity.d.ts","sourceRoot":"","sources":["../../src/lib/config-target-identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGhD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAOvF;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAUlH"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config-target-identity.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-target-identity.test.d.ts","sourceRoot":"","sources":["../../src/lib/config-target-identity.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=diff-redaction.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-redaction.test.d.ts","sourceRoot":"","sources":["../../src/lib/diff-redaction.test.ts"],"names":[],"mappings":""}
@@ -26,4 +26,13 @@ export declare function redactContent(content: string, format: RedactFormat): Re
26
26
  export declare function scanSecrets(content: string, format: RedactFormat): RedactedVar[];
27
27
  /** Returns true if content contains any detectable secrets. */
28
28
  export declare function hasSecrets(content: string, format: RedactFormat): boolean;
29
+ /**
30
+ * Is this variable NAME secret-shaped? (`NPM_TOKEN` yes, `PATH`/`HOME` no.)
31
+ *
32
+ * Exported so callers reasoning about placeholder names — notably the diff
33
+ * renderer, which must tell a redaction artefact from an ordinary shell
34
+ * variable — share this module's single definition of "secret-shaped" instead
35
+ * of duplicating the pattern and drifting from it.
36
+ */
37
+ export declare function isSecretVarName(name: string): boolean;
29
38
  //# sourceMappingURL=redact.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/lib/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAgND,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5F,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,YAAY,CAQjF;AAED,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,CAGhF;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAEzE"}
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/lib/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAgND,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5F,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,YAAY,CAQjF;AAED,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,CAGhF;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAEzE;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sync-dry-run-unchanged.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-dry-run-unchanged.test.d.ts","sourceRoot":"","sources":["../../src/lib/sync-dry-run-unchanged.test.ts"],"names":[],"mappings":""}
@@ -43,6 +43,16 @@ export interface SyncToDiskOptions {
43
43
  export declare function syncToDisk(opts?: SyncToDiskOptions): Promise<SyncResult>;
44
44
  export interface DiffConfigOptions {
45
45
  store?: ConfigStore;
46
+ /**
47
+ * Render the raw disk content, INCLUDING any credential values it holds.
48
+ *
49
+ * Off by default and deliberately hard to reach: the CLI refuses it on a
50
+ * non-TTY, mirroring `secrets get --show`. Everything a tool prints is
51
+ * persisted verbatim into the session transcript, and agent output is also
52
+ * served as run evidence — so an unredacted diff writes a live credential
53
+ * into a durable, fetchable artefact.
54
+ */
55
+ showSecrets?: boolean;
46
56
  }
47
57
  export declare function diffConfig(config: Config, opts?: DiffConfigOptions): Promise<string>;
48
58
  export declare function detectCategory(filePath: string): ConfigCategory;
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/lib/sync.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrH,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAW/E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,qBAAqB,EAAE,YAAY,EAQ/C,CAAC;AAwDF,eAAO,MAAM,aAAa,EAAE,WAAW,EAwDtC,CAAC;AAIF,eAAO,MAAM,oBAAoB;;cAC2B,cAAc;WAAsB,WAAW;YAAwB,YAAY;GAc9I,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAgE/E;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,wBAAsB,SAAS,CAAC,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,CAqGhF;AAGD,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,wBAAsB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAmClF;AAGD,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAwBD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2B9F;AAGD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAU/D;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAgBzD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAQ3D;AAGD,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/lib/sync.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrH,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAW/E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,qBAAqB,EAAE,YAAY,EAQ/C,CAAC;AAwDF,eAAO,MAAM,aAAa,EAAE,WAAW,EAwDtC,CAAC;AAIF,eAAO,MAAM,oBAAoB;;cAC2B,cAAc;WAAsB,WAAW;YAAwB,YAAY;GAe9I,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAiE/E;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,wBAAsB,SAAS,CAAC,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,CAqGhF;AAGD,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,wBAAsB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAmClF;AAGD,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA8JD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CA+B9F;AAGD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAU/D;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAgBzD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAQ3D;AAGD,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
package/dist/mcp/index.js CHANGED
@@ -5170,6 +5170,7 @@ var exports_redact = {};
5170
5170
  __export(exports_redact, {
5171
5171
  scanSecrets: () => scanSecrets,
5172
5172
  redactContent: () => redactContent,
5173
+ isSecretVarName: () => isSecretVarName,
5173
5174
  hasSecrets: () => hasSecrets
5174
5175
  });
5175
5176
  function redactShell(content) {
@@ -5343,6 +5344,9 @@ function scanSecrets(content, format) {
5343
5344
  function hasSecrets(content, format) {
5344
5345
  return scanSecrets(content, format).length > 0;
5345
5346
  }
5347
+ function isSecretVarName(name) {
5348
+ return SECRET_KEY_PATTERN.test(name);
5349
+ }
5346
5350
  var SECRET_KEY_PATTERN, VALUE_PATTERNS, MIN_SECRET_VALUE_LEN = 8;
5347
5351
  var init_redact = __esm(() => {
5348
5352
  SECRET_KEY_PATTERN = /^(.*_?API_?KEY|.*_?TOKEN|.*_?SECRET|.*_?PASSWORD|.*_?PASSWD|.*_?CREDENTIAL|.*_?AUTH(?:_TOKEN|_KEY|ORIZATION)?|.*_?PRIVATE_?KEY|.*_?ACCESS_?KEY|.*_?CLIENT_?SECRET|.*_?SIGNING_?KEY|.*_?ENCRYPTION_?KEY|.*_AUTH_TOKEN)$/i;
@@ -5922,6 +5926,7 @@ async function writeConfigResult(config, targetPath, content, opts, meta = {}) {
5922
5926
  new_content: renderedContent,
5923
5927
  dry_run: opts.dryRun ?? false,
5924
5928
  changed,
5929
+ primary_changed: changed,
5925
5930
  unresolved_template_vars: [...new Set([
5926
5931
  ...renderedTarget.unresolved,
5927
5932
  ...rendered.unresolved
@@ -5988,7 +5993,7 @@ async function applyPreparedConfig(config, opts) {
5988
5993
  if (config.target_path && shouldApplyPrimary) {
5989
5994
  result = await writeConfigResult(config, config.target_path, config.content, opts);
5990
5995
  result.outputs = outputResults;
5991
- result.changed = result.changed || outputResults.some((output) => output.changed);
5996
+ result.changed = result.primary_changed || outputResults.some((output) => output.changed);
5992
5997
  result.unresolved_template_vars = [...new Set([
5993
5998
  ...result.unresolved_template_vars ?? [],
5994
5999
  ...outputResults.flatMap((output) => output.unresolved_template_vars ?? [])
@@ -6337,7 +6342,8 @@ async function syncProject(opts) {
6337
6342
  }
6338
6343
  for (const ruleDir of [
6339
6344
  { dir: join6(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
6340
- { dir: join6(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" }
6345
+ { dir: join6(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" },
6346
+ { dir: join6(absDir, ".cursor", "rules"), agent: "cursor", namePrefix: "cursor-rules" }
6341
6347
  ]) {
6342
6348
  if (!existsSync5(ruleDir.dir))
6343
6349
  continue;
@@ -6515,30 +6521,86 @@ async function syncToDisk(opts = {}) {
6515
6521
  }
6516
6522
  return result;
6517
6523
  }
6518
- function buildDiff(expectedContent, targetPath) {
6524
+ function redactionPlaceholders(storedLine) {
6525
+ const found = [...storedLine.match(CERTAIN_PLACEHOLDER_RE) ?? []];
6526
+ const assigned = storedLine.match(ASSIGNED_PLACEHOLDER_RE);
6527
+ if (assigned) {
6528
+ const name = assigned[3] ?? assigned[4] ?? assigned[5];
6529
+ if (name && isSecretVarName(name))
6530
+ found.push(assigned[2]);
6531
+ }
6532
+ return found;
6533
+ }
6534
+ function redactFormatForTarget(targetPath, storedFormat) {
6535
+ const p = targetPath.toLowerCase();
6536
+ if (/(^|\/)\.(zshrc|zprofile|bashrc|bash_profile|profile|zshenv|env)$/.test(p) || p.endsWith(".env"))
6537
+ return "shell";
6538
+ if (/(^|\/)\.(npmrc|yarnrc|curlrc|netrc)$/.test(p))
6539
+ return "ini";
6540
+ return storedFormat;
6541
+ }
6542
+ function storedPlaceholderIsLiteralOnDisk(storedLine, diskLine) {
6543
+ return redactionPlaceholders(storedLine).some((p) => !diskLine.includes(p));
6544
+ }
6545
+ function buildDiff(expectedContent, targetPath, storedFormat, showSecrets) {
6519
6546
  const path = expandPath(targetPath);
6520
6547
  if (!existsSync5(path))
6521
6548
  return `(file not found on disk: ${path})`;
6522
6549
  const diskContent = readFileSync3(path, "utf-8");
6523
6550
  if (diskContent === expectedContent)
6524
6551
  return "(no diff \u2014 identical)";
6552
+ const format = redactFormatForTarget(targetPath, storedFormat);
6525
6553
  const stored = expectedContent.split(`
6526
6554
  `);
6527
6555
  const disk = diskContent.split(`
6528
6556
  `);
6557
+ const { content: redactedDiskContent, redacted } = showSecrets ? { content: diskContent, redacted: [] } : redactContent(diskContent, format);
6558
+ const redactedDisk = redactedDiskContent.split(`
6559
+ `);
6560
+ const reasonByLine = new Map;
6561
+ for (const r of redacted)
6562
+ if (!reasonByLine.has(r.line))
6563
+ reasonByLine.set(r.line, r.reason);
6529
6564
  const lines = [`--- stored (DB)`, `+++ disk (${path})`];
6530
6565
  const maxLen = Math.max(stored.length, disk.length);
6531
6566
  for (let i = 0;i < maxLen; i++) {
6567
+ const lineNo = i + 1;
6532
6568
  const s = stored[i];
6533
6569
  const dk = disk[i];
6534
6570
  if (s === dk) {
6535
6571
  if (s !== undefined)
6536
6572
  lines.push(` ${s}`);
6537
- } else {
6573
+ continue;
6574
+ }
6575
+ if (showSecrets || dk === undefined) {
6538
6576
  if (s !== undefined)
6539
6577
  lines.push(`-${s}`);
6540
6578
  if (dk !== undefined)
6541
6579
  lines.push(`+${dk}`);
6580
+ continue;
6581
+ }
6582
+ const structural = s !== undefined && storedPlaceholderIsLiteralOnDisk(s, dk);
6583
+ const patterned = reasonByLine.has(lineNo);
6584
+ if (!structural && !patterned) {
6585
+ if (s !== undefined)
6586
+ lines.push(`-${s}`);
6587
+ lines.push(`+${dk}`);
6588
+ continue;
6589
+ }
6590
+ if (structural) {
6591
+ const placeholder = redactionPlaceholders(s).find((p) => !dk.includes(p)) ?? "a placeholder";
6592
+ lines.push(`~line ${lineNo} differs: stored \`${s}\`, disk holds a literal value for ${placeholder} \u2014 redacted (use --show-secrets on a TTY to reveal)`);
6593
+ continue;
6594
+ }
6595
+ const safe = redactedDisk[i] ?? "";
6596
+ const reason = reasonByLine.get(lineNo);
6597
+ if (s !== undefined && safe === s) {
6598
+ lines.push(`~line ${lineNo} differs: stored \`${s}\`, disk holds a literal value (${reason}) \u2014 redacted (use --show-secrets on a TTY to reveal)`);
6599
+ } else {
6600
+ if (s !== undefined)
6601
+ lines.push(`-${s}`);
6602
+ lines.push(`+${safe}`);
6603
+ lines.push(`~line ${lineNo}: disk value redacted (${reason}) \u2014 use --show-secrets on a TTY to reveal`);
6542
6604
  }
6543
6605
  }
6544
6606
  return lines.join(`
@@ -6553,15 +6615,16 @@ async function diffConfig(config, opts = {}) {
6553
6615
  if (isGeneratedOutputTarget2(config, outputOwnerIdsByTarget(contextConfigs))) {
6554
6616
  return "(generated output \u2014 managed by fan-out)";
6555
6617
  }
6618
+ const showSecrets = opts.showSecrets ?? false;
6556
6619
  if (config.target_path) {
6557
- const diff = buildDiff(config.content, config.target_path);
6620
+ const diff = buildDiff(config.content, config.target_path, config.format, showSecrets);
6558
6621
  if (!diff.includes("no diff"))
6559
6622
  diffs.push(diff);
6560
6623
  }
6561
6624
  if (config.outputs.length > 0) {
6562
6625
  for (const output of config.outputs) {
6563
6626
  const expected = applyTransform(config, output, { configs: contextConfigs });
6564
- const diff = buildDiff(expected, output.target_path);
6627
+ const diff = buildDiff(expected, output.target_path, detectFormat(output.target_path), showSecrets);
6565
6628
  if (!diff.includes("no diff"))
6566
6629
  diffs.push(diff);
6567
6630
  }
@@ -6632,7 +6695,7 @@ function detectFormat(filePath) {
6632
6695
  return "ini";
6633
6696
  return "text";
6634
6697
  }
6635
- var CLAUDE_PROMPT_OUTPUTS, KNOWN_CONFIGS, PROJECT_CONFIG_FILES;
6698
+ var CLAUDE_PROMPT_OUTPUTS, KNOWN_CONFIGS, PROJECT_CONFIG_FILES, CERTAIN_PLACEHOLDER_RE, ASSIGNED_PLACEHOLDER_RE;
6636
6699
  var init_sync = __esm(() => {
6637
6700
  init_config_store();
6638
6701
  init_apply();
@@ -6688,6 +6751,7 @@ var init_sync = __esm(() => {
6688
6751
  { file: "AGENTS.md", category: "rules", agent: "codex", format: "markdown" },
6689
6752
  { file: ".codex/AGENTS.md", category: "rules", agent: "codex", format: "markdown" },
6690
6753
  { file: ".opencode/AGENTS.md", category: "rules", agent: "opencode", format: "markdown" },
6754
+ { file: "CODEWITH.md", category: "rules", agent: "codewith", format: "markdown" },
6691
6755
  { file: ".codewith/CODEWITH.md", category: "rules", agent: "codewith", format: "markdown" },
6692
6756
  { file: ".aicopilot/AICOPILOT.md", category: "rules", agent: "aicopilot", format: "markdown" },
6693
6757
  { file: "AICOPILOT.md", category: "rules", agent: "aicopilot", format: "markdown" },
@@ -6696,6 +6760,8 @@ var init_sync = __esm(() => {
6696
6760
  { file: ".agents/mcp_config.json", category: "mcp", agent: "antigravity", format: "json" },
6697
6761
  { file: ".qwen/settings.json", category: "agent", agent: "qwen", format: "json" }
6698
6762
  ];
6763
+ CERTAIN_PLACEHOLDER_RE = /\{\{[A-Za-z_][A-Za-z0-9_]*\}\}/g;
6764
+ ASSIGNED_PLACEHOLDER_RE = /[=:]\s*(["']?)(\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Z][A-Z0-9_]*)|%([A-Za-z_][A-Za-z0-9_]*)%)\1\s*,?\s*$/;
6699
6765
  });
6700
6766
 
6701
6767
  // src/lib/sync-dir.ts
@@ -6792,7 +6858,7 @@ var init_sync_dir = __esm(() => {
6792
6858
  var require_package = __commonJS((exports, module) => {
6793
6859
  module.exports = {
6794
6860
  name: "@hasna/instructions",
6795
- version: "0.4.11",
6861
+ version: "0.4.13",
6796
6862
  description: "AI coding agent instruction & configuration manager \u2014 store, version, apply, and share all your AI coding configs. CLI + MCP + HTTP API (instructions-serve) + generated SDK + Dashboard.",
6797
6863
  type: "module",
6798
6864
  main: "dist/index.js",
@@ -6986,6 +7052,7 @@ function summarizeApplyResult(result) {
6986
7052
  path: result.path,
6987
7053
  dry_run: result.dry_run,
6988
7054
  changed: result.changed,
7055
+ primary_changed: result.primary_changed,
6989
7056
  agent: result.agent,
6990
7057
  transform: result.transform,
6991
7058
  output_count: result.outputs?.length ?? 0,
@@ -158,7 +158,21 @@ export interface ApplyResult {
158
158
  previous_content: string | null;
159
159
  new_content: string;
160
160
  dry_run: boolean;
161
+ /**
162
+ * AGGREGATE: true when this config has any work to do — this target OR any of
163
+ * its outputs. Profile/sync counters and the MCP surface consume it this way,
164
+ * so its meaning is deliberately unchanged.
165
+ */
161
166
  changed: boolean;
167
+ /**
168
+ * This target's OWN verdict: does the file at `path` differ from what would be
169
+ * written? Distinct from `changed`, which ORs in the outputs — a config whose
170
+ * primary file is byte-identical but whose outputs drifted has
171
+ * `primary_changed: false` and `changed: true`. Display surfaces label a line
172
+ * with `path`, so they must read this one; reading `changed` there reported
173
+ * "changed" for a file that was not going to change.
174
+ */
175
+ primary_changed: boolean;
162
176
  agent?: ConfigAgent;
163
177
  transform?: ConfigTransform;
164
178
  outputs?: ApplyResult[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/instructions",
3
- "version": "0.4.11",
3
+ "version": "0.4.13",
4
4
  "description": "AI coding agent instruction & configuration manager \u2014 store, version, apply, and share all your AI coding configs. CLI + MCP + HTTP API (instructions-serve) + generated SDK + Dashboard.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",