@hasna/instructions 0.4.18 → 0.4.20

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/README.md CHANGED
@@ -331,14 +331,22 @@ workflows:
331
331
  - `{{PROJECT_DASHBOARD_DIR}}` -> `.hasna/project`
332
332
  - `{{PROJECT_DASHBOARD_RENDER_MANIFEST}}` -> `.hasna/project/dashboard/render.json`
333
333
  - `{{PROJECT_DASHBOARD_SNAPSHOTS_DIR}}` -> `.hasna/project/dashboard/snapshots`
334
- - `{{PROJECT_CHANNEL_PREFIX}}` -> `iproj-`
334
+ - `{{PROJECT_CHANNEL_PREFIX}}` -> `""` (no prefix; the channel is the normalized project slug)
335
+
336
+ Existing profiles can be migrated in place without deleting or recreating them:
337
+
338
+ ```bash
339
+ instructions profile update linux-arm64 \
340
+ --var PROJECT_CHANNEL_PREFIX= \
341
+ --unset-var LEGACY_VARIABLE
342
+ ```
335
343
 
336
344
  `instructions init` and `bun run seed` seed the
337
345
  `agent-managed-project-dashboard-standard` reference. It documents the standard
338
346
  `.hasna/project` layout, `projects dashboard *` commands, provider panel
339
- commands, `#iproj-*` channel naming, durable todos/goal workflow, and the rule
340
- that dashboards must show ids/statuses/evidence refs instead of raw private
341
- documents or secrets.
347
+ commands, normalized project-slug channel naming, durable todos/goal workflow,
348
+ and the rule that dashboards must show ids/statuses/evidence refs instead of raw
349
+ private documents or secrets.
342
350
 
343
351
  ## License
344
352
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=add-reference-update.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-reference-update.test.d.ts","sourceRoot":"","sources":["../../src/cli/add-reference-update.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=doctor-reference-duplicates.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-reference-duplicates.test.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-reference-duplicates.test.ts"],"names":[],"mappings":""}
package/dist/cli/index.js CHANGED
@@ -10371,6 +10371,21 @@ function canonicalFingerprintValue(value) {
10371
10371
  }
10372
10372
  return value;
10373
10373
  }
10374
+ function ruleAttestation(rule) {
10375
+ const metadata = rule.metadata ?? {};
10376
+ const read = (key) => {
10377
+ const value = metadata[key];
10378
+ return typeof value === "string" ? value : null;
10379
+ };
10380
+ const applied = metadata["payloadFloorApplied"];
10381
+ return {
10382
+ contentSha256: sha2563(rule.content ?? ""),
10383
+ payloadFloorApplied: typeof applied === "boolean" ? applied : null,
10384
+ flooredFromRulesVersion: read("flooredFromRulesVersion"),
10385
+ flooredFromPayloadSha256: read("flooredFromPayloadSha256"),
10386
+ payloadIntegrity: read("payloadIntegrity")
10387
+ };
10388
+ }
10374
10389
  function sourceFingerprint(source) {
10375
10390
  return {
10376
10391
  id: source.id,
@@ -10469,6 +10484,27 @@ function applyAgentOperatingRulesFloor(source, content) {
10469
10484
  metadata: { ...source.metadata ?? {}, ...payload.metadata, ...floored }
10470
10485
  };
10471
10486
  }
10487
+ function applyAgentOperatingRulesFloorToRule(source, rule, content) {
10488
+ const unchanged = { content, metadata: rule.metadata ?? null };
10489
+ if (!claimsAgentOperatingRulesPolicy(source, content))
10490
+ return unchanged;
10491
+ const payload = resolveAgentOperatingRulesPayload(content);
10492
+ if (payload.content === content) {
10493
+ return {
10494
+ content,
10495
+ metadata: { ...rule.metadata ?? {}, payloadIntegrity: payload.integrity }
10496
+ };
10497
+ }
10498
+ const floored = {
10499
+ payloadFloorApplied: true,
10500
+ flooredFromRulesVersion: parseAgentOperatingRulesVersion(content),
10501
+ flooredFromPayloadSha256: sha2563(content)
10502
+ };
10503
+ return {
10504
+ content: payload.content,
10505
+ metadata: { ...rule.metadata ?? {}, ...payload.metadata, ...floored }
10506
+ };
10507
+ }
10472
10508
  function skippedSource(source, reason) {
10473
10509
  return {
10474
10510
  id: source.id,
@@ -10507,24 +10543,67 @@ function normalizeSources(sources, tool, allowEmptySources) {
10507
10543
  rejectDuplicateRulePaths(ordered);
10508
10544
  return { sources: ordered, skipped: deduplicated.skipped };
10509
10545
  }
10546
+ function semanticPolicyIntegrity(body) {
10547
+ return sha2563(body) === AGENT_OPERATING_RULES_PAYLOAD_SHA256 ? "pinned-digest" : "unverified-self-declared";
10548
+ }
10549
+ function semanticPolicyDeclaration(source) {
10550
+ const normalize = (value) => value.replace(/\r\n/g, `
10551
+ `).trim();
10552
+ const sentinel = source.content.match(AGENT_OPERATING_RULES_SENTINEL_PATTERN);
10553
+ if (sentinel) {
10554
+ return {
10555
+ version: sentinel[1],
10556
+ normalizedContent: normalize(source.content),
10557
+ integrity: semanticPolicyIntegrity(source.content)
10558
+ };
10559
+ }
10560
+ for (const rule of source.resolvedRules) {
10561
+ const body = rule.content ?? "";
10562
+ if (!claimsAgentOperatingRulesPolicy(source, body))
10563
+ continue;
10564
+ const ruleSentinel = body.match(AGENT_OPERATING_RULES_SENTINEL_PATTERN);
10565
+ if (!ruleSentinel)
10566
+ continue;
10567
+ return {
10568
+ version: ruleSentinel[1],
10569
+ normalizedContent: normalize(body),
10570
+ integrity: semanticPolicyIntegrity(body)
10571
+ };
10572
+ }
10573
+ return null;
10574
+ }
10575
+ function withoutSemanticPolicyPayloads(source) {
10576
+ const content = AGENT_OPERATING_RULES_SENTINEL_PATTERN.test(source.content) ? "" : source.content;
10577
+ const resolvedRules = source.resolvedRules.filter((rule) => {
10578
+ const body = rule.content ?? "";
10579
+ return !(AGENT_OPERATING_RULES_SENTINEL_PATTERN.test(body) && claimsAgentOperatingRulesPolicy(source, body));
10580
+ });
10581
+ const hasPathReferences = (source.sourcePaths ?? []).length > 0;
10582
+ if (!content.trim() && resolvedRules.length === 0 && !hasPathReferences)
10583
+ return null;
10584
+ return { ...source, content, resolvedRules };
10585
+ }
10510
10586
  function deduplicateSemanticPolicySources(sources) {
10511
10587
  const selected = [];
10512
10588
  const skipped = [];
10513
10589
  const policySources = new Map;
10514
- const collapseReason = (winner, key) => `superseded by "${winner.id}": sources declaring the semantic policy ${key} collapse to one so a single instruction home cannot carry two rule-set versions`;
10590
+ const collapseReason = (winner, key, partial, displacesVerified) => `superseded by "${winner.id}": sources declaring the semantic policy ${key} collapse to one so a single instruction home cannot carry two rule-set versions` + (partial ? "; only the policy payload was removed and this source's other instructions still render" : "") + (displacesVerified ? "; WARNING the surviving payload is unverified-self-declared and displaced a digest-verified one on its own version claim" : "");
10591
+ const discard = (loser, winner, key, displacesVerified) => {
10592
+ const remainder = withoutSemanticPolicyPayloads(loser);
10593
+ skipped.push(skippedSource(loser, collapseReason(winner, key, remainder !== null, displacesVerified)));
10594
+ return remainder;
10595
+ };
10515
10596
  for (const source of sources) {
10516
- const sentinel = source.content.match(AGENT_OPERATING_RULES_SENTINEL_PATTERN);
10517
- if (!sentinel) {
10597
+ const declaration = semanticPolicyDeclaration(source);
10598
+ if (!declaration) {
10518
10599
  selected.push(source);
10519
10600
  continue;
10520
10601
  }
10521
- const version = sentinel[1];
10602
+ const { version, normalizedContent, integrity } = declaration;
10522
10603
  const key = AGENT_OPERATING_RULES_SEMANTIC_POLICY_KEY;
10523
- const normalizedContent = source.content.replace(/\r\n/g, `
10524
- `).trim();
10525
10604
  const existing = policySources.get(key);
10526
10605
  if (!existing) {
10527
- policySources.set(key, { index: selected.length, version, normalizedContent });
10606
+ policySources.set(key, { index: selected.length, version, normalizedContent, integrity });
10528
10607
  selected.push(source);
10529
10608
  continue;
10530
10609
  }
@@ -10534,16 +10613,22 @@ function deduplicateSemanticPolicySources(sources) {
10534
10613
  }
10535
10614
  const current = selected[existing.index];
10536
10615
  const priorityOrder = semanticPolicySourcePriority(source) - semanticPolicySourcePriority(current);
10537
- if (priorityOrder < 0 || priorityOrder === 0 && versionOrder <= 0) {
10538
- skipped.push(skippedSource(source, collapseReason(current, key)));
10616
+ const displacesVerified = existing.integrity === "pinned-digest" && integrity === "unverified-self-declared";
10617
+ const arrivingWins = priorityOrder > 0 || priorityOrder === 0 && versionOrder > 0;
10618
+ if (!arrivingWins) {
10619
+ const remainder2 = discard(source, current, key, false);
10620
+ if (remainder2)
10621
+ selected.push(remainder2);
10539
10622
  continue;
10540
10623
  }
10541
- skipped.push(skippedSource(current, collapseReason(source, key)));
10624
+ const remainder = discard(current, source, key, displacesVerified);
10542
10625
  selected[existing.index] = {
10543
10626
  ...source,
10544
10627
  resolvedOrder: current.resolvedOrder
10545
10628
  };
10546
- policySources.set(key, { index: existing.index, version, normalizedContent });
10629
+ if (remainder)
10630
+ selected.push(remainder);
10631
+ policySources.set(key, { index: existing.index, version, normalizedContent, integrity });
10547
10632
  }
10548
10633
  return { selected, skipped };
10549
10634
  }
@@ -10551,7 +10636,7 @@ function semanticPolicySourcePriority(source) {
10551
10636
  let priority = 0;
10552
10637
  if (source.nonOverridable)
10553
10638
  priority += 4;
10554
- if (source.id === GLOBAL_AGENT_RULES_STANDARD_SLUG)
10639
+ if (source.id === GLOBAL_AGENT_RULES_STANDARD_SLUG || source.id === AGENT_OPERATING_RULES_SOURCE_ID)
10555
10640
  priority += 2;
10556
10641
  if (source.metadata?.["role"] === AGENT_OPERATING_RULES_ROLE)
10557
10642
  priority += 1;
@@ -11051,7 +11136,8 @@ function planSessionRender(input) {
11051
11136
  label: rule.resolvedLabel,
11052
11137
  path: rule.resolvedPath,
11053
11138
  globs: rule.globs ?? [],
11054
- hash: rule.hash ?? null
11139
+ hash: rule.hash ?? null,
11140
+ ...ruleAttestation(rule)
11055
11141
  })),
11056
11142
  renderedPayloadSha256: sha2563(source.content),
11057
11143
  provenance: source.provenance ?? null,
@@ -11172,7 +11258,8 @@ function normalizeInstructionRules(source, tool) {
11172
11258
  return (source.rules ?? []).map((rule) => {
11173
11259
  if (!rule.id.trim())
11174
11260
  throw new Error(`Instruction rule id is required for source ${source.id}.`);
11175
- const content = filterProviderOnlyBlocks(rule.content ?? "", tool);
11261
+ const floored = applyAgentOperatingRulesFloorToRule(source, rule, rule.content ?? "");
11262
+ const content = filterProviderOnlyBlocks(floored.content, tool);
11176
11263
  if (!content.trim() && !rule.path)
11177
11264
  throw new Error(`Instruction rule content or path is required for rule ${rule.id}.`);
11178
11265
  const resolvedPath = normalizeRulePath(rule.path ?? `${slug(rule.id)}.md`);
@@ -11183,6 +11270,7 @@ function normalizeInstructionRules(source, tool) {
11183
11270
  return {
11184
11271
  ...rule,
11185
11272
  content,
11273
+ metadata: floored.metadata,
11186
11274
  normalizedId: slug(rule.id),
11187
11275
  resolvedLabel: rule.label ?? rule.id,
11188
11276
  resolvedPath
@@ -13794,6 +13882,7 @@ import { basename as basename7, join as join15, resolve as resolve8 } from "path
13794
13882
 
13795
13883
  // src/lib/config-target-identity.ts
13796
13884
  init_apply();
13885
+ init_database();
13797
13886
  function findConfigsByTargetPath(configs, targetPath) {
13798
13887
  const wanted = normalizeTargetPath(targetPath);
13799
13888
  return configs.filter((config) => {
@@ -13804,6 +13893,20 @@ function findConfigsByTargetPath(configs, targetPath) {
13804
13893
  return normalizeTargetPath(config.target_path) === wanted;
13805
13894
  });
13806
13895
  }
13896
+ function findReferenceConfigsByName(configs, name) {
13897
+ const wantedSlug = slugify(name);
13898
+ return configs.filter((config) => config.kind === "reference" && (config.name === name || slugify(config.name) === wantedSlug));
13899
+ }
13900
+ function findDuplicateReferenceNameGroups(configs) {
13901
+ const groups = new Map;
13902
+ for (const config of configs) {
13903
+ if (config.kind !== "reference")
13904
+ continue;
13905
+ const key = slugify(config.name);
13906
+ groups.set(key, [...groups.get(key) ?? [], config]);
13907
+ }
13908
+ return [...groups.entries()].filter(([, rows]) => rows.length > 1).map(([, rows]) => ({ name: rows[0].name, configs: rows }));
13909
+ }
13807
13910
  function findDuplicateTargetPathGroups(configs) {
13808
13911
  const groups = new Map;
13809
13912
  for (const config of configs) {
@@ -14833,7 +14936,7 @@ var PROJECT_DASHBOARD_PROFILE_VARIABLES = {
14833
14936
  PROJECT_DASHBOARD_DIR: ".hasna/project",
14834
14937
  PROJECT_DASHBOARD_RENDER_MANIFEST: ".hasna/project/dashboard/render.json",
14835
14938
  PROJECT_DASHBOARD_SNAPSHOTS_DIR: ".hasna/project/dashboard/snapshots",
14836
- PROJECT_CHANNEL_PREFIX: "iproj-"
14939
+ PROJECT_CHANNEL_PREFIX: ""
14837
14940
  };
14838
14941
  var PROJECT_DASHBOARD_STANDARD_CONTENT = `# Agent-Managed Project Dashboard Standard
14839
14942
 
@@ -14888,8 +14991,8 @@ context.
14888
14991
 
14889
14992
  ## Coordination
14890
14993
 
14891
- - Project conversation channels use \`iproj-<project-slug>\` in the CLI and are
14892
- displayed to humans as \`#iproj-<project-slug>\`.
14994
+ - Project conversation channels use the normalized project slug in the CLI and
14995
+ are displayed to humans as \`#<project-slug>\`.
14893
14996
  - Todos tasks are the source of truth for work; messages are only coordination.
14894
14997
  - Durable Codewith goal plans should own long-running implementation.
14895
14998
  - New implementation/verification work should route through task-triggered fresh
@@ -14994,10 +15097,15 @@ function mergeProfileSelectors(preset, existing) {
14994
15097
  };
14995
15098
  }
14996
15099
  function mergeProfileVariables(preset, existing) {
14997
- return {
15100
+ const variables = {
14998
15101
  ...preset ?? {},
14999
15102
  ...existing
15000
15103
  };
15104
+ for (const [key, value] of Object.entries(preset ?? {})) {
15105
+ if (value === "")
15106
+ variables[key] = value;
15107
+ }
15108
+ return variables;
15001
15109
  }
15002
15110
  function mergeUnique(preset, existing) {
15003
15111
  const values = [...new Set([...preset ?? [], ...existing ?? []])];
@@ -15577,6 +15685,15 @@ function parseVarArgs(values) {
15577
15685
  }
15578
15686
  return Object.keys(vars).length > 0 ? vars : undefined;
15579
15687
  }
15688
+ function parseUnsetVarArgs(values) {
15689
+ if (!values || values.length === 0)
15690
+ return [];
15691
+ const keys = [...new Set(values.map((value) => value.trim()))];
15692
+ if (keys.some((key) => key.length === 0 || key.includes("="))) {
15693
+ throw new Error('Invalid --unset-var (expected variable names without "=")');
15694
+ }
15695
+ return keys;
15696
+ }
15580
15697
  function parseProfileSelectors(opts) {
15581
15698
  const selectors = {};
15582
15699
  const os = splitCsv(opts.os);
@@ -15691,20 +15808,33 @@ program.command("add <path>").description("Ingest a file into the config DB").op
15691
15808
  const targetPath = abs.startsWith(homedir7()) ? abs.replace(homedir7(), "~") : abs;
15692
15809
  const name = opts.name || filePath.split("/").pop();
15693
15810
  const store = resolveConfigStore();
15694
- const existingOwners = opts.kind === "reference" ? [] : findConfigsByTargetPath(await store.listConfigs(), targetPath);
15811
+ const allConfigs = await store.listConfigs();
15812
+ const existingOwners = opts.kind === "reference" ? findReferenceConfigsByName(allConfigs, name) : findConfigsByTargetPath(allConfigs, targetPath);
15813
+ const isReference = opts.kind === "reference";
15814
+ const identityLabel = isReference ? `Reference config "${name}"` : targetPath;
15815
+ const identityNoun = isReference ? "name" : "path";
15695
15816
  if (existingOwners.length > 0 && !opts.update) {
15696
15817
  const owners = existingOwners.map((owner) => `${owner.slug} (${owner.id})`).join(", ");
15697
- console.error(chalk.red(`${targetPath} is already tracked by: ${owners}`));
15818
+ console.error(chalk.red(`${identityLabel} is already tracked by: ${owners}`));
15698
15819
  if (existingOwners.length > 1) {
15699
- console.error(chalk.red(` ${existingOwners.length} rows already collide on this path \u2014 apply order between them is undefined.`));
15820
+ console.error(chalk.red(` ${existingOwners.length} rows already collide on this ${identityNoun} \u2014 apply order between them is undefined.`));
15700
15821
  }
15701
15822
  console.error(chalk.dim(" Use `instructions add <path> --update` to refresh that row in place,"));
15702
- console.error(chalk.dim(" `instructions sync` to pull disk changes in, or `instructions delete <id>` first."));
15823
+ if (isReference) {
15824
+ console.error(chalk.dim(" or `instructions delete <id>` first."));
15825
+ } else {
15826
+ console.error(chalk.dim(" `instructions sync` to pull disk changes in, or `instructions delete <id>` first."));
15827
+ }
15703
15828
  process.exit(1);
15704
15829
  }
15705
15830
  let config;
15706
15831
  if (existingOwners.length > 0) {
15707
- const [target, ...rest] = existingOwners;
15832
+ const exactIndex = isReference ? existingOwners.findIndex((owner) => owner.name === name) : -1;
15833
+ const target = exactIndex >= 0 ? existingOwners[exactIndex] : existingOwners[0];
15834
+ const rest = existingOwners.filter((owner) => owner.id !== target.id);
15835
+ if (content !== target.content) {
15836
+ await store.createSnapshot(target.id, target.content, target.version);
15837
+ }
15708
15838
  config = await store.updateConfig(target.id, {
15709
15839
  content,
15710
15840
  format: fmt,
@@ -15714,7 +15844,7 @@ program.command("add <path>").description("Ingest a file into the config DB").op
15714
15844
  });
15715
15845
  console.log(chalk.green("\u2713") + ` Updated: ${chalk.bold(config.name)} ${chalk.dim(`(${config.slug})`)}`);
15716
15846
  if (rest.length > 0) {
15717
- console.log(chalk.yellow(` \u26A0 ${rest.length} other row(s) still target ${targetPath}: ${rest.map((r) => r.slug).join(", ")}`));
15847
+ console.log(chalk.yellow(` \u26A0 ${rest.length} other row(s) still share this ${identityNoun}: ${rest.map((r) => r.slug).join(", ")}`));
15718
15848
  console.log(chalk.yellow(" Apply order between them is undefined. Delete the extras."));
15719
15849
  }
15720
15850
  if (redacted.length > 0) {
@@ -15979,6 +16109,31 @@ profileCmd.command("create <name>").description("Create a new profile").option("
15979
16109
  });
15980
16110
  console.log(chalk.green("\u2713") + ` Created profile: ${chalk.bold(p.name)} ${chalk.dim(`(${p.slug})`)}`);
15981
16111
  });
16112
+ profileCmd.command("update <id>").description("Update an existing profile's variables in one store operation").option("--var <vars...>", "set profile variable(s) as KEY=VALUE").option("--unset-var <keys...>", "remove profile variable(s) by key").action(async (id, opts) => {
16113
+ try {
16114
+ const setVariables = parseVarArgs(opts.var) ?? {};
16115
+ const unsetVariables = parseUnsetVarArgs(opts.unsetVar);
16116
+ const setKeys = new Set(Object.keys(setVariables));
16117
+ const conflicts = unsetVariables.filter((key) => setKeys.has(key));
16118
+ if (conflicts.length > 0) {
16119
+ throw new Error(`Variables cannot be both set and unset: ${conflicts.join(", ")}`);
16120
+ }
16121
+ if (Object.keys(setVariables).length === 0 && unsetVariables.length === 0) {
16122
+ throw new Error("Provide --var KEY=VALUE and/or --unset-var KEY");
16123
+ }
16124
+ const store = resolveConfigStore();
16125
+ const profile = await store.getProfile(id);
16126
+ const variables = { ...profile.variables };
16127
+ for (const key of unsetVariables)
16128
+ delete variables[key];
16129
+ Object.assign(variables, setVariables);
16130
+ const updated = await store.updateProfile(profile.id, { variables });
16131
+ console.log(chalk.green("\u2713") + ` Updated profile: ${chalk.bold(updated.name)} ${chalk.dim(`(${updated.slug})`)}`);
16132
+ } catch (e) {
16133
+ console.error(chalk.red(formatCliError(e)));
16134
+ process.exit(1);
16135
+ }
16136
+ });
15982
16137
  profileCmd.command("show <id>").description("Show profile and its configs").option("--limit <n>", `max config rows (default ${DEFAULT_LIST_LIMIT})`).option("--cursor <n>", "zero-based pagination cursor").action(async (id, opts) => {
15983
16138
  try {
15984
16139
  const store = resolveConfigStore();
@@ -16755,6 +16910,20 @@ Stored configs (${allConfigs.length}):`));
16755
16910
  }
16756
16911
  console.log(chalk.dim(" Keep one row per path: `instructions delete <id>` for the extras."));
16757
16912
  }
16913
+ const duplicateReferenceNames = findDuplicateReferenceNameGroups(allConfigs);
16914
+ if (duplicateReferenceNames.length === 0) {
16915
+ pass("No reference config name is claimed by more than one row");
16916
+ } else {
16917
+ const rowCount = duplicateReferenceNames.reduce((total, group) => total + group.configs.length, 0);
16918
+ fail(`${duplicateReferenceNames.length} reference name(s) claimed by more than one row (${rowCount} rows) \u2014 only one is live in the next render`);
16919
+ for (const group of duplicateReferenceNames) {
16920
+ console.log(chalk.yellow(` ${group.name}`));
16921
+ for (const c of group.configs) {
16922
+ console.log(chalk.dim(` ${c.slug} (${c.id}) updated ${c.updated_at}`));
16923
+ }
16924
+ }
16925
+ console.log(chalk.dim(" Keep one row per name: `instructions delete <id>` for the extras."));
16926
+ }
16758
16927
  console.log(`
16759
16928
  ${issues === 0 ? chalk.green("\u2713 All checks passed") : chalk.yellow(`${issues} issue(s) found`)}`);
16760
16929
  });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=profile-update.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-update.test.d.ts","sourceRoot":"","sources":["../../src/cli/profile-update.test.ts"],"names":[],"mappings":""}
package/dist/index.js CHANGED
@@ -8442,6 +8442,21 @@ function canonicalFingerprintValue(value) {
8442
8442
  }
8443
8443
  return value;
8444
8444
  }
8445
+ function ruleAttestation(rule) {
8446
+ const metadata = rule.metadata ?? {};
8447
+ const read = (key) => {
8448
+ const value = metadata[key];
8449
+ return typeof value === "string" ? value : null;
8450
+ };
8451
+ const applied = metadata["payloadFloorApplied"];
8452
+ return {
8453
+ contentSha256: sha2563(rule.content ?? ""),
8454
+ payloadFloorApplied: typeof applied === "boolean" ? applied : null,
8455
+ flooredFromRulesVersion: read("flooredFromRulesVersion"),
8456
+ flooredFromPayloadSha256: read("flooredFromPayloadSha256"),
8457
+ payloadIntegrity: read("payloadIntegrity")
8458
+ };
8459
+ }
8445
8460
  function sourceFingerprint(source) {
8446
8461
  return {
8447
8462
  id: source.id,
@@ -8540,6 +8555,27 @@ function applyAgentOperatingRulesFloor(source, content) {
8540
8555
  metadata: { ...source.metadata ?? {}, ...payload.metadata, ...floored }
8541
8556
  };
8542
8557
  }
8558
+ function applyAgentOperatingRulesFloorToRule(source, rule, content) {
8559
+ const unchanged = { content, metadata: rule.metadata ?? null };
8560
+ if (!claimsAgentOperatingRulesPolicy(source, content))
8561
+ return unchanged;
8562
+ const payload = resolveAgentOperatingRulesPayload(content);
8563
+ if (payload.content === content) {
8564
+ return {
8565
+ content,
8566
+ metadata: { ...rule.metadata ?? {}, payloadIntegrity: payload.integrity }
8567
+ };
8568
+ }
8569
+ const floored = {
8570
+ payloadFloorApplied: true,
8571
+ flooredFromRulesVersion: parseAgentOperatingRulesVersion(content),
8572
+ flooredFromPayloadSha256: sha2563(content)
8573
+ };
8574
+ return {
8575
+ content: payload.content,
8576
+ metadata: { ...rule.metadata ?? {}, ...payload.metadata, ...floored }
8577
+ };
8578
+ }
8543
8579
  function skippedSource(source, reason) {
8544
8580
  return {
8545
8581
  id: source.id,
@@ -8578,24 +8614,67 @@ function normalizeSources(sources, tool, allowEmptySources) {
8578
8614
  rejectDuplicateRulePaths(ordered);
8579
8615
  return { sources: ordered, skipped: deduplicated.skipped };
8580
8616
  }
8617
+ function semanticPolicyIntegrity(body) {
8618
+ return sha2563(body) === AGENT_OPERATING_RULES_PAYLOAD_SHA256 ? "pinned-digest" : "unverified-self-declared";
8619
+ }
8620
+ function semanticPolicyDeclaration(source) {
8621
+ const normalize = (value) => value.replace(/\r\n/g, `
8622
+ `).trim();
8623
+ const sentinel = source.content.match(AGENT_OPERATING_RULES_SENTINEL_PATTERN);
8624
+ if (sentinel) {
8625
+ return {
8626
+ version: sentinel[1],
8627
+ normalizedContent: normalize(source.content),
8628
+ integrity: semanticPolicyIntegrity(source.content)
8629
+ };
8630
+ }
8631
+ for (const rule of source.resolvedRules) {
8632
+ const body = rule.content ?? "";
8633
+ if (!claimsAgentOperatingRulesPolicy(source, body))
8634
+ continue;
8635
+ const ruleSentinel = body.match(AGENT_OPERATING_RULES_SENTINEL_PATTERN);
8636
+ if (!ruleSentinel)
8637
+ continue;
8638
+ return {
8639
+ version: ruleSentinel[1],
8640
+ normalizedContent: normalize(body),
8641
+ integrity: semanticPolicyIntegrity(body)
8642
+ };
8643
+ }
8644
+ return null;
8645
+ }
8646
+ function withoutSemanticPolicyPayloads(source) {
8647
+ const content = AGENT_OPERATING_RULES_SENTINEL_PATTERN.test(source.content) ? "" : source.content;
8648
+ const resolvedRules = source.resolvedRules.filter((rule) => {
8649
+ const body = rule.content ?? "";
8650
+ return !(AGENT_OPERATING_RULES_SENTINEL_PATTERN.test(body) && claimsAgentOperatingRulesPolicy(source, body));
8651
+ });
8652
+ const hasPathReferences = (source.sourcePaths ?? []).length > 0;
8653
+ if (!content.trim() && resolvedRules.length === 0 && !hasPathReferences)
8654
+ return null;
8655
+ return { ...source, content, resolvedRules };
8656
+ }
8581
8657
  function deduplicateSemanticPolicySources(sources) {
8582
8658
  const selected = [];
8583
8659
  const skipped = [];
8584
8660
  const policySources = new Map;
8585
- const collapseReason = (winner, key) => `superseded by "${winner.id}": sources declaring the semantic policy ${key} collapse to one so a single instruction home cannot carry two rule-set versions`;
8661
+ const collapseReason = (winner, key, partial, displacesVerified) => `superseded by "${winner.id}": sources declaring the semantic policy ${key} collapse to one so a single instruction home cannot carry two rule-set versions` + (partial ? "; only the policy payload was removed and this source's other instructions still render" : "") + (displacesVerified ? "; WARNING the surviving payload is unverified-self-declared and displaced a digest-verified one on its own version claim" : "");
8662
+ const discard = (loser, winner, key, displacesVerified) => {
8663
+ const remainder = withoutSemanticPolicyPayloads(loser);
8664
+ skipped.push(skippedSource(loser, collapseReason(winner, key, remainder !== null, displacesVerified)));
8665
+ return remainder;
8666
+ };
8586
8667
  for (const source of sources) {
8587
- const sentinel = source.content.match(AGENT_OPERATING_RULES_SENTINEL_PATTERN);
8588
- if (!sentinel) {
8668
+ const declaration = semanticPolicyDeclaration(source);
8669
+ if (!declaration) {
8589
8670
  selected.push(source);
8590
8671
  continue;
8591
8672
  }
8592
- const version = sentinel[1];
8673
+ const { version, normalizedContent, integrity } = declaration;
8593
8674
  const key = AGENT_OPERATING_RULES_SEMANTIC_POLICY_KEY;
8594
- const normalizedContent = source.content.replace(/\r\n/g, `
8595
- `).trim();
8596
8675
  const existing = policySources.get(key);
8597
8676
  if (!existing) {
8598
- policySources.set(key, { index: selected.length, version, normalizedContent });
8677
+ policySources.set(key, { index: selected.length, version, normalizedContent, integrity });
8599
8678
  selected.push(source);
8600
8679
  continue;
8601
8680
  }
@@ -8605,16 +8684,22 @@ function deduplicateSemanticPolicySources(sources) {
8605
8684
  }
8606
8685
  const current = selected[existing.index];
8607
8686
  const priorityOrder = semanticPolicySourcePriority(source) - semanticPolicySourcePriority(current);
8608
- if (priorityOrder < 0 || priorityOrder === 0 && versionOrder <= 0) {
8609
- skipped.push(skippedSource(source, collapseReason(current, key)));
8687
+ const displacesVerified = existing.integrity === "pinned-digest" && integrity === "unverified-self-declared";
8688
+ const arrivingWins = priorityOrder > 0 || priorityOrder === 0 && versionOrder > 0;
8689
+ if (!arrivingWins) {
8690
+ const remainder2 = discard(source, current, key, false);
8691
+ if (remainder2)
8692
+ selected.push(remainder2);
8610
8693
  continue;
8611
8694
  }
8612
- skipped.push(skippedSource(current, collapseReason(source, key)));
8695
+ const remainder = discard(current, source, key, displacesVerified);
8613
8696
  selected[existing.index] = {
8614
8697
  ...source,
8615
8698
  resolvedOrder: current.resolvedOrder
8616
8699
  };
8617
- policySources.set(key, { index: existing.index, version, normalizedContent });
8700
+ if (remainder)
8701
+ selected.push(remainder);
8702
+ policySources.set(key, { index: existing.index, version, normalizedContent, integrity });
8618
8703
  }
8619
8704
  return { selected, skipped };
8620
8705
  }
@@ -8622,7 +8707,7 @@ function semanticPolicySourcePriority(source) {
8622
8707
  let priority = 0;
8623
8708
  if (source.nonOverridable)
8624
8709
  priority += 4;
8625
- if (source.id === GLOBAL_AGENT_RULES_STANDARD_SLUG)
8710
+ if (source.id === GLOBAL_AGENT_RULES_STANDARD_SLUG || source.id === AGENT_OPERATING_RULES_SOURCE_ID)
8626
8711
  priority += 2;
8627
8712
  if (source.metadata?.["role"] === AGENT_OPERATING_RULES_ROLE)
8628
8713
  priority += 1;
@@ -9122,7 +9207,8 @@ function planSessionRender(input) {
9122
9207
  label: rule.resolvedLabel,
9123
9208
  path: rule.resolvedPath,
9124
9209
  globs: rule.globs ?? [],
9125
- hash: rule.hash ?? null
9210
+ hash: rule.hash ?? null,
9211
+ ...ruleAttestation(rule)
9126
9212
  })),
9127
9213
  renderedPayloadSha256: sha2563(source.content),
9128
9214
  provenance: source.provenance ?? null,
@@ -9344,7 +9430,8 @@ function normalizeInstructionRules(source, tool) {
9344
9430
  return (source.rules ?? []).map((rule) => {
9345
9431
  if (!rule.id.trim())
9346
9432
  throw new Error(`Instruction rule id is required for source ${source.id}.`);
9347
- const content = filterProviderOnlyBlocks(rule.content ?? "", tool);
9433
+ const floored = applyAgentOperatingRulesFloorToRule(source, rule, rule.content ?? "");
9434
+ const content = filterProviderOnlyBlocks(floored.content, tool);
9348
9435
  if (!content.trim() && !rule.path)
9349
9436
  throw new Error(`Instruction rule content or path is required for rule ${rule.id}.`);
9350
9437
  const resolvedPath = normalizeRulePath(rule.path ?? `${slug(rule.id)}.md`);
@@ -9355,6 +9442,7 @@ function normalizeInstructionRules(source, tool) {
9355
9442
  return {
9356
9443
  ...rule,
9357
9444
  content,
9445
+ metadata: floored.metadata,
9358
9446
  normalizedId: slug(rule.id),
9359
9447
  resolvedLabel: rule.label ?? rule.id,
9360
9448
  resolvedPath
@@ -11163,7 +11251,7 @@ var PROJECT_DASHBOARD_PROFILE_VARIABLES = {
11163
11251
  PROJECT_DASHBOARD_DIR: ".hasna/project",
11164
11252
  PROJECT_DASHBOARD_RENDER_MANIFEST: ".hasna/project/dashboard/render.json",
11165
11253
  PROJECT_DASHBOARD_SNAPSHOTS_DIR: ".hasna/project/dashboard/snapshots",
11166
- PROJECT_CHANNEL_PREFIX: "iproj-"
11254
+ PROJECT_CHANNEL_PREFIX: ""
11167
11255
  };
11168
11256
  var PROJECT_DASHBOARD_STANDARD_CONTENT = `# Agent-Managed Project Dashboard Standard
11169
11257
 
@@ -11218,8 +11306,8 @@ context.
11218
11306
 
11219
11307
  ## Coordination
11220
11308
 
11221
- - Project conversation channels use \`iproj-<project-slug>\` in the CLI and are
11222
- displayed to humans as \`#iproj-<project-slug>\`.
11309
+ - Project conversation channels use the normalized project slug in the CLI and
11310
+ are displayed to humans as \`#<project-slug>\`.
11223
11311
  - Todos tasks are the source of truth for work; messages are only coordination.
11224
11312
  - Durable Codewith goal plans should own long-running implementation.
11225
11313
  - New implementation/verification work should route through task-triggered fresh
@@ -11324,10 +11412,15 @@ function mergeProfileSelectors(preset, existing) {
11324
11412
  };
11325
11413
  }
11326
11414
  function mergeProfileVariables(preset, existing) {
11327
- return {
11415
+ const variables = {
11328
11416
  ...preset ?? {},
11329
11417
  ...existing
11330
11418
  };
11419
+ for (const [key, value] of Object.entries(preset ?? {})) {
11420
+ if (value === "")
11421
+ variables[key] = value;
11422
+ }
11423
+ return variables;
11331
11424
  }
11332
11425
  function mergeUnique(preset, existing) {
11333
11426
  const values = [...new Set([...preset ?? [], ...existing ?? []])];
@@ -15,6 +15,82 @@ import type { Config } from "../types/index.js";
15
15
  * Reference configs (`kind: "reference"`) own no target path and never match.
16
16
  */
17
17
  export declare function findConfigsByTargetPath(configs: Config[], targetPath: string): Config[];
18
+ /**
19
+ * Every reference-kind row already ingested under `name`.
20
+ *
21
+ * A reference config (`kind: "reference"`) owns no target_path — it is not
22
+ * mirrored 1:1 onto one file on disk, so `findConfigsByTargetPath` can never
23
+ * find it, by design (see that function's own doc comment). That left
24
+ * `add <path> --kind reference --update` with no identity signal at all: every
25
+ * re-ingest of a reference config's content minted a fresh row instead of
26
+ * updating the one that already existed, at every `--update` setting, because
27
+ * there was nothing to match on. Measured live 2026-08-04, todos 757cefdb: 20
28
+ * of 20 reference-kind rows in the fleet store had target_path=null.
29
+ *
30
+ * For a reference config, `name` IS the identity, in exactly the same sense a
31
+ * file-kind config's target_path is its identity: re-ingest with the same
32
+ * name, get the same row; re-ingest with a different name, get a different
33
+ * (or new) row. Two comparisons, both needed:
34
+ *
35
+ * - EXACT name match. `uniqueSlug` (db/database.ts) only de-duplicates the
36
+ * SLUG column, which carries a DB-level UNIQUE constraint — it never
37
+ * touches `name`, which carries no such constraint. So every prior
38
+ * duplicate this bug already produced still has the identical `name` and a
39
+ * `-1`, `-2`, ... suffixed slug. Measured live 2026-08-04 in the fleet
40
+ * store: 8 reference rows all named "Global Agent Rules Standard"
41
+ * (`global-agent-rules-standard-1` through `-8`), one identical SHA-256
42
+ * content hash across all 8, ingested on 6 different days — the exact
43
+ * shape this function exists to stop.
44
+ * - Slugified match, for a re-ingest whose `--name` differs only in case or
45
+ * punctuation from an existing row's name.
46
+ *
47
+ * CORRECTED 2026-08-04 (todos 195272ae, Finding 1): this used to compare
48
+ * the query's slug against each candidate's STORED `.slug` COLUMN
49
+ * (`config.slug === wantedSlug`). That is sound only for a candidate whose
50
+ * own slug was never disambiguated — the moment two rows already collide
51
+ * and `uniqueSlug` has suffixed one of them (`sample-rule-1`), its stored
52
+ * slug no longer equals what re-slugifying its OWN name produces, so the
53
+ * old comparison went blind to it. Reproduced live: row A "Sample Rule"
54
+ * (slug "sample-rule"), row B "sample rule" (slug disambiguated to
55
+ * "sample-rule-1" because A already held the base slug) — querying "Sample
56
+ * Rule" found only A. `add --update` then updated A, reported
57
+ * `rest.length === 0` (no "N other rows share this name" warning), and
58
+ * left B — the exact row a human would call a duplicate of A — untouched
59
+ * and unmentioned. This is the one population the slug clause exists to
60
+ * catch: it is impossible for a fresh, non-colliding row to need it, since
61
+ * an un-disambiguated slug already matches via `slugify(name)` trivially.
62
+ * Comparing against `slugify(config.name)` instead — recomputed from the
63
+ * candidate's own name rather than trusted from its (possibly
64
+ * disambiguated) stored column — fixes this without weakening the EXACT
65
+ * name clause above, which still independently catches the byte-identical
66
+ * case regardless: it can only ADD matches the old comparison missed, not
67
+ * remove any a query's name literally shares.
68
+ */
69
+ export declare function findReferenceConfigsByName(configs: Config[], name: string): Config[];
70
+ /**
71
+ * Groups of reference-kind rows that collide on identity, the mirror image of
72
+ * `findDuplicateTargetPathGroups` for the identity axis reference configs
73
+ * actually use. Only groups with more than one member are returned, so an
74
+ * empty result means the store is clean.
75
+ *
76
+ * CORRECTED 2026-08-04 (todos 195272ae, Finding 1): grouping used to key on
77
+ * the raw, exact `config.name` string. `doctor` (which calls this) therefore
78
+ * reported a store CLEAN for two rows whose names differ only in case or
79
+ * punctuation — precisely the pair `findReferenceConfigsByName` above treats
80
+ * as one identity (see its doc comment for the reproduction). The two
81
+ * functions disagreeing about what "the same reference config" means was the
82
+ * same defect class PR #57 fixed one level up, one file down: `doctor` a
83
+ * store clean, `add --update` half-fixing it. Keying on `slugify(config.name)`
84
+ * instead makes this agree with `findReferenceConfigsByName`'s identity
85
+ * notion — a case/punctuation variant is now reported as a duplicate group
86
+ * too, not only a byte-identical one. The reported `name` is the first
87
+ * colliding row's own (human-authored) name, for display — the grouping key
88
+ * itself is never surfaced.
89
+ */
90
+ export declare function findDuplicateReferenceNameGroups(configs: Config[]): Array<{
91
+ name: string;
92
+ configs: Config[];
93
+ }>;
18
94
  /**
19
95
  * Groups of rows that collide on one normalized target path. Only groups with
20
96
  * more than one member are returned, so an empty result means the store is
@@ -1 +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"}
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;AAIhD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAOvF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAKpF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAU9G;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"}
@@ -127,7 +127,17 @@ export declare function compareAgentOperatingRulesVersions(left: string, right:
127
127
  * ties on priority in `deduplicateSemanticPolicySources` and then WINS on version,
128
128
  * EVICTING the genuine baseline from the same render; the collapse happens before
129
129
  * `rejectDuplicateSourceSlugs` runs, so the duplicate-slug guard never sees the
130
- * collision. Nothing in these bytes distinguishes a genuine future rules version from
130
+ * collision. That eviction was REACHABLE and is now narrowed, not closed: the managed
131
+ * source id `hasna-agent-operating-rules` earns precedence in
132
+ * `semanticPolicySourcePriority` alongside the managed slug, so the canonical source no
133
+ * longer merely ties with any export that sets `nonOverridable`, and an eviction by an
134
+ * unverified payload is reported in `skippedSources` and in `warnings` instead of
135
+ * passing as a routine collapse. An export that also mimics a canonical id still ties
136
+ * and still wins on version. Ordering by `payloadIntegrity` instead was tried and
137
+ * rejected: the pinned digest describes the EMBEDDED snapshot, so preferring it would
138
+ * freeze a home carrying that snapshot beside a newly published rules document — the
139
+ * same downgrade this floor exists to prevent, arriving by the selection path.
140
+ * Nothing in these bytes distinguishes a genuine future rules version from
131
141
  * an inflated one. Rejecting
132
142
  * above-baseline versions was considered and deliberately NOT done: the canonical
133
143
  * rules document ships from `@hasna/identities`, which legitimately runs ahead of the
@@ -138,15 +148,24 @@ export declare function compareAgentOperatingRulesVersions(left: string, right:
138
148
  * channel), not a comparison. Until then the choice is recorded rather than hidden:
139
149
  * every payload carries `payloadIntegrity`, which is `unverified-self-declared`
140
150
  * whenever bytes were accepted on their version claim alone.
141
- * 2. This function guards only the payloads routed through it, and the render pipeline
142
- * routes exactly one field: `source.content`. `normalizeSources` floors that, so a
143
- * claiming source is covered whether it came from the config store, an identity export,
144
- * or a file. `source.rules[].content` is NOT floored `normalizeInstructionRules` only
145
- * filters provider blocks, `normalizeIdentityRules` copies rule bodies straight out of
146
- * export JSON, and `deduplicateSemanticPolicySources` inspects only `source.content`.
147
- * So a sentinel carried inside a RULE is neither floored nor deduped nor attested, on
148
- * the same untrusted export transport this floor otherwise defends. That predates this
149
- * guard and is tracked as a follow-up; do not read the choke point as covering it.
151
+ * 2. This function guards only the payloads routed through it. The render pipeline routes
152
+ * BOTH `source.content` and `source.rules[].content`: `normalizeSources` floors the
153
+ * first and `normalizeInstructionRules` floors the second through
154
+ * `applyAgentOperatingRulesFloorToRule`, both before provider filtering, and
155
+ * `deduplicateSemanticPolicySources` reads a declaration from either field. A claiming
156
+ * source or rule is therefore covered whether it came from the config store, an
157
+ * identity export, or a file.
158
+ *
159
+ * The rule half was NOT covered until hasna/instructions#54, and this note used to say
160
+ * so in present tense. Until then a sentinel carried inside a RULE was neither floored
161
+ * nor deduped nor attested on the same untrusted export transport this floor otherwise
162
+ * defends, so an export installed a below-baseline NON-OVERRIDABLE rules document by
163
+ * putting it in `rules[]` instead of `content`.
164
+ *
165
+ * What remains uncovered is narrower and is stated so the choke point is not read as
166
+ * total: an unprivileged rule that merely QUOTES the rules mid-body is deliberately not
167
+ * floored (the F2 false positive), and a rule under a privileged parent IS floored even
168
+ * when it only quotes them.
150
169
  *
151
170
  * The attestation is also PER-RENDER, not durable: a repair is recorded in the manifest
152
171
  * of the render that performed it, so fleet-wide auditing needs those manifests
@@ -1 +1 @@
1
- {"version":3,"file":"global-agent-rules-standard.d.ts","sourceRoot":"","sources":["../../src/lib/global-agent-rules-standard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE/E,eAAO,MAAM,gCAAgC,gCAAgC,CAAC;AAE9E,eAAO,MAAM,mCAAmC,EAAG,mCAA4C,CAAC;AAChG,eAAO,MAAM,+BAA+B,EAAG,6BAAsC,CAAC;AACtF,yFAAyF;AACzF,eAAO,MAAM,0BAA0B,EAAG,uBAAgC,CAAC;AAC3E,eAAO,MAAM,6BAA6B,EAAG,OAAgB,CAAC;AAC9D,eAAO,MAAM,wCAAwC,EAAG,YAAqB,CAAC;AAC9E,eAAO,MAAM,8BAA8B,EAAG,8CAAuD,CAAC;AACtG;;;;;GAKG;AACH,eAAO,MAAM,yCAAyC,EAAG,6BAAsC,CAAC;AAChG,6FAA6F;AAC7F,eAAO,MAAM,sCAAsC,QAA2E,CAAC;AAC/H;;;;;;;GAOG;AACH,eAAO,MAAM,qCAAqC,QAAsG,CAAC;AACzJ,eAAO,MAAM,oCAAoC,EAAG,kEAA2E,CAAC;AAChI,eAAO,MAAM,oCAAoC,oEAAuC,CAAC;AACzF,eAAO,MAAM,0CAA0C,EAAG,kEAA2E,CAAC;AACtI,eAAO,MAAM,2CAA2C,EAAG,2DAAoE,CAAC;AAEhI,eAAO,MAAM,8BAA8B;;;;CAIjC,CAAC;AAEX,eAAO,MAAM,iCAAiC;;;;;;;CAOpC,CAAC;AAEX,eAAO,MAAM,gCAAgC;;;;;;;;;;;;CAYnC,CAAC;AAEX,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;CAejC,CAAC;AAEX,eAAO,MAAM,0BAA0B,8ZAA8Z,CAAC;AAEtc,eAAO,MAAM,mCAAmC,QA+B7B,CAAC;AAEpB,iFAAiF;AACjF,MAAM,MAAM,gCAAgC,GAAG,eAAe,GAAG,mBAAmB,CAAC;AAErF;;;;;;;;GAQG;AACH,MAAM,MAAM,mCAAmC,GAAG,eAAe,GAAG,0BAA0B,CAAC;AAE/F,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,gCAAgC,CAAC;IACzC,iFAAiF;IACjF,uBAAuB,EAAE,OAAO,CAAC;IACjC,gFAAgF;IAChF,SAAS,EAAE,mCAAmC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,2EAA2E;AAC3E,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAEjG;AAED,qDAAqD;AACrD,wBAAgB,kCAAkC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQtF;AAmBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,0BAA0B,CA0E5B;AAwBD;;;;;;GAMG;AACH,wBAAsB,oCAAoC,CAAC,KAAK,GAAE,WAAkC,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBrH"}
1
+ {"version":3,"file":"global-agent-rules-standard.d.ts","sourceRoot":"","sources":["../../src/lib/global-agent-rules-standard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE/E,eAAO,MAAM,gCAAgC,gCAAgC,CAAC;AAE9E,eAAO,MAAM,mCAAmC,EAAG,mCAA4C,CAAC;AAChG,eAAO,MAAM,+BAA+B,EAAG,6BAAsC,CAAC;AACtF,yFAAyF;AACzF,eAAO,MAAM,0BAA0B,EAAG,uBAAgC,CAAC;AAC3E,eAAO,MAAM,6BAA6B,EAAG,OAAgB,CAAC;AAC9D,eAAO,MAAM,wCAAwC,EAAG,YAAqB,CAAC;AAC9E,eAAO,MAAM,8BAA8B,EAAG,8CAAuD,CAAC;AACtG;;;;;GAKG;AACH,eAAO,MAAM,yCAAyC,EAAG,6BAAsC,CAAC;AAChG,6FAA6F;AAC7F,eAAO,MAAM,sCAAsC,QAA2E,CAAC;AAC/H;;;;;;;GAOG;AACH,eAAO,MAAM,qCAAqC,QAAsG,CAAC;AACzJ,eAAO,MAAM,oCAAoC,EAAG,kEAA2E,CAAC;AAChI,eAAO,MAAM,oCAAoC,oEAAuC,CAAC;AACzF,eAAO,MAAM,0CAA0C,EAAG,kEAA2E,CAAC;AACtI,eAAO,MAAM,2CAA2C,EAAG,2DAAoE,CAAC;AAEhI,eAAO,MAAM,8BAA8B;;;;CAIjC,CAAC;AAEX,eAAO,MAAM,iCAAiC;;;;;;;CAOpC,CAAC;AAEX,eAAO,MAAM,gCAAgC;;;;;;;;;;;;CAYnC,CAAC;AAEX,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;CAejC,CAAC;AAEX,eAAO,MAAM,0BAA0B,8ZAA8Z,CAAC;AAEtc,eAAO,MAAM,mCAAmC,QA+B7B,CAAC;AAEpB,iFAAiF;AACjF,MAAM,MAAM,gCAAgC,GAAG,eAAe,GAAG,mBAAmB,CAAC;AAErF;;;;;;;;GAQG;AACH,MAAM,MAAM,mCAAmC,GAAG,eAAe,GAAG,0BAA0B,CAAC;AAE/F,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,gCAAgC,CAAC;IACzC,iFAAiF;IACjF,uBAAuB,EAAE,OAAO,CAAC;IACjC,gFAAgF;IAChF,SAAS,EAAE,mCAAmC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,2EAA2E;AAC3E,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAEjG;AAED,qDAAqD;AACrD,wBAAgB,kCAAkC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQtF;AAmBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,0BAA0B,CA0E5B;AAwBD;;;;;;GAMG;AACH,wBAAsB,oCAAoC,CAAC,KAAK,GAAE,WAAkC,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBrH"}
@@ -2,6 +2,6 @@ import type { Config, ProfileVariables } from "../types/index.js";
2
2
  import { type ConfigStore } from "../data/config-store.js";
3
3
  export declare const PROJECT_DASHBOARD_STANDARD_SLUG = "agent-managed-project-dashboard-standard";
4
4
  export declare const PROJECT_DASHBOARD_PROFILE_VARIABLES: ProfileVariables;
5
- export declare const PROJECT_DASHBOARD_STANDARD_CONTENT = "# Agent-Managed Project Dashboard Standard\n\nThis standard applies to Hasna work projects under `Workspace/<division>/project/<slug>`.\nHumans do not work directly inside these folders; agents keep structure,\nevidence, tasks, knowledge, and dashboard output consistent.\n\n## Canonical Files\n\n- Project manifest root: `.hasna/project/`\n- Dashboard render manifest: `.hasna/project/dashboard/render.json`\n- Latest snapshot: `.hasna/project/dashboard/snapshots/latest.snapshot.json`\n- Dashboard schema ids come from `@hasna/contracts`.\n- Project folders may contain private documents, but render JSON must contain\n only ids, counts, statuses, resource refs, evidence refs, and redacted\n summaries.\n\n## Viewer Commands\n\nUse the Projects-owned viewer. Do not invent a separate per-project app unless\n`open-projects` cannot express the surface.\n\n```bash\nprojects dashboard snapshot <project> --write --json\nprojects dashboard render <project> --json\nprojects dashboard validate <project> --json\nPROJECTS_DASHBOARD_TOKEN=<token> projects dashboard serve <project> --host 0.0.0.0 --port <port>\n```\n\nNon-loopback serving must use `--token`, `PROJECTS_DASHBOARD_TOKEN`, or an\nexplicit `--trust-network` choice. Never put the token in a URL, task\nevidence, render spec, or report.\n\n## Provider Panels\n\nProvider CLIs emit bounded `hasna.project_panel.v1` summaries:\n\n```bash\ntodos project-panel --project <project> --json --contract\nfiles project-panel --project <project> --json --contract\nmailery project-panel --project <project> --limit 20 --json --contract\nconversations project-panel --project <project> --limit 30 --json --contract\nknowledge project-panel --project <project> --scope project --limit 30 --json --contract\nmementos --json project-panel --project <project> --contract\nreports project-panel --project <project> --json --contract\n```\n\nProviders must degrade to unavailable/error panels instead of dumping raw\ncontent. Mailery is workspace-scoped until explicit project-email mapping is\nconfigured; Knowledge must run from the project cwd or with the correct store\ncontext.\n\n## Coordination\n\n- Project conversation channels use `iproj-<project-slug>` in the CLI and are\n displayed to humans as `#iproj-<project-slug>`.\n- Todos tasks are the source of truth for work; messages are only coordination.\n- Durable Codewith goal plans should own long-running implementation.\n- New implementation/verification work should route through task-triggered fresh\n agent runs, not by opening or pasting into existing tmux panes.\n- Agent handoff should reference task ids, project ids, commit ids, evidence\n paths, and dashboard URLs without exposing secrets or raw private documents.\n\n## Report Rules\n\nReports and dashboards should use JSON Render/React Flow through\n`projects dashboard render`. Include decisions, open questions, bank/document\nids, tasks, and evidence refs. Exclude raw email bodies, account numbers, tax\nids, passport numbers, credentials, and contract clauses unless an explicit\napproved storage policy exists.\n";
5
+ export declare const PROJECT_DASHBOARD_STANDARD_CONTENT = "# Agent-Managed Project Dashboard Standard\n\nThis standard applies to Hasna work projects under `Workspace/<division>/project/<slug>`.\nHumans do not work directly inside these folders; agents keep structure,\nevidence, tasks, knowledge, and dashboard output consistent.\n\n## Canonical Files\n\n- Project manifest root: `.hasna/project/`\n- Dashboard render manifest: `.hasna/project/dashboard/render.json`\n- Latest snapshot: `.hasna/project/dashboard/snapshots/latest.snapshot.json`\n- Dashboard schema ids come from `@hasna/contracts`.\n- Project folders may contain private documents, but render JSON must contain\n only ids, counts, statuses, resource refs, evidence refs, and redacted\n summaries.\n\n## Viewer Commands\n\nUse the Projects-owned viewer. Do not invent a separate per-project app unless\n`open-projects` cannot express the surface.\n\n```bash\nprojects dashboard snapshot <project> --write --json\nprojects dashboard render <project> --json\nprojects dashboard validate <project> --json\nPROJECTS_DASHBOARD_TOKEN=<token> projects dashboard serve <project> --host 0.0.0.0 --port <port>\n```\n\nNon-loopback serving must use `--token`, `PROJECTS_DASHBOARD_TOKEN`, or an\nexplicit `--trust-network` choice. Never put the token in a URL, task\nevidence, render spec, or report.\n\n## Provider Panels\n\nProvider CLIs emit bounded `hasna.project_panel.v1` summaries:\n\n```bash\ntodos project-panel --project <project> --json --contract\nfiles project-panel --project <project> --json --contract\nmailery project-panel --project <project> --limit 20 --json --contract\nconversations project-panel --project <project> --limit 30 --json --contract\nknowledge project-panel --project <project> --scope project --limit 30 --json --contract\nmementos --json project-panel --project <project> --contract\nreports project-panel --project <project> --json --contract\n```\n\nProviders must degrade to unavailable/error panels instead of dumping raw\ncontent. Mailery is workspace-scoped until explicit project-email mapping is\nconfigured; Knowledge must run from the project cwd or with the correct store\ncontext.\n\n## Coordination\n\n- Project conversation channels use the normalized project slug in the CLI and\n are displayed to humans as `#<project-slug>`.\n- Todos tasks are the source of truth for work; messages are only coordination.\n- Durable Codewith goal plans should own long-running implementation.\n- New implementation/verification work should route through task-triggered fresh\n agent runs, not by opening or pasting into existing tmux panes.\n- Agent handoff should reference task ids, project ids, commit ids, evidence\n paths, and dashboard URLs without exposing secrets or raw private documents.\n\n## Report Rules\n\nReports and dashboards should use JSON Render/React Flow through\n`projects dashboard render`. Include decisions, open questions, bank/document\nids, tasks, and evidence refs. Exclude raw email bodies, account numbers, tax\nids, passport numbers, credentials, and contract clauses unless an explicit\napproved storage policy exists.\n";
6
6
  export declare function ensureProjectDashboardStandardConfig(store?: ConfigStore): Promise<Config>;
7
7
  //# sourceMappingURL=project-dashboard-standard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"project-dashboard-standard.d.ts","sourceRoot":"","sources":["../../src/lib/project-dashboard-standard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE/E,eAAO,MAAM,+BAA+B,6CAA6C,CAAC;AAE1F,eAAO,MAAM,mCAAmC,EAAE,gBAKjD,CAAC;AAEF,eAAO,MAAM,kCAAkC,2hGAqE9C,CAAC;AAEF,wBAAsB,oCAAoC,CAAC,KAAK,GAAE,WAAkC,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BrH"}
1
+ {"version":3,"file":"project-dashboard-standard.d.ts","sourceRoot":"","sources":["../../src/lib/project-dashboard-standard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE/E,eAAO,MAAM,+BAA+B,6CAA6C,CAAC;AAE1F,eAAO,MAAM,mCAAmC,EAAE,gBAKjD,CAAC;AAEF,eAAO,MAAM,kCAAkC,0hGAqE9C,CAAC;AAEF,wBAAsB,oCAAoC,CAAC,KAAK,GAAE,WAAkC,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BrH"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=session-render-rule-currency-floor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-render-rule-currency-floor.test.d.ts","sourceRoot":"","sources":["../../src/lib/session-render-rule-currency-floor.test.ts"],"names":[],"mappings":""}
@@ -150,6 +150,11 @@ export interface SessionRenderManifest {
150
150
  path: string;
151
151
  globs: string[];
152
152
  hash: string | null;
153
+ contentSha256: string;
154
+ payloadFloorApplied: boolean | null;
155
+ flooredFromRulesVersion: string | null;
156
+ flooredFromPayloadSha256: string | null;
157
+ payloadIntegrity: string | null;
153
158
  }>;
154
159
  renderedPayloadSha256: string;
155
160
  provenance: Record<string, unknown> | null;
@@ -1 +1 @@
1
- {"version":3,"file":"session-render.d.ts","sourceRoot":"","sources":["../../src/lib/session-render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-render.d.ts","sourceRoot":"","sources":["../../src/lib/session-render.ts"],"names":[],"mappings":"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"}
package/dist/mcp/index.js CHANGED
@@ -6957,7 +6957,7 @@ var init_sync_dir = __esm(() => {
6957
6957
  var require_package = __commonJS((exports, module) => {
6958
6958
  module.exports = {
6959
6959
  name: "@hasna/instructions",
6960
- version: "0.4.18",
6960
+ version: "0.4.20",
6961
6961
  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.",
6962
6962
  type: "module",
6963
6963
  main: "dist/index.js",
@@ -7062,6 +7062,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprot
7062
7062
 
7063
7063
  // src/lib/config-target-identity.ts
7064
7064
  init_apply();
7065
+ init_database();
7065
7066
  function findConfigsByTargetPath(configs, targetPath) {
7066
7067
  const wanted = normalizeTargetPath(targetPath);
7067
7068
  return configs.filter((config) => {
@@ -7072,6 +7073,10 @@ function findConfigsByTargetPath(configs, targetPath) {
7072
7073
  return normalizeTargetPath(config.target_path) === wanted;
7073
7074
  });
7074
7075
  }
7076
+ function findReferenceConfigsByName(configs, name) {
7077
+ const wantedSlug = slugify(name);
7078
+ return configs.filter((config) => config.kind === "reference" && (config.name === name || slugify(config.name) === wantedSlug));
7079
+ }
7075
7080
 
7076
7081
  // src/mcp/server.ts
7077
7082
  init_sync_dir();
@@ -7178,7 +7183,7 @@ function summarizeApplyResult(result) {
7178
7183
  var TOOL_DOCS = {
7179
7184
  list_configs: "List configs. Params: category?, agent?, kind?, search?, limit?, cursor?, verbose?. Defaults to a paged compact envelope without content; use get_config for full content.",
7180
7185
  get_config: "Get a config by id or slug. Returns full config including content.",
7181
- create_config: "Create a new config. Required: name, content, category. Optional: agent, target_path, outputs, kind, format, tags, description, is_template. Refuses when target_path is already tracked by another config (one target path, one row) \u2014 use update_config on the owning row, or delete_config first. kind:'reference' owns no target path and is exempt.",
7186
+ create_config: "Create a new config. Required: name, content, category. Optional: agent, target_path, outputs, kind, format, tags, description, is_template. Refuses when target_path is already tracked by another config (one target path, one row) \u2014 use update_config on the owning row, or delete_config first. kind:'reference' owns no target path and is exempt from that check, but is instead refused when its name (or a case/punctuation variant of it) already tracks another reference config.",
7182
7187
  update_config: "Update a config by id or slug. Optional: content, name, tags, description, category, agent, target_path, outputs.",
7183
7188
  apply_config: "Apply a config through the shared ownership gate. Params: id_or_slug, dry_run?, verbose?. Returns results plus session-renderer-owned targets that were skipped.",
7184
7189
  sync_directory: "Sync a directory with the DB. Params: dir, direction ('from_disk'|'to_disk'). Returns sync result.",
@@ -7269,6 +7274,15 @@ function buildServer() {
7269
7274
  return err(`${targetPath} is already tracked by: ${named}.${collision}` + ` Use update_config on that row to refresh it in place, or delete_config first.`);
7270
7275
  }
7271
7276
  }
7277
+ if (kind === "reference") {
7278
+ const name2 = args["name"];
7279
+ const owners = findReferenceConfigsByName(await store.listConfigs(), name2);
7280
+ if (owners.length > 0) {
7281
+ const named = owners.map((owner) => `${owner.slug} (${owner.id})`).join(", ");
7282
+ const collision = owners.length > 1 ? ` ${owners.length} rows already collide on this name \u2014 apply order between them is undefined.` : "";
7283
+ return err(`Reference config "${name2}" is already tracked by: ${named}.${collision}` + ` Use update_config on that row to refresh it in place, or delete_config first.`);
7284
+ }
7285
+ }
7272
7286
  const c = await store.createConfig({
7273
7287
  name: args["name"],
7274
7288
  content: args["content"],
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AA4EnE,wBAAgB,WAAW,IAAI,MAAM,CAyTpC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AA4EnE,wBAAgB,WAAW,IAAI,MAAM,CAyVpC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/instructions",
3
- "version": "0.4.18",
3
+ "version": "0.4.20",
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",