@indigoai-us/hq-cli 5.201.0 → 5.201.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.201.2] — 2026-09-25
6
+
7
+ ### Changed
8
+
9
+ - The checkpoint ontology plan tells the model to name a person by the full name the input or the company's entities give, not a first name alone.
10
+
11
+ ## [5.201.1] — 2026-09-25
12
+
13
+ ### Fixed
14
+
15
+ - Outpost grant checks now include child lanes from the owning Outpost. Owner
16
+ records take precedence over duplicate primary records, and each grant
17
+ command reads the owner lane list once.
18
+ - Outpost grant checks re-read owner lanes under the hire lock and use the
19
+ validated Outpost CLI override for the lane-list probe.
20
+
5
21
  ## [5.201.0] — 2026-09-25
6
22
 
7
23
  ### Added
@@ -479,6 +479,14 @@ function laneHireFields(lane, lanes) {
479
479
  hire_summary: hireSummary,
480
480
  };
481
481
  }
482
+ function mergeOwnerLaneHierarchy(supplied, ownerLanes) {
483
+ const byId = new Map();
484
+ for (const lane of supplied)
485
+ byId.set(lane.lane_id, lane);
486
+ for (const lane of ownerLanes)
487
+ byId.set(lane.lane_id, lane);
488
+ return [...byId.values()];
489
+ }
482
490
  function outpostCliOverride(ctx, outpostId) {
483
491
  const envKey = `HQ_LANES_OUTPOST_CLI_${outpostId.toUpperCase().replace(/[^A-Z0-9_]/g, "_")}`;
484
492
  const configured = ctx.env[envKey];
@@ -1031,11 +1039,12 @@ async function loadHostCapacitySnapshots(ctx, hqRoot, config = loadLanesConfig(h
1031
1039
  };
1032
1040
  }
1033
1041
  async function readOutpostLaneRecords(ctx, outpostId) {
1042
+ const hqBinary = outpostCliOverride(ctx, outpostId);
1034
1043
  let result;
1035
1044
  try {
1036
1045
  result = await ctx.dispatchOutpostExec({
1037
1046
  outpostId,
1038
- command: buildOutpostLaneListCommand(),
1047
+ command: buildOutpostLaneListCommand({ hqBinary }),
1039
1048
  timeoutSeconds: CAPACITY_PROBE_TIMEOUT_MS / 1000,
1040
1049
  waitMs: CAPACITY_PROBE_TIMEOUT_MS,
1041
1050
  });
@@ -3312,9 +3321,20 @@ async function dispatchOutpostLaneCommand(ctx, lane, action, options) {
3312
3321
  throw new LanesError("outpost_dispatch_failed", `Lane ${lane.lane_id} has no Outpost host to dispatch to`, { lane_id: lane.lane_id });
3313
3322
  }
3314
3323
  const outpostId = lane.host.id;
3315
- const grantContext = action === "grant"
3316
- ? createOutpostHireGrantContext(lane, loadAllLanes(ctx.hqRoot()), await ctx.laneHireGrantsEnabled(lane.company))
3317
- : undefined;
3324
+ let grantContext;
3325
+ let grantHierarchy;
3326
+ if (action === "grant") {
3327
+ const enforcementEnabled = await ctx.laneHireGrantsEnabled(lane.company);
3328
+ let hierarchy = loadAllLanes(ctx.hqRoot());
3329
+ const ownerLanes = await readOutpostLaneRecords(ctx, outpostId);
3330
+ const byId = new Map(hierarchy.map((record) => [record.lane_id, record]));
3331
+ for (const ownerLane of ownerLanes) {
3332
+ byId.set(ownerLane.lane_id, ownerLane);
3333
+ }
3334
+ hierarchy = [...byId.values()];
3335
+ grantHierarchy = hierarchy;
3336
+ grantContext = createOutpostHireGrantContext(lane, hierarchy, enforcementEnabled);
3337
+ }
3318
3338
  let dispatched;
3319
3339
  try {
3320
3340
  dispatched = await ctx.dispatchOutpostExec({
@@ -3407,6 +3427,7 @@ async function dispatchOutpostLaneCommand(ctx, lane, action, options) {
3407
3427
  ...remote,
3408
3428
  lane_id: ownerLane.lane_id,
3409
3429
  lane: ownerLane,
3430
+ ...laneHireFields(ownerLane, grantHierarchy ?? []),
3410
3431
  outpost_id: outpostId,
3411
3432
  outpost_command_id: dispatched.commandId,
3412
3433
  outpost_transport: "outposts_exec",
@@ -4518,7 +4539,11 @@ async function applyHireGrant(ctx, laneId, hireGrant, authorization, grantContex
4518
4539
  (!grantContext || !sameHireGrantSenior(current.senior, grantContext.expected_senior))) {
4519
4540
  throw new LanesError("hire_grant_senior_changed", `Lane ${laneId}'s senior changed before the Outpost applied the grant update`, { lane_id: laneId, current_senior: current.senior });
4520
4541
  }
4521
- const hierarchy = grantContext?.hierarchy ?? loadAllLanes(hqRoot);
4542
+ const hierarchy = grantContext
4543
+ ? authorization === "ssm-owner-dispatch"
4544
+ ? mergeOwnerLaneHierarchy(grantContext.hierarchy, loadAllLanes(hqRoot))
4545
+ : grantContext.hierarchy
4546
+ : loadAllLanes(hqRoot);
4522
4547
  if (enforce && current.senior.kind === "lane") {
4523
4548
  if (!current.senior.id) {
4524
4549
  throw new LanesError("hire_grant_senior_invalid", `Lane ${laneId} has a lane senior without an id`, {
@@ -4604,7 +4629,8 @@ async function runGrantOwnerTarget(ctx, laneId, opts) {
4604
4629
  const hireGrant = parseHireGrant(opts.hire);
4605
4630
  const grantContext = parseOutpostHireGrantContext(opts.grantContext, laneId);
4606
4631
  const hqRoot = ctx.hqRoot();
4607
- printGrantResult(hqRoot, await applyHireGrant(ctx, laneId, hireGrant, "ssm-owner-dispatch", grantContext), grantContext.hierarchy);
4632
+ const updated = await applyHireGrant(ctx, laneId, hireGrant, "ssm-owner-dispatch", grantContext);
4633
+ printGrantResult(hqRoot, updated, mergeOwnerLaneHierarchy(grantContext.hierarchy, loadAllLanes(hqRoot)));
4608
4634
  }
4609
4635
  async function runBackfillGrants(ctx, opts) {
4610
4636
  if (opts.apply && opts.dryRun) {
@@ -29,7 +29,7 @@ const CANDIDATE_INSTRUCTIONS = [
29
29
  `Write ${CANDIDATES_FILE} in the run directory as {"schema":"${CANDIDATES_SCHEMA}","candidates":[...]} and nothing else.`,
30
30
  "Each candidate: {input, type, name, aliases, confidence, evidence}. input is one of this plan's input ids; type is person, project, company or concept; name is the entity's full proper name; aliases are other names the input uses for it (at most 5); confidence is 0 to 1; evidence is a short quote from the input.",
31
31
  "Read only the files and line ranges this plan lists. For a signal, read its body and name the entities in missing_refs if the signal supports them.",
32
- "Name the specific people, projects, products, companies and named concepts that the input says something about. That includes the company that owns this knowledge and its own products when the input describes them. Name a third-party tool, vendor or service only when a section of the input is about it; skip ones that appear in a list, a stack summary or a passing mention. Skip generic words, file names and headings.",
32
+ "Name the specific people, projects, products, companies and named concepts that the input says something about. That includes the company that owns this knowledge and its own products when the input describes them. Name a third-party tool, vendor or service only when a section of the input is about it; skip ones that appear in a list, a stack summary or a passing mention. Skip generic words, file names and headings. Name a person by the full name the input or the company's entities give, not a first name alone.",
33
33
  "For the session input (its text is session_text in this plan), name only entities that already exist in the company and that the session did work on. Session candidates are recorded as links, never created.",
34
34
  "Do not create, edit, move or delete anything under ontology/, signals/ or sources/ yourself.",
35
35
  ];
@@ -72,7 +72,7 @@ export declare function parseOutpostPickupPayload(raw: unknown): OutpostPickupPa
72
72
  export declare function buildOutpostPickupCommand(payloadUrl: string): string;
73
73
  /** Bounded, read-only capacity query executed by the target Outpost CLI. */
74
74
  export declare function buildOutpostCapacityCommand(): string;
75
- /** Read every lane on an Outpost, optionally using its configured HQ binary. */
75
+ /** Read lane records owned by an Outpost, using its configured HQ binary when set. */
76
76
  export declare function buildOutpostLaneListCommand(input?: {
77
77
  hqBinary?: string;
78
78
  }): string;
@@ -65,7 +65,7 @@ export function buildOutpostPickupCommand(payloadUrl) {
65
65
  export function buildOutpostCapacityCommand() {
66
66
  return withRemoteHqDir(joinCommandParts(["hq", "lanes", "capacity", "--json"]));
67
67
  }
68
- /** Read every lane on an Outpost, optionally using its configured HQ binary. */
68
+ /** Read lane records owned by an Outpost, using its configured HQ binary when set. */
69
69
  export function buildOutpostLaneListCommand(input = {}) {
70
70
  return withRemoteHqDir(joinCommandParts([
71
71
  input.hqBinary?.trim() || "hq",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.201.0",
3
+ "version": "5.201.2",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {