@lsctech/polaris 0.4.1 → 0.4.3

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.
@@ -46,7 +46,7 @@ const commands_js_1 = require("./commands.js");
46
46
  * `.claude/commands/polaris-<verb>.md` file per verb.
47
47
  *
48
48
  * Skill-backed verbs route through the existing packet+chain path:
49
- * 1. Read .polaris/skills/<skill>/SKILL.md
49
+ * 1. Read .polaris/skills/<target-skill>/SKILL.md
50
50
  * 2. Run `polaris skill packet <skill>`
51
51
  * 3. Execute the chain
52
52
  *
@@ -96,8 +96,8 @@ See \`${command.routing}\` for the full routing protocol and skill directory res
96
96
 
97
97
  ## Execution
98
98
 
99
- 1. Look up \`/${command.name}\` in \`${command.routing}\` to find the target skill directory.
100
- 2. Read \`.polaris/skills/<target-skill>/SKILL.md\` — it is the authoritative instruction source.
99
+ 1. Look up \`/${command.name}\` in \`${command.routing}\` to confirm the target skill directory.
100
+ 2. Read \`.polaris/skills/${command.targetSkill}/SKILL.md\` — it is the authoritative instruction source.
101
101
  3. Run the skill bootloader:
102
102
  \`\`\`bash
103
103
  polaris skill packet ${command.skill}${command.args.length > 0 ? " $ARGUMENTS" : ""}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.CODEX_PLUGIN_SKILL_VERSION = void 0;
37
+ exports.generateCodexPluginSkill = generateCodexPluginSkill;
38
+ exports.generateCodexOpenAiYaml = generateCodexOpenAiYaml;
39
+ exports.generateAllCodexPluginSkills = generateAllCodexPluginSkills;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const commands_js_1 = require("./commands.js");
43
+ exports.CODEX_PLUGIN_SKILL_VERSION = "1";
44
+ function skillCommands() {
45
+ return commands_js_1.SLASH_COMMANDS.filter((command) => command.kind === "skill");
46
+ }
47
+ function renderArgs(command) {
48
+ if (command.args.length === 0)
49
+ return "None.";
50
+ return command.args
51
+ .map((arg) => `- \`${arg.name}\`${arg.required ? " (required)" : " (optional)"} - ${arg.description}`)
52
+ .join("\n");
53
+ }
54
+ function renderUsage(command) {
55
+ const argUsage = command.args
56
+ .map((arg) => (arg.required ? `<${arg.name}>` : `[${arg.name}]`))
57
+ .join(" ");
58
+ return argUsage ? `${command.name} ${argUsage}` : command.name;
59
+ }
60
+ function renderBootloaderArgs(command) {
61
+ const argUsage = command.args
62
+ .map((arg) => (arg.required ? `<${arg.name}>` : `[${arg.name}]`))
63
+ .join(" ");
64
+ return argUsage ? ` ${argUsage}` : "";
65
+ }
66
+ function generateCodexPluginSkill(command) {
67
+ return `---
68
+ name: ${command.name}
69
+ description: ${command.description}
70
+ ---
71
+ <!-- polaris-codex-skill-version: ${exports.CODEX_PLUGIN_SKILL_VERSION} -->
72
+
73
+ # ${command.name}
74
+
75
+ ${command.description}
76
+
77
+ This Codex plugin skill is a thin wrapper around the canonical Polaris skill. It does not implement a parallel runtime.
78
+
79
+ ## Usage
80
+
81
+ \`\`\`text
82
+ ${renderUsage(command)}
83
+ \`\`\`
84
+
85
+ ## Arguments
86
+
87
+ ${renderArgs(command)}
88
+
89
+ ## Mandatory Routing
90
+
91
+ 1. Read \`${command.routing}\` and resolve \`${command.name}\` to its target skill.
92
+ 2. Read \`.polaris/skills/${command.targetSkill}/SKILL.md\` before any repo inspection, tracker lookup, or runtime file reads.
93
+ 3. Run the skill bootloader from that canonical \`SKILL.md\`:
94
+ \`\`\`bash
95
+ polaris skill packet ${command.skill}${renderBootloaderArgs(command)}
96
+ \`\`\`
97
+ 4. If no packet is returned, stop and report: \`Blocking: Polaris could not authorize this run.\`
98
+ 5. Execute \`.polaris/skills/${command.targetSkill}/chain.md\` in strict step order.
99
+
100
+ If \`.polaris/skills/${command.targetSkill}/SKILL.md\` is missing, stop and report:
101
+ \`Blocking: skill packet not found at .polaris/skills/${command.targetSkill}/SKILL.md\`
102
+ `;
103
+ }
104
+ function generateCodexOpenAiYaml(command) {
105
+ const displayName = command.name
106
+ .split("-")
107
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
108
+ .join(" ");
109
+ return `interface:
110
+ display_name: "${displayName}"
111
+ short_description: "${command.description.replaceAll('"', '\\"')}"
112
+ brand_color: "#6366F1"
113
+ default_prompt: "Use $${command.name} to ${command.description.charAt(0).toLowerCase()}${command.description.slice(1)}."
114
+ `;
115
+ }
116
+ function generateAllCodexPluginSkills(outDir = ".codex/plugins/polaris/skills") {
117
+ fs.mkdirSync(outDir, { recursive: true });
118
+ const written = [];
119
+ for (const command of skillCommands()) {
120
+ const skillDir = path.join(outDir, command.name);
121
+ const agentsDir = path.join(skillDir, "agents");
122
+ fs.mkdirSync(agentsDir, { recursive: true });
123
+ const skillPath = path.join(skillDir, "SKILL.md");
124
+ fs.writeFileSync(skillPath, generateCodexPluginSkill(command), "utf8");
125
+ written.push(skillPath);
126
+ const yamlPath = path.join(agentsDir, "openai.yaml");
127
+ fs.writeFileSync(yamlPath, generateCodexOpenAiYaml(command), "utf8");
128
+ written.push(yamlPath);
129
+ }
130
+ return written;
131
+ }
@@ -7,6 +7,7 @@ exports.SLASH_COMMANDS = [
7
7
  name: "polaris-run",
8
8
  kind: "skill",
9
9
  skill: "run",
10
+ targetSkill: "polaris-run",
10
11
  routing: ".polaris/skills/ROUTING.md",
11
12
  args: [
12
13
  {
@@ -21,6 +22,7 @@ exports.SLASH_COMMANDS = [
21
22
  name: "polaris-analyze",
22
23
  kind: "skill",
23
24
  skill: "analyze",
25
+ targetSkill: "polaris-analyze",
24
26
  routing: ".polaris/skills/ROUTING.md",
25
27
  args: [
26
28
  {
@@ -31,6 +33,15 @@ exports.SLASH_COMMANDS = [
31
33
  ],
32
34
  description: "Analyze a cluster and produce an implementation plan via the Analyst skill packet",
33
35
  },
36
+ {
37
+ name: "polaris-finalize",
38
+ kind: "skill",
39
+ skill: "run",
40
+ targetSkill: "polaris-run",
41
+ routing: ".polaris/skills/ROUTING.md",
42
+ args: [],
43
+ description: "Finalize the active Polaris run through the Foreman skill packet",
44
+ },
34
45
  {
35
46
  name: "polaris-init",
36
47
  kind: "cli",
@@ -48,7 +59,8 @@ exports.SLASH_COMMANDS = [
48
59
  {
49
60
  name: "polaris-reconcile",
50
61
  kind: "skill",
51
- skill: "triage",
62
+ skill: "reconcile",
63
+ targetSkill: "polaris-reconcile",
52
64
  routing: ".polaris/skills/ROUTING.md",
53
65
  args: [
54
66
  {
@@ -59,6 +71,21 @@ exports.SLASH_COMMANDS = [
59
71
  ],
60
72
  description: "Reconcile project cognition via the triage skill packet",
61
73
  },
74
+ {
75
+ name: "polaris-catalog",
76
+ kind: "skill",
77
+ skill: "catalog",
78
+ targetSkill: "polaris-catalog",
79
+ routing: ".polaris/skills/ROUTING.md",
80
+ args: [
81
+ {
82
+ name: "cluster_id",
83
+ required: true,
84
+ description: "Cluster ID to catalog (e.g., POL-257)",
85
+ },
86
+ ],
87
+ description: "Catalog project cognition and SmartDocs via the catalog skill packet",
88
+ },
62
89
  {
63
90
  name: "polaris-status",
64
91
  kind: "cli",
@@ -66,6 +93,24 @@ exports.SLASH_COMMANDS = [
66
93
  args: [],
67
94
  description: "Print the current Polaris loop run state summary",
68
95
  },
96
+ {
97
+ name: "docs-ingest",
98
+ kind: "skill",
99
+ skill: "ingest",
100
+ targetSkill: "docs-ingest",
101
+ routing: ".polaris/skills/ROUTING.md",
102
+ args: [],
103
+ description: "Ingest raw documentation files through the Polaris SmartDocs skill packet",
104
+ },
105
+ {
106
+ name: "docs-promote",
107
+ kind: "skill",
108
+ skill: "promote",
109
+ targetSkill: "docs-promote",
110
+ routing: ".polaris/skills/ROUTING.md",
111
+ args: [],
112
+ description: "Review and promote candidate SmartDocs through the Polaris governance skill packet",
113
+ },
69
114
  ];
70
115
  exports.SLASH_COMMAND_BY_NAME = Object.fromEntries(exports.SLASH_COMMANDS.map((command) => [command.name, command]));
71
116
  function resolveSlashCommand(name) {
@@ -35,10 +35,12 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.detectShimDrift = detectShimDrift;
37
37
  exports.syncShims = syncShims;
38
+ exports.syncCodexPluginSkills = syncCodexPluginSkills;
38
39
  const fs = __importStar(require("fs"));
39
40
  const path = __importStar(require("path"));
40
41
  const commands_js_1 = require("./commands.js");
41
42
  const claude_generator_js_1 = require("./claude-generator.js");
43
+ const codex_generator_js_1 = require("./codex-generator.js");
42
44
  /**
43
45
  * Workspace sync and versioning for generated agent-plugin shims.
44
46
  *
@@ -106,3 +108,6 @@ function syncShims(outDir = ".claude/commands") {
106
108
  }
107
109
  return { written, drift };
108
110
  }
111
+ function syncCodexPluginSkills(outDir = ".codex/plugins/polaris/skills") {
112
+ return { written: (0, codex_generator_js_1.generateAllCodexPluginSkills)(outDir) };
113
+ }
@@ -86,9 +86,18 @@ function gateUserIntervened(artifacts) {
86
86
  };
87
87
  }
88
88
  /**
89
- * foreman-resent-packet: Was the packet dispatched more than once (dispatch_epoch > 1)?
89
+ * foreman-resent-packet: Was the same child dispatched more than once?
90
90
  *
91
- * Evidence: dispatch_boundary.dispatch_epoch in current-state.json.
91
+ * Evidence:
92
+ * - open_children_meta.<child>.dispatch_record.dispatch_count (if runtime tracks it)
93
+ * - ledger child-dispatched events (issue_id)
94
+ * - telemetry child-dispatched events (child_id)
95
+ *
96
+ * A normal multi-session run has dispatch_epoch > 1 because distinct children are
97
+ * dispatched across sessions. That is expected. The problematic pattern is the
98
+ * foreman re-sending a worker packet to the same child after that child already
99
+ * returned a result. When per-child dispatch count data is unavailable, the gate
100
+ * is skipped rather than failing on dispatch_epoch alone.
92
101
  */
93
102
  function gateForemanResentPacket(artifacts) {
94
103
  const state = artifacts.currentState;
@@ -98,13 +107,57 @@ function gateForemanResentPacket(artifacts) {
98
107
  if (typeof dispatchEpoch !== "number") {
99
108
  return { gate: "foreman-resent-packet", outcome: "skipped", detail: "dispatch_epoch not present in state" };
100
109
  }
101
- const failed = dispatchEpoch > 1;
110
+ const perChildCounts = countChildDispatches(artifacts);
111
+ if (perChildCounts) {
112
+ const reDispatched = Array.from(perChildCounts.entries())
113
+ .filter(([, count]) => count > 1)
114
+ .map(([childId]) => childId);
115
+ const failed = reDispatched.length > 0;
116
+ return {
117
+ gate: "foreman-resent-packet",
118
+ outcome: failed ? "failed" : "passed",
119
+ detail: failed ? `child re-dispatched: ${reDispatched.join(", ")}` : undefined,
120
+ };
121
+ }
122
+ // No per-child dispatch data available. A single epoch cannot contain a re-dispatch.
123
+ if (dispatchEpoch === 1) {
124
+ return { gate: "foreman-resent-packet", outcome: "passed" };
125
+ }
102
126
  return {
103
127
  gate: "foreman-resent-packet",
104
- outcome: failed ? "failed" : "passed",
105
- detail: failed ? `dispatch_epoch=${dispatchEpoch}` : undefined,
128
+ outcome: "skipped",
129
+ detail: "per-child dispatch count data unavailable",
106
130
  };
107
131
  }
132
+ /** Counts per-child dispatches from all available artifact sources, or null if none are present. */
133
+ function countChildDispatches(artifacts) {
134
+ const counts = new Map();
135
+ const state = asRecord(artifacts.currentState);
136
+ const openChildrenMeta = asRecord(state?.["open_children_meta"]);
137
+ for (const [childId, meta] of Object.entries(openChildrenMeta ?? {})) {
138
+ const metaRec = asRecord(meta);
139
+ const dispatchRecord = asRecord(metaRec?.["dispatch_record"]);
140
+ const dispatchCount = dispatchRecord?.["dispatch_count"];
141
+ if (typeof dispatchCount === "number") {
142
+ counts.set(childId, Math.max(counts.get(childId) ?? 0, dispatchCount));
143
+ }
144
+ }
145
+ for (const event of artifacts.ledgerEvents) {
146
+ const rec = asRecord(event);
147
+ if (rec?.["event"] === "child-dispatched" && typeof rec["issue_id"] === "string") {
148
+ const childId = rec["issue_id"];
149
+ counts.set(childId, (counts.get(childId) ?? 0) + 1);
150
+ }
151
+ }
152
+ for (const event of artifacts.telemetryEvents) {
153
+ const rec = asRecord(event);
154
+ if (rec?.["event"] === "child-dispatched" && typeof rec["child_id"] === "string") {
155
+ const childId = rec["child_id"];
156
+ counts.set(childId, (counts.get(childId) ?? 0) + 1);
157
+ }
158
+ }
159
+ return counts.size > 0 ? counts : null;
160
+ }
108
161
  /**
109
162
  * foreman-fixed-worker-output: Did foreman make commits between child-complete
110
163
  * and the next dispatch?
@@ -94,6 +94,7 @@ function safeReaddir(dir) {
94
94
  return [];
95
95
  }
96
96
  }
97
+ const NON_WORKER_PREFIXES = ["librarian-", "CHART-", "medic-result-"];
97
98
  function readResultPackets(clusterDir) {
98
99
  if (!clusterDir)
99
100
  return [];
@@ -101,7 +102,7 @@ function readResultPackets(clusterDir) {
101
102
  if (!(0, node_fs_1.existsSync)(resultsDir))
102
103
  return [];
103
104
  return safeReaddir(resultsDir)
104
- .filter((f) => f.endsWith(".json"))
105
+ .filter((f) => f.endsWith(".json") && !NON_WORKER_PREFIXES.some((p) => f.startsWith(p)))
105
106
  .map((f) => readJson((0, node_path_1.join)(resultsDir, f)))
106
107
  .filter((v) => v !== undefined);
107
108
  }
@@ -158,8 +159,19 @@ function loadRunArtifacts(repoRoot, runId) {
158
159
  const telemetryEvents = telemetryPath ? (0, gates_js_1.readJsonLines)(telemetryPath) : [];
159
160
  // Result packets from cluster results dir
160
161
  const resultPackets = readResultPackets(clusterDir);
161
- // Also check for WorkerResultContracts inside result packets
162
- const workerResultContracts = extractWorkerResultContracts(resultPackets);
162
+ // WorkerResultContracts: prefer completed_children_results from current-state.json (Bug A fix)
163
+ let workerResultContracts;
164
+ const stateRec = currentState && typeof currentState === "object" && currentState !== null
165
+ ? currentState
166
+ : null;
167
+ const completedChildrenResults = stateRec?.["completed_children_results"];
168
+ if (completedChildrenResults && typeof completedChildrenResults === "object" && !Array.isArray(completedChildrenResults)) {
169
+ workerResultContracts = Object.values(completedChildrenResults).filter((v) => v !== null && typeof v === "object" && typeof v["worker_id"] === "string");
170
+ }
171
+ else {
172
+ // Legacy fallback: extract from result packet files
173
+ workerResultContracts = extractWorkerResultContracts(resultPackets);
174
+ }
163
175
  return {
164
176
  runId,
165
177
  runDir,
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractRepoOverview = extractRepoOverview;
4
+ exports.refreshPolarisRules = refreshPolarisRules;
3
5
  exports.generatePolarisRules = generatePolarisRules;
4
6
  const node_fs_1 = require("node:fs");
5
7
  const node_path_1 = require("node:path");
@@ -186,6 +188,32 @@ function buildContentInline(overview) {
186
188
  "",
187
189
  ].join("\n");
188
190
  }
191
+ function extractRepoOverview(content) {
192
+ const match = content.match(/(?:^|\n)## Repository Overview\r?\n([\s\S]*?)(?:\r?\n## |$)/);
193
+ if (!match)
194
+ return "Repository managed by Polaris.";
195
+ const overview = match[1].trim().replace(/(^|\n)---\s*$/, "").trim();
196
+ return overview || "Repository managed by Polaris.";
197
+ }
198
+ function refreshPolarisRules(repoRoot, currentVersion) {
199
+ const outputPath = (0, node_path_1.join)(repoRoot, "POLARIS_RULES.md");
200
+ let content = "";
201
+ if ((0, node_fs_1.existsSync)(outputPath)) {
202
+ content = (0, node_fs_1.readFileSync)(outputPath, "utf-8");
203
+ }
204
+ const firstLine = content.split(/\r?\n/)[0] ?? "";
205
+ const versionMatch = firstLine.match(/^<!-- polaris-version: ([\d.]+-?[\w.]*) -->$/);
206
+ const existingVersion = versionMatch?.[1];
207
+ if (existingVersion === currentVersion) {
208
+ return { status: "skipped", path: outputPath };
209
+ }
210
+ const overview = extractRepoOverview(content);
211
+ const newContent = `<!-- polaris-version: ${currentVersion} -->\n${buildContentInline(overview)}`;
212
+ const dir = (0, node_path_1.dirname)(outputPath);
213
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
214
+ (0, node_fs_1.writeFileSync)(outputPath, newContent, "utf-8");
215
+ return { status: "updated", path: outputPath };
216
+ }
189
217
  async function generatePolarisRules(repoRoot, inventory, options = {}) {
190
218
  const { overwrite = false, workspaceDir } = options;
191
219
  const outputPath = (0, node_path_1.join)(repoRoot, "POLARIS_RULES.md");
package/dist/cli/index.js CHANGED
@@ -27,6 +27,7 @@ const librarian_js_1 = require("./librarian.js");
27
27
  const medic_js_1 = require("./medic.js");
28
28
  const welfare_js_1 = require("../map/welfare.js");
29
29
  const adopt_command_js_1 = require("./adopt-command.js");
30
+ const upgrade_command_js_1 = require("./upgrade-command.js");
30
31
  const simplicity_js_1 = require("../loop/simplicity.js");
31
32
  const autoresearch_js_1 = require("./autoresearch.js");
32
33
  function resolveStateFile(repoRoot, explicit) {
@@ -110,6 +111,7 @@ function createPolarisCommand(options = {}) {
110
111
  repoRoot,
111
112
  }));
112
113
  program.addCommand((0, adopt_command_js_1.createAdoptCommand)({ repoRoot }));
114
+ program.addCommand((0, upgrade_command_js_1.createUpgradeCommand)({ repoRoot }));
113
115
  program.addCommand((0, autoresearch_js_1.createAutoresearchCommand)({ repoRoot }));
114
116
  program
115
117
  .command("simplicity")
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createUpgradeCommand = createUpgradeCommand;
4
+ const commander_1 = require("commander");
5
+ const version_js_1 = require("./version.js");
6
+ const adopt_rules_js_1 = require("./adopt-rules.js");
7
+ function createUpgradeCommand(options = {}) {
8
+ const repoRoot = options.repoRoot ?? process.cwd();
9
+ const doRefresh = options.refresh ?? adopt_rules_js_1.refreshPolarisRules;
10
+ const getCurrentVersion = options.getVersion ?? version_js_1.getVersion;
11
+ const cmd = new commander_1.Command("upgrade")
12
+ .description("Refresh POLARIS_RULES.md to the current Polaris CLI version")
13
+ .option("-r, --repo-root <path>", "Repository root", repoRoot)
14
+ .action(async (cmdOptions) => {
15
+ const targetRoot = cmdOptions.repoRoot ?? repoRoot;
16
+ const version = getCurrentVersion();
17
+ const result = doRefresh(targetRoot, version);
18
+ if (result.status === "updated") {
19
+ process.stdout.write(`POLARIS_RULES.md updated to version ${version}\n`);
20
+ }
21
+ else {
22
+ process.stdout.write(`Already up to date (${version})\n`);
23
+ }
24
+ });
25
+ return cmd;
26
+ }
@@ -101,6 +101,8 @@ Capture the resulting commit SHA.
101
101
 
102
102
  Record the commit SHA and list of committed files for step 09.
103
103
 
104
+ Use `git diff --cached --name-only` output as the source for `files_committed` — git outputs repo-relative paths (e.g., "src/cli/POLARIS.md"), which is the required format for the result JSON.
105
+
104
106
  ## Failure Handling
105
107
 
106
108
  If `git commit` fails:
@@ -24,7 +24,7 @@ interface CloseoutLibrarianResult {
24
24
  status: "success" | "partial" | "blocked" | "failure";
25
25
  commit_sha: string | null;
26
26
  commit_message: string;
27
- files_committed: string[];
27
+ files_committed: string[]; // repo-relative paths (e.g., "src/cli/POLARIS.md")
28
28
  drift_reconciliation: DriftReconciliationResult;
29
29
  polaris_md_updates: FileUpdate[];
30
30
  summary_md_updates: FileUpdate[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lsctech/polaris",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "Polaris — standalone taskchain orchestration framework for governed AI agent workflows",
5
5
  "bin": {
6
6
  "polaris": "dist/cli/index.js",