archondev 2.19.0 → 2.19.1
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 +20 -5
- package/dist/index.js +293 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ Copy governance files into any project. Works with your existing AI tools: **Cur
|
|
|
32
32
|
[Download Lite Packages →](https://archondev.io/download)
|
|
33
33
|
|
|
34
34
|
**What you get:**
|
|
35
|
-
-
|
|
35
|
+
- .archon/active/architecture.md template with best practices
|
|
36
36
|
- **Quality Level / Posture** — Tell AI if it's prototype, production, or enterprise-grade
|
|
37
37
|
- IDE-specific rule files (.cursorrules, CLAUDE.md, GEMINI.md, etc.)
|
|
38
38
|
- Progress tracking templates
|
|
@@ -45,6 +45,15 @@ Copy governance files into any project. Works with your existing AI tools: **Cur
|
|
|
45
45
|
- **Pre-Deploy Accessibility** — WCAG 2.2 AA check before going live, legal liability warnings
|
|
46
46
|
- Works with any AI coding assistant
|
|
47
47
|
|
|
48
|
+
### Local Governance SQLite (Dev Only)
|
|
49
|
+
|
|
50
|
+
Governance data for this repo lives in `.archon/governance.db` and is local-only. It is never synced to Supabase.
|
|
51
|
+
To initialize or refresh it:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pnpm exec tsx scripts/init-governance-db.ts
|
|
55
|
+
```
|
|
56
|
+
|
|
48
57
|
---
|
|
49
58
|
|
|
50
59
|
## Commands
|
|
@@ -84,14 +93,16 @@ Copy governance files into any project. Works with your existing AI tools: **Cur
|
|
|
84
93
|
| `archon seo fix` | Apply recommended SEO fixes |
|
|
85
94
|
| `archon geo identity` | Generate brand identity phrases for AI citation |
|
|
86
95
|
| `archon geo schema` | Generate JSON-LD schemas |
|
|
96
|
+
| `archon governance status` | Show governance status (AGD) |
|
|
97
|
+
| `archon governance architecture update` | Update architecture with change reason |
|
|
98
|
+
| `archon governance task update` | Update governance tasks |
|
|
99
|
+
| `archon governance handoff` | Log handoff + current context |
|
|
100
|
+
| `archon governance migrate` | Migrate legacy governance files |
|
|
101
|
+
| `archon governance sqlite-init` | Initialize or refresh local governance SQLite DB |
|
|
87
102
|
| `archon github connect` | Link GitHub account for cloud execution |
|
|
88
103
|
| `archon github status` | Check GitHub connection status |
|
|
89
104
|
| `archon session save [name]` | Save current session to cloud |
|
|
90
105
|
| `archon session resume [id]` | Resume session on another device |
|
|
91
|
-
|
|
92
|
-
**Notes:**
|
|
93
|
-
- Credits tier shows your balance and per‑model usage on startup; use `archon credits` for full details and history.
|
|
94
|
-
- You can paste multi‑line requests into interactive prompts; Archon captures them as a single response.
|
|
95
106
|
| `archon execute ATOM --cloud` | Execute in cloud (creates PR when done) |
|
|
96
107
|
| `archon cloud status` | List cloud executions |
|
|
97
108
|
| `archon parallel cloud ATOM-001 ATOM-002` | Queue multiple atoms for cloud execution (Credits tier) |
|
|
@@ -104,6 +115,10 @@ Copy governance files into any project. Works with your existing AI tools: **Cur
|
|
|
104
115
|
| `archon cleanup run` | Execute cleanup tasks |
|
|
105
116
|
| `archon cleanup auto [enable\|disable]` | Enable/disable auto cleanup on start |
|
|
106
117
|
|
|
118
|
+
**Notes:**
|
|
119
|
+
- Credits tier shows your balance and per‑model usage on startup; use `archon credits` for full details and history.
|
|
120
|
+
- You can paste multi‑line requests into interactive prompts; Archon captures them as a single response.
|
|
121
|
+
|
|
107
122
|
**Tip:** Use `archon plan --edit` to adjust title and acceptance criteria before planning.
|
|
108
123
|
**Web Checks:** If Archon detects a web project, it prompts to run A11y/SEO/GEO checks and stores your preference in `.archon/config.yaml`.
|
|
109
124
|
|
package/dist/index.js
CHANGED
|
@@ -3236,7 +3236,7 @@ async function showNewProjectMenu(cwd) {
|
|
|
3236
3236
|
await quickStart(cwd);
|
|
3237
3237
|
break;
|
|
3238
3238
|
case "3": {
|
|
3239
|
-
const description = await
|
|
3239
|
+
const description = await promptWithCommands("Describe what you want to do", { allowMultiline: true });
|
|
3240
3240
|
if (description.trim()) {
|
|
3241
3241
|
const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
|
|
3242
3242
|
await plan2(description, {});
|
|
@@ -3302,7 +3302,7 @@ async function runExploreFlow(cwd) {
|
|
|
3302
3302
|
const choice = await promptWithCommands("Enter choice");
|
|
3303
3303
|
switch (choice.toLowerCase()) {
|
|
3304
3304
|
case "1": {
|
|
3305
|
-
const description = await
|
|
3305
|
+
const description = await promptWithCommands("Describe what you want to do", { allowMultiline: true });
|
|
3306
3306
|
if (description.trim()) {
|
|
3307
3307
|
const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
|
|
3308
3308
|
await plan2(description, {});
|
|
@@ -3564,7 +3564,7 @@ ${state.forbiddenPatterns?.length ? `- **Forbidden patterns:** ${state.forbidden
|
|
|
3564
3564
|
console.log();
|
|
3565
3565
|
const continueChoice = await promptYesNo("Would you like to plan your first task now?", true);
|
|
3566
3566
|
if (continueChoice) {
|
|
3567
|
-
const description = await
|
|
3567
|
+
const description = await promptWithCommands("Describe what you want to build first", { allowMultiline: true });
|
|
3568
3568
|
if (description.trim()) {
|
|
3569
3569
|
const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
|
|
3570
3570
|
await plan2(description, {});
|
|
@@ -3649,7 +3649,7 @@ async function showAdaptExistingMenu(cwd, state) {
|
|
|
3649
3649
|
await runExploreFlow(cwd);
|
|
3650
3650
|
break;
|
|
3651
3651
|
case "2": {
|
|
3652
|
-
const description = await
|
|
3652
|
+
const description = await promptWithCommands("Describe what you want to do", { allowMultiline: true });
|
|
3653
3653
|
if (description.trim()) {
|
|
3654
3654
|
const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
|
|
3655
3655
|
await plan2(description, {});
|
|
@@ -3828,7 +3828,7 @@ async function showReviewProgress(cwd) {
|
|
|
3828
3828
|
}
|
|
3829
3829
|
async function planTask() {
|
|
3830
3830
|
const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
|
|
3831
|
-
const description = await
|
|
3831
|
+
const description = await promptWithCommands("Describe what you want to build", { allowMultiline: true });
|
|
3832
3832
|
if (description.trim()) {
|
|
3833
3833
|
await plan2(description, {});
|
|
3834
3834
|
}
|
|
@@ -4041,32 +4041,28 @@ function prompt(question) {
|
|
|
4041
4041
|
});
|
|
4042
4042
|
});
|
|
4043
4043
|
}
|
|
4044
|
-
function promptMultiline(question
|
|
4044
|
+
function promptMultiline(question) {
|
|
4045
4045
|
return new Promise((resolve) => {
|
|
4046
4046
|
const rl = readline.createInterface({
|
|
4047
4047
|
input: process.stdin,
|
|
4048
4048
|
output: process.stdout
|
|
4049
4049
|
});
|
|
4050
4050
|
const lines = [];
|
|
4051
|
-
let timer = null;
|
|
4052
|
-
const finish = () => {
|
|
4053
|
-
if (timer) clearTimeout(timer);
|
|
4054
|
-
rl.close();
|
|
4055
|
-
resolve(lines.join("\n").trimEnd());
|
|
4056
|
-
};
|
|
4057
|
-
const scheduleFinish = () => {
|
|
4058
|
-
if (timer) clearTimeout(timer);
|
|
4059
|
-
timer = setTimeout(finish, idleMs);
|
|
4060
|
-
};
|
|
4061
4051
|
rl.on("line", (line) => {
|
|
4052
|
+
if (line.trim() === ".") {
|
|
4053
|
+
rl.close();
|
|
4054
|
+
return;
|
|
4055
|
+
}
|
|
4062
4056
|
lines.push(line);
|
|
4063
|
-
scheduleFinish();
|
|
4064
4057
|
});
|
|
4065
4058
|
rl.on("SIGINT", () => {
|
|
4066
4059
|
rl.close();
|
|
4067
4060
|
process.exit(0);
|
|
4068
4061
|
});
|
|
4069
|
-
rl.
|
|
4062
|
+
rl.on("close", () => {
|
|
4063
|
+
resolve(lines.join("\n").trimEnd());
|
|
4064
|
+
});
|
|
4065
|
+
rl.setPrompt(`${chalk6.cyan("?")} ${question} (multi-line: end with a single '.' line or Ctrl+D): `);
|
|
4070
4066
|
rl.prompt();
|
|
4071
4067
|
});
|
|
4072
4068
|
}
|
|
@@ -7138,7 +7134,7 @@ async function modelsList() {
|
|
|
7138
7134
|
// src/cli/governance.ts
|
|
7139
7135
|
import { Command as Command2 } from "commander";
|
|
7140
7136
|
import chalk17 from "chalk";
|
|
7141
|
-
import { existsSync as
|
|
7137
|
+
import { existsSync as existsSync19, readFileSync as readFileSync7 } from "fs";
|
|
7142
7138
|
import { readFile as readFile12 } from "fs/promises";
|
|
7143
7139
|
import { join as join19 } from "path";
|
|
7144
7140
|
import matter4 from "gray-matter";
|
|
@@ -7623,6 +7619,7 @@ async function migrateLegacyGovernance(options = {}) {
|
|
|
7623
7619
|
}
|
|
7624
7620
|
|
|
7625
7621
|
// src/core/governance/sqlite.ts
|
|
7622
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync5, readFileSync as readFileSync6 } from "fs";
|
|
7626
7623
|
import { join as join18 } from "path";
|
|
7627
7624
|
import matter3 from "gray-matter";
|
|
7628
7625
|
import Database2 from "better-sqlite3";
|
|
@@ -7631,6 +7628,262 @@ var TASKS_PATH = join18(".archon", "active", "tasks.json");
|
|
|
7631
7628
|
var HANDOFFS_PATH = join18(".archon", "history", "handoffs.jsonl");
|
|
7632
7629
|
var DECISIONS_PATH = join18(".archon", "history", "decision_log.jsonl");
|
|
7633
7630
|
var COMPLETED_PATH = join18(".archon", "archive", "completed_tasks.jsonl");
|
|
7631
|
+
var GovernanceSqliteView = class {
|
|
7632
|
+
db = null;
|
|
7633
|
+
config;
|
|
7634
|
+
constructor(config = {}) {
|
|
7635
|
+
this.config = config;
|
|
7636
|
+
}
|
|
7637
|
+
init(cwd) {
|
|
7638
|
+
const archonDir = join18(cwd, ".archon");
|
|
7639
|
+
if (!existsSync18(archonDir)) {
|
|
7640
|
+
mkdirSync5(archonDir, { recursive: true });
|
|
7641
|
+
}
|
|
7642
|
+
const dbPath = this.config.inMemory ? ":memory:" : join18(cwd, this.config.dbPath ?? ".archon/governance.db");
|
|
7643
|
+
this.db = new Database2(dbPath);
|
|
7644
|
+
this.db.exec(`
|
|
7645
|
+
PRAGMA journal_mode = WAL;
|
|
7646
|
+
CREATE TABLE IF NOT EXISTS architecture (
|
|
7647
|
+
id TEXT PRIMARY KEY,
|
|
7648
|
+
version REAL,
|
|
7649
|
+
last_updated TEXT,
|
|
7650
|
+
updated_by TEXT,
|
|
7651
|
+
change_reason TEXT,
|
|
7652
|
+
content TEXT
|
|
7653
|
+
);
|
|
7654
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
7655
|
+
id TEXT PRIMARY KEY,
|
|
7656
|
+
description TEXT NOT NULL,
|
|
7657
|
+
status TEXT NOT NULL,
|
|
7658
|
+
created_at TEXT NOT NULL,
|
|
7659
|
+
updated_at TEXT,
|
|
7660
|
+
notes TEXT
|
|
7661
|
+
);
|
|
7662
|
+
CREATE TABLE IF NOT EXISTS completed_tasks (
|
|
7663
|
+
id TEXT PRIMARY KEY,
|
|
7664
|
+
description TEXT NOT NULL,
|
|
7665
|
+
status TEXT NOT NULL,
|
|
7666
|
+
created_at TEXT NOT NULL,
|
|
7667
|
+
updated_at TEXT,
|
|
7668
|
+
notes TEXT
|
|
7669
|
+
);
|
|
7670
|
+
CREATE TABLE IF NOT EXISTS handoffs (
|
|
7671
|
+
id TEXT PRIMARY KEY,
|
|
7672
|
+
timestamp TEXT NOT NULL,
|
|
7673
|
+
from_agent TEXT,
|
|
7674
|
+
reason TEXT NOT NULL,
|
|
7675
|
+
summary TEXT NOT NULL,
|
|
7676
|
+
next_actions TEXT NOT NULL
|
|
7677
|
+
);
|
|
7678
|
+
CREATE TABLE IF NOT EXISTS decisions (
|
|
7679
|
+
id TEXT PRIMARY KEY,
|
|
7680
|
+
timestamp TEXT NOT NULL,
|
|
7681
|
+
category TEXT NOT NULL,
|
|
7682
|
+
change_reason TEXT NOT NULL,
|
|
7683
|
+
updated_by TEXT,
|
|
7684
|
+
diff_summary TEXT
|
|
7685
|
+
);
|
|
7686
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS governance_fts USING fts5(
|
|
7687
|
+
source,
|
|
7688
|
+
record_id,
|
|
7689
|
+
text,
|
|
7690
|
+
timestamp
|
|
7691
|
+
);
|
|
7692
|
+
`);
|
|
7693
|
+
}
|
|
7694
|
+
close() {
|
|
7695
|
+
if (this.db) {
|
|
7696
|
+
this.db.close();
|
|
7697
|
+
this.db = null;
|
|
7698
|
+
}
|
|
7699
|
+
}
|
|
7700
|
+
async loadFromDisk(cwd) {
|
|
7701
|
+
if (!this.db) {
|
|
7702
|
+
throw new Error("GovernanceSqliteView not initialized. Call init() first.");
|
|
7703
|
+
}
|
|
7704
|
+
const stats = {
|
|
7705
|
+
tasks: 0,
|
|
7706
|
+
completedTasks: 0,
|
|
7707
|
+
handoffs: 0,
|
|
7708
|
+
decisions: 0,
|
|
7709
|
+
architecture: false
|
|
7710
|
+
};
|
|
7711
|
+
this.db.exec("DELETE FROM governance_fts; DELETE FROM architecture; DELETE FROM tasks; DELETE FROM completed_tasks; DELETE FROM handoffs; DELETE FROM decisions;");
|
|
7712
|
+
const archPath = join18(cwd, ARCH_PATH);
|
|
7713
|
+
if (existsSync18(archPath)) {
|
|
7714
|
+
const raw = readFileSync6(archPath, "utf-8");
|
|
7715
|
+
const parsed = matter3(raw);
|
|
7716
|
+
const data = parsed.data;
|
|
7717
|
+
const versionRaw = data["version"];
|
|
7718
|
+
const version = typeof versionRaw === "number" ? versionRaw : typeof versionRaw === "string" ? Number.parseFloat(versionRaw) : null;
|
|
7719
|
+
const archId = "architecture";
|
|
7720
|
+
const content = parsed.content.trim();
|
|
7721
|
+
this.db.prepare(
|
|
7722
|
+
`INSERT OR REPLACE INTO architecture (id, version, last_updated, updated_by, change_reason, content)
|
|
7723
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
7724
|
+
).run(
|
|
7725
|
+
archId,
|
|
7726
|
+
Number.isFinite(version) ? version : null,
|
|
7727
|
+
typeof data["last_updated"] === "string" ? data["last_updated"] : null,
|
|
7728
|
+
typeof data["updated_by"] === "string" ? data["updated_by"] : null,
|
|
7729
|
+
typeof data["change_reason"] === "string" ? data["change_reason"] : null,
|
|
7730
|
+
content
|
|
7731
|
+
);
|
|
7732
|
+
this.db.prepare(
|
|
7733
|
+
`INSERT INTO governance_fts (source, record_id, text, timestamp)
|
|
7734
|
+
VALUES (?, ?, ?, ?)`
|
|
7735
|
+
).run("architecture", archId, content, typeof data["last_updated"] === "string" ? data["last_updated"] : null);
|
|
7736
|
+
stats.architecture = true;
|
|
7737
|
+
}
|
|
7738
|
+
const tasksPath = join18(cwd, TASKS_PATH);
|
|
7739
|
+
if (existsSync18(tasksPath)) {
|
|
7740
|
+
const raw = readFileSync6(tasksPath, "utf-8");
|
|
7741
|
+
const tasks = JSON.parse(raw);
|
|
7742
|
+
const insertTask = this.db.prepare(
|
|
7743
|
+
`INSERT OR REPLACE INTO tasks (id, description, status, created_at, updated_at, notes)
|
|
7744
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
7745
|
+
);
|
|
7746
|
+
const insertFts = this.db.prepare(
|
|
7747
|
+
`INSERT INTO governance_fts (source, record_id, text, timestamp)
|
|
7748
|
+
VALUES (?, ?, ?, ?)`
|
|
7749
|
+
);
|
|
7750
|
+
for (const task of tasks) {
|
|
7751
|
+
insertTask.run(task.id, task.description, task.status, task.created_at, task.updated_at ?? null, task.notes ?? null);
|
|
7752
|
+
insertFts.run("task", task.id, task.description + (task.notes ? `
|
|
7753
|
+
${task.notes}` : ""), task.updated_at ?? task.created_at);
|
|
7754
|
+
stats.tasks += 1;
|
|
7755
|
+
}
|
|
7756
|
+
}
|
|
7757
|
+
const completedPath = join18(cwd, COMPLETED_PATH);
|
|
7758
|
+
if (existsSync18(completedPath)) {
|
|
7759
|
+
const lines = readFileSync6(completedPath, "utf-8").split("\n").filter((line) => line.trim().length > 0);
|
|
7760
|
+
const insertCompleted = this.db.prepare(
|
|
7761
|
+
`INSERT OR REPLACE INTO completed_tasks (id, description, status, created_at, updated_at, notes)
|
|
7762
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
7763
|
+
);
|
|
7764
|
+
const insertFts = this.db.prepare(
|
|
7765
|
+
`INSERT INTO governance_fts (source, record_id, text, timestamp)
|
|
7766
|
+
VALUES (?, ?, ?, ?)`
|
|
7767
|
+
);
|
|
7768
|
+
for (const line of lines) {
|
|
7769
|
+
const task = JSON.parse(line);
|
|
7770
|
+
insertCompleted.run(task.id, task.description, task.status, task.created_at, task.updated_at ?? null, task.notes ?? null);
|
|
7771
|
+
insertFts.run("completed_task", task.id, task.description + (task.notes ? `
|
|
7772
|
+
${task.notes}` : ""), task.updated_at ?? task.created_at);
|
|
7773
|
+
stats.completedTasks += 1;
|
|
7774
|
+
}
|
|
7775
|
+
}
|
|
7776
|
+
const handoffsPath = join18(cwd, HANDOFFS_PATH);
|
|
7777
|
+
if (existsSync18(handoffsPath)) {
|
|
7778
|
+
const lines = readFileSync6(handoffsPath, "utf-8").split("\n").filter((line) => line.trim().length > 0);
|
|
7779
|
+
const insertHandoff = this.db.prepare(
|
|
7780
|
+
`INSERT OR REPLACE INTO handoffs (id, timestamp, from_agent, reason, summary, next_actions)
|
|
7781
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
7782
|
+
);
|
|
7783
|
+
const insertFts = this.db.prepare(
|
|
7784
|
+
`INSERT INTO governance_fts (source, record_id, text, timestamp)
|
|
7785
|
+
VALUES (?, ?, ?, ?)`
|
|
7786
|
+
);
|
|
7787
|
+
for (const line of lines) {
|
|
7788
|
+
const entry = JSON.parse(line);
|
|
7789
|
+
const id = `${entry.timestamp}-${entry.from_agent ?? "unknown"}`;
|
|
7790
|
+
const nextActions = entry.next_actions.join("\n");
|
|
7791
|
+
insertHandoff.run(id, entry.timestamp, entry.from_agent ?? null, entry.reason, entry.summary, nextActions);
|
|
7792
|
+
insertFts.run("handoff", id, `${entry.summary}
|
|
7793
|
+
${nextActions}`, entry.timestamp);
|
|
7794
|
+
stats.handoffs += 1;
|
|
7795
|
+
}
|
|
7796
|
+
}
|
|
7797
|
+
const decisionsPath = join18(cwd, DECISIONS_PATH);
|
|
7798
|
+
if (existsSync18(decisionsPath)) {
|
|
7799
|
+
const lines = readFileSync6(decisionsPath, "utf-8").split("\n").filter((line) => line.trim().length > 0);
|
|
7800
|
+
const insertDecision = this.db.prepare(
|
|
7801
|
+
`INSERT OR REPLACE INTO decisions (id, timestamp, category, change_reason, updated_by, diff_summary)
|
|
7802
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
7803
|
+
);
|
|
7804
|
+
const insertFts = this.db.prepare(
|
|
7805
|
+
`INSERT INTO governance_fts (source, record_id, text, timestamp)
|
|
7806
|
+
VALUES (?, ?, ?, ?)`
|
|
7807
|
+
);
|
|
7808
|
+
for (const line of lines) {
|
|
7809
|
+
const entry = JSON.parse(line);
|
|
7810
|
+
const id = `${entry.timestamp}-${entry.category}`;
|
|
7811
|
+
insertDecision.run(
|
|
7812
|
+
id,
|
|
7813
|
+
entry.timestamp,
|
|
7814
|
+
entry.category,
|
|
7815
|
+
entry.change_reason,
|
|
7816
|
+
entry.updated_by ?? null,
|
|
7817
|
+
entry.diff_summary ?? null
|
|
7818
|
+
);
|
|
7819
|
+
insertFts.run("decision", id, `${entry.change_reason}${entry.diff_summary ? `
|
|
7820
|
+
${entry.diff_summary}` : ""}`, entry.timestamp);
|
|
7821
|
+
stats.decisions += 1;
|
|
7822
|
+
}
|
|
7823
|
+
}
|
|
7824
|
+
return stats;
|
|
7825
|
+
}
|
|
7826
|
+
search(query, limit = 10) {
|
|
7827
|
+
if (!this.db) {
|
|
7828
|
+
throw new Error("GovernanceSqliteView not initialized. Call init() first.");
|
|
7829
|
+
}
|
|
7830
|
+
const rows = this.db.prepare(
|
|
7831
|
+
`SELECT source, record_id as recordId, text, timestamp, rank
|
|
7832
|
+
FROM governance_fts
|
|
7833
|
+
WHERE governance_fts MATCH ?
|
|
7834
|
+
ORDER BY rank
|
|
7835
|
+
LIMIT ?`
|
|
7836
|
+
).all(query, limit);
|
|
7837
|
+
return rows;
|
|
7838
|
+
}
|
|
7839
|
+
listTasks(status2) {
|
|
7840
|
+
if (!this.db) {
|
|
7841
|
+
throw new Error("GovernanceSqliteView not initialized. Call init() first.");
|
|
7842
|
+
}
|
|
7843
|
+
if (status2) {
|
|
7844
|
+
return this.db.prepare(
|
|
7845
|
+
"SELECT id, description, status, created_at, updated_at, notes FROM tasks WHERE status = ? ORDER BY created_at"
|
|
7846
|
+
).all(status2);
|
|
7847
|
+
}
|
|
7848
|
+
return this.db.prepare(
|
|
7849
|
+
"SELECT id, description, status, created_at, updated_at, notes FROM tasks ORDER BY created_at"
|
|
7850
|
+
).all();
|
|
7851
|
+
}
|
|
7852
|
+
getLatestHandoff() {
|
|
7853
|
+
if (!this.db) {
|
|
7854
|
+
throw new Error("GovernanceSqliteView not initialized. Call init() first.");
|
|
7855
|
+
}
|
|
7856
|
+
const row = this.db.prepare(
|
|
7857
|
+
"SELECT timestamp, from_agent as fromAgent, reason, summary, next_actions as nextActions FROM handoffs ORDER BY timestamp DESC LIMIT 1"
|
|
7858
|
+
).get();
|
|
7859
|
+
if (!row) return null;
|
|
7860
|
+
return {
|
|
7861
|
+
timestamp: row.timestamp,
|
|
7862
|
+
from_agent: row.fromAgent ?? void 0,
|
|
7863
|
+
reason: row.reason,
|
|
7864
|
+
summary: row.summary,
|
|
7865
|
+
next_actions: row.nextActions.split("\n").filter((item) => item.trim().length > 0)
|
|
7866
|
+
};
|
|
7867
|
+
}
|
|
7868
|
+
getArchitecture() {
|
|
7869
|
+
if (!this.db) {
|
|
7870
|
+
throw new Error("GovernanceSqliteView not initialized. Call init() first.");
|
|
7871
|
+
}
|
|
7872
|
+
const row = this.db.prepare(
|
|
7873
|
+
"SELECT version, last_updated, updated_by, change_reason, content FROM architecture LIMIT 1"
|
|
7874
|
+
).get();
|
|
7875
|
+
if (!row) return null;
|
|
7876
|
+
return {
|
|
7877
|
+
content: row.content,
|
|
7878
|
+
meta: {
|
|
7879
|
+
version: row.version,
|
|
7880
|
+
last_updated: row.last_updated,
|
|
7881
|
+
updated_by: row.updated_by,
|
|
7882
|
+
change_reason: row.change_reason
|
|
7883
|
+
}
|
|
7884
|
+
};
|
|
7885
|
+
}
|
|
7886
|
+
};
|
|
7634
7887
|
|
|
7635
7888
|
// src/cli/governance.ts
|
|
7636
7889
|
var ACTIVE_ARCH_PATH3 = join19(".archon", "active", "architecture.md");
|
|
@@ -7644,11 +7897,11 @@ function isTaskStatus(value) {
|
|
|
7644
7897
|
}
|
|
7645
7898
|
function resolveArchitecturePath2(cwd) {
|
|
7646
7899
|
const agdPath = join19(cwd, ACTIVE_ARCH_PATH3);
|
|
7647
|
-
if (
|
|
7900
|
+
if (existsSync19(agdPath)) {
|
|
7648
7901
|
return { path: agdPath, source: "agd" };
|
|
7649
7902
|
}
|
|
7650
7903
|
const legacyPath = join19(cwd, "ARCHITECTURE.md");
|
|
7651
|
-
if (
|
|
7904
|
+
if (existsSync19(legacyPath)) {
|
|
7652
7905
|
return { path: legacyPath, source: "legacy" };
|
|
7653
7906
|
}
|
|
7654
7907
|
return { path: null, source: null };
|
|
@@ -7736,9 +7989,9 @@ function createGovernanceCommand() {
|
|
|
7736
7989
|
console.log(chalk17.yellow(" \u25CB No architecture file found"));
|
|
7737
7990
|
}
|
|
7738
7991
|
const tasksPath = join19(cwd, ACTIVE_TASKS_PATH2);
|
|
7739
|
-
if (
|
|
7992
|
+
if (existsSync19(tasksPath)) {
|
|
7740
7993
|
try {
|
|
7741
|
-
const tasksRaw = JSON.parse(
|
|
7994
|
+
const tasksRaw = JSON.parse(readFileSync7(tasksPath, "utf-8"));
|
|
7742
7995
|
const tasks2 = parseTasks(tasksRaw);
|
|
7743
7996
|
if (tasks2) {
|
|
7744
7997
|
renderStatusCounts(countTaskStatuses(tasks2));
|
|
@@ -7750,8 +8003,8 @@ function createGovernanceCommand() {
|
|
|
7750
8003
|
}
|
|
7751
8004
|
}
|
|
7752
8005
|
const contextPath = join19(cwd, CURRENT_CONTEXT_PATH);
|
|
7753
|
-
if (
|
|
7754
|
-
const content =
|
|
8006
|
+
if (existsSync19(contextPath)) {
|
|
8007
|
+
const content = readFileSync7(contextPath, "utf-8");
|
|
7755
8008
|
const meta = parseContextMeta(content);
|
|
7756
8009
|
console.log(chalk17.dim(` Handoff: ${meta.timestamp ?? "present"}`));
|
|
7757
8010
|
if (meta.reason) {
|
|
@@ -7759,15 +8012,15 @@ function createGovernanceCommand() {
|
|
|
7759
8012
|
}
|
|
7760
8013
|
}
|
|
7761
8014
|
const handoffHistoryPath = join19(cwd, HANDOFF_HISTORY_PATH);
|
|
7762
|
-
if (
|
|
7763
|
-
const count = lineCount(
|
|
8015
|
+
if (existsSync19(handoffHistoryPath)) {
|
|
8016
|
+
const count = lineCount(readFileSync7(handoffHistoryPath, "utf-8"));
|
|
7764
8017
|
if (count > 0) {
|
|
7765
8018
|
console.log(chalk17.dim(` Handoff entries: ${count}`));
|
|
7766
8019
|
}
|
|
7767
8020
|
}
|
|
7768
8021
|
const completedPath = join19(cwd, COMPLETED_TASKS_PATH);
|
|
7769
|
-
if (
|
|
7770
|
-
const count = lineCount(
|
|
8022
|
+
if (existsSync19(completedPath)) {
|
|
8023
|
+
const count = lineCount(readFileSync7(completedPath, "utf-8"));
|
|
7771
8024
|
if (count > 0) {
|
|
7772
8025
|
console.log(chalk17.dim(` Completed tasks archived: ${count}`));
|
|
7773
8026
|
}
|
|
@@ -7784,7 +8037,7 @@ function createGovernanceCommand() {
|
|
|
7784
8037
|
return;
|
|
7785
8038
|
}
|
|
7786
8039
|
if (options.raw) {
|
|
7787
|
-
const raw =
|
|
8040
|
+
const raw = readFileSync7(archInfo.path, "utf-8");
|
|
7788
8041
|
console.log(raw.trimEnd());
|
|
7789
8042
|
return;
|
|
7790
8043
|
}
|
|
@@ -7801,7 +8054,7 @@ function createGovernanceCommand() {
|
|
|
7801
8054
|
console.log(result.value);
|
|
7802
8055
|
return;
|
|
7803
8056
|
}
|
|
7804
|
-
const legacyRaw =
|
|
8057
|
+
const legacyRaw = readFileSync7(archInfo.path, "utf-8");
|
|
7805
8058
|
const legacyParsed = matter4(legacyRaw);
|
|
7806
8059
|
const legacyContent = legacyParsed.content.trim();
|
|
7807
8060
|
if (!legacyContent) {
|
|
@@ -7813,7 +8066,7 @@ function createGovernanceCommand() {
|
|
|
7813
8066
|
architecture.command("update").description("Update active architecture with change reason").requiredOption("-f, --file <path>", "Path to new architecture content").requiredOption("-r, --reason <text>", "Reason for the change (required)").option("-b, --by <name>", "Updated by (optional)").action(async (options) => {
|
|
7814
8067
|
const cwd = process.cwd();
|
|
7815
8068
|
const filePath = options.file;
|
|
7816
|
-
if (!
|
|
8069
|
+
if (!existsSync19(filePath)) {
|
|
7817
8070
|
console.log(chalk17.red(`File not found: ${filePath}`));
|
|
7818
8071
|
process.exit(1);
|
|
7819
8072
|
}
|
|
@@ -7885,6 +8138,14 @@ function createGovernanceCommand() {
|
|
|
7885
8138
|
}
|
|
7886
8139
|
console.log("");
|
|
7887
8140
|
});
|
|
8141
|
+
governance.command("sqlite-init").description("Initialize or refresh local governance SQLite DB").option("--db <path>", "Override DB path (default: .archon/governance.db)").action(async (options) => {
|
|
8142
|
+
const cwd = process.cwd();
|
|
8143
|
+
const view = new GovernanceSqliteView({ dbPath: options.db ?? ".archon/governance.db" });
|
|
8144
|
+
view.init(cwd);
|
|
8145
|
+
await view.loadFromDisk(cwd);
|
|
8146
|
+
view.close();
|
|
8147
|
+
console.log(chalk17.green("\u2713 Governance SQLite DB initialized"));
|
|
8148
|
+
});
|
|
7888
8149
|
return governance;
|
|
7889
8150
|
}
|
|
7890
8151
|
|