@lsctech/polaris 0.3.2 → 0.3.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.
@@ -52,14 +52,15 @@ function groupAndSort(packets) {
52
52
  * Write _review-queue.json (canonical) and _review-queue.md (display-only) to outputDir.
53
53
  * Markdown is regenerated from JSON — never parse markdown to recover decisions.
54
54
  */
55
- function writeReviewQueue(packets, runId, outputDir) {
55
+ function writeReviewQueue(packets, runId, outputDir, filename = "_review-queue.json") {
56
56
  (0, node_fs_1.mkdirSync)(outputDir, { recursive: true });
57
57
  const queueFile = {
58
58
  generated_at: new Date().toISOString(),
59
59
  run_id: runId,
60
60
  packets,
61
61
  };
62
- (0, node_fs_1.writeFileSync)((0, node_path_1.join)(outputDir, "_review-queue.json"), JSON.stringify(queueFile, null, 2) + "\n", "utf-8");
62
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(outputDir, filename), JSON.stringify(queueFile, null, 2) + "\n", "utf-8");
63
+ const mdFilename = filename.replace(/\.json$/, ".md");
63
64
  const sorted = groupAndSort(packets);
64
65
  const sections = sorted.map(renderPacketMarkdown).join("\n\n---\n\n");
65
66
  const md = [
@@ -69,21 +70,21 @@ function writeReviewQueue(packets, runId, outputDir) {
69
70
  `**Generated:** ${queueFile.generated_at}`,
70
71
  `**Pending review:** ${packets.length} document(s)`,
71
72
  ``,
72
- `> Markdown is display-only. Edit \`_review-queue.json\` to set \`reviewDecision\` fields.`,
73
+ `> Markdown is display-only. Edit \`${filename}\` to set \`reviewDecision\` fields.`,
73
74
  `> Rerun \`polaris docs ingest\` to apply decisions.`,
74
75
  ``,
75
76
  `---`,
76
77
  ``,
77
78
  sections,
78
79
  ].join("\n");
79
- (0, node_fs_1.writeFileSync)((0, node_path_1.join)(outputDir, "_review-queue.md"), md, "utf-8");
80
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(outputDir, mdFilename), md, "utf-8");
80
81
  }
81
82
  /**
82
83
  * Read review queue from JSON. Returns empty array if no queue file exists.
83
84
  * Never reads markdown.
84
85
  */
85
- function readReviewQueue(outputDir) {
86
- const jsonPath = (0, node_path_1.join)(outputDir, "_review-queue.json");
86
+ function readReviewQueue(outputDir, filename = "_review-queue.json") {
87
+ const jsonPath = (0, node_path_1.join)(outputDir, filename);
87
88
  if (!(0, node_fs_1.existsSync)(jsonPath))
88
89
  return [];
89
90
  try {
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.agenticDecideKey = agenticDecideKey;
4
+ const node_fs_1 = require("node:fs");
5
+ async function agenticDecideKey(packet) {
6
+ let docContent = "";
7
+ try {
8
+ if ((0, node_fs_1.existsSync)(packet.sourcePath)) {
9
+ docContent = (0, node_fs_1.readFileSync)(packet.sourcePath, "utf-8").slice(0, 3000);
10
+ }
11
+ }
12
+ catch { /* ignore */ }
13
+ // @ts-ignore: @anthropic-ai/sdk may not be installed as a dependency
14
+ const mod = await import("@anthropic-ai/sdk");
15
+ const Anthropic = mod.default ?? mod.Anthropic;
16
+ const client = new Anthropic();
17
+ const staleSymbols = packet.staleSymbols;
18
+ const triageFlag = packet.triageFlag;
19
+ const prompt = `You are reviewing a candidate documentation file flagged during Polaris docs triage.
20
+
21
+ Flag type: ${String(triageFlag ?? "unknown")}
22
+ Authority risk: ${packet.authorityRisk}
23
+ Recommendation from triage: ${packet.recommendation}
24
+ Reasoning: ${packet.reasoning.join("; ")}
25
+ ${Array.isArray(staleSymbols) ? `Stale symbols (not found in codebase graph): ${staleSymbols.join(", ")}` : ""}
26
+
27
+ Document content:
28
+ ---
29
+ ${docContent}
30
+ ---
31
+
32
+ Decide whether this document should be:
33
+ - approved: doc is valid doctrine and should be promoted to active
34
+ - rejected: doc is outdated, incorrect, or superseded and should be deprecated
35
+ - deferred: uncertain — needs human review
36
+
37
+ Respond with exactly one word: approve, reject, or defer.`;
38
+ const response = await client.messages.create({
39
+ model: "claude-haiku-4-5-20251001",
40
+ max_tokens: 10,
41
+ messages: [{ role: "user", content: prompt }],
42
+ });
43
+ const text = (response.content[0].text ?? "defer").trim().toLowerCase();
44
+ if (text.startsWith("approve"))
45
+ return "a";
46
+ if (text.startsWith("reject"))
47
+ return "r";
48
+ return "d";
49
+ }
@@ -142,12 +142,24 @@ function createDocsCommand(options = {}) {
142
142
  .description("Interactively review pending governance decisions in the review queue")
143
143
  .option("--queue <path>", "path to _review-queue.json (default: smartdocs/raw/_review-queue.json)")
144
144
  .option("-r, --repo-root <path>", "Repository root", defaultRepoRoot)
145
+ .option("--agentic", "use LLM agent to make review decisions automatically")
146
+ .option("--triage", "review the triage queue (_triage-queue.json) instead of the review queue")
145
147
  .action(async (opts) => {
148
+ const repoRoot = opts.repoRoot;
149
+ const queueFilename = opts.triage ? "_triage-queue.json" : "_review-queue.json";
150
+ const queueDir = opts.queue
151
+ ? (0, node_path_1.resolve)(opts.repoRoot, opts.queue)
152
+ .replace(/_review-queue\.json$/, "")
153
+ .replace(/_triage-queue\.json$/, "")
154
+ .replace(/\/$/, "")
155
+ : (0, node_path_1.resolve)(repoRoot, "smartdocs", "raw");
156
+ let readKey;
157
+ if (opts.agentic) {
158
+ const { agenticDecideKey } = await import("./agentic-review.js");
159
+ readKey = agenticDecideKey;
160
+ }
146
161
  try {
147
- const queueDir = opts.queue
148
- ? (0, node_path_1.resolve)(opts.repoRoot, opts.queue).replace(/_review-queue\.json$/, "").replace(/\/$/, "")
149
- : (0, node_path_1.resolve)(opts.repoRoot, "smartdocs", "raw");
150
- await (0, review_js_1.runReviewSession)({ repoRoot: opts.repoRoot, queueDir });
162
+ await (0, review_js_1.runReviewSession)({ repoRoot, queueDir, queueFilename, readKey });
151
163
  }
152
164
  catch (err) {
153
165
  console.error(`polaris docs review: ${err instanceof Error ? err.message : String(err)}`);
@@ -84,7 +84,8 @@ function readSingleKey() {
84
84
  async function runReviewSession(options) {
85
85
  const { repoRoot, readKey, getReviewedBy = defaultGetReviewedBy, output = (msg) => process.stdout.write(msg + "\n"), } = options;
86
86
  const queueDir = options.queueDir ?? (0, node_path_1.resolve)(repoRoot, "smartdocs", "raw");
87
- const packets = (0, index_js_1.readReviewQueue)(queueDir);
87
+ const queueFilename = options.queueFilename;
88
+ const packets = (0, index_js_1.readReviewQueue)(queueDir, queueFilename);
88
89
  if (packets.length === 0) {
89
90
  output("No review queue found. Run polaris docs ingest first.");
90
91
  return;
@@ -98,7 +99,7 @@ async function runReviewSession(options) {
98
99
  for (let i = 0; i < undecided.length; i++) {
99
100
  const packet = undecided[i];
100
101
  output(formatPacketCard(packet, i + 1, undecided.length));
101
- const key = readKey ? await readKey() : await readSingleKey();
102
+ const key = readKey ? await readKey(packet) : await readSingleKey();
102
103
  if (key === "q") {
103
104
  const remaining = undecided.length - decided;
104
105
  output(`\nSession ended. ${decided} decision(s) saved, ${remaining} packet(s) still pending.`);
@@ -126,7 +127,7 @@ async function runReviewSession(options) {
126
127
  reviewedBy: getReviewedBy(),
127
128
  };
128
129
  }
129
- (0, index_js_1.writeReviewQueue)(packets, "review-session", queueDir);
130
+ (0, index_js_1.writeReviewQueue)(packets, "review-session", queueDir, queueFilename);
130
131
  decided++;
131
132
  }
132
133
  const approved = packets.filter((p) => p.reviewDecision === "approve").length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lsctech/polaris",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Polaris — standalone taskchain orchestration framework for governed AI agent workflows",
5
5
  "bin": {
6
6
  "polaris-cli": "dist/cli/index.js"