@digital-lake/lognexus 1.0.0-alpha.0 ā 1.0.0-alpha.4
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 +86 -59
- package/dist/cli.js +271 -88
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts +10 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +109 -0
- package/dist/doctor.js.map +1 -0
- package/dist/index.d.ts +12 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/mcp/prompts.d.ts +30 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js +150 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +25 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +75 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts +22 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +202 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +26 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +197 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/notes/attach.d.ts +20 -0
- package/dist/notes/attach.d.ts.map +1 -0
- package/dist/notes/attach.js +27 -0
- package/dist/notes/attach.js.map +1 -0
- package/dist/notes/notes.d.ts +14 -0
- package/dist/notes/notes.d.ts.map +1 -0
- package/dist/notes/notes.js +82 -0
- package/dist/notes/notes.js.map +1 -0
- package/dist/scaffold.d.ts +7 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +33 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/state/manager.d.ts +9 -0
- package/dist/state/manager.d.ts.map +1 -0
- package/dist/state/manager.js +72 -0
- package/dist/state/manager.js.map +1 -0
- package/dist/state/schema.d.ts +111 -0
- package/dist/state/schema.d.ts.map +1 -0
- package/dist/state/schema.js +31 -0
- package/dist/state/schema.js.map +1 -0
- package/dist/state/sync.d.ts +8 -0
- package/dist/state/sync.d.ts.map +1 -0
- package/dist/state/sync.js +79 -0
- package/dist/state/sync.js.map +1 -0
- package/dist/status.d.ts +9 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +52 -0
- package/dist/status.js.map +1 -0
- package/package.json +7 -4
- package/dist/config/loadConfig.d.ts +0 -36
- package/dist/config/loadConfig.d.ts.map +0 -1
- package/dist/config/loadConfig.js +0 -65
- package/dist/config/loadConfig.js.map +0 -1
- package/dist/providers/deepseek.d.ts +0 -10
- package/dist/providers/deepseek.d.ts.map +0 -1
- package/dist/providers/deepseek.js +0 -13
- package/dist/providers/deepseek.js.map +0 -1
- package/dist/providers/factory.d.ts +0 -4
- package/dist/providers/factory.d.ts.map +0 -1
- package/dist/providers/factory.js +0 -23
- package/dist/providers/factory.js.map +0 -1
- package/dist/providers/gemini.d.ts +0 -17
- package/dist/providers/gemini.d.ts.map +0 -1
- package/dist/providers/gemini.js +0 -105
- package/dist/providers/gemini.js.map +0 -1
- package/dist/providers/openaiCompatible.d.ts +0 -17
- package/dist/providers/openaiCompatible.d.ts.map +0 -1
- package/dist/providers/openaiCompatible.js +0 -100
- package/dist/providers/openaiCompatible.js.map +0 -1
- package/dist/providers/types.d.ts +0 -35
- package/dist/providers/types.d.ts.map +0 -1
- package/dist/providers/types.js +0 -2
- package/dist/providers/types.js.map +0 -1
- package/dist/routing/tierRouter.d.ts +0 -11
- package/dist/routing/tierRouter.d.ts.map +0 -1
- package/dist/routing/tierRouter.js +0 -42
- package/dist/routing/tierRouter.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# LogNexus
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<strong>The Git-Powered
|
|
8
|
+
<strong>The Universal, Git-Powered Context & Rules Framework for Native AI Agents</strong>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
@@ -19,9 +19,11 @@
|
|
|
19
19
|
|
|
20
20
|
## What is LogNexus?
|
|
21
21
|
|
|
22
|
-
As AI coding agents take on
|
|
22
|
+
As AI coding agents take on complex engineering tasks across different IDEs, they suffer from a fundamental failure mode: **cognitive amnesia**. Between conversation resets, context compactations, model handoffs, and unexpected bugs, the *why* behind design decisions, discarded alternatives, and technical discoveries vanishes.
|
|
23
23
|
|
|
24
|
-
**LogNexus transforms Git and GitHub into a persistent, traceable knowledge graph.** It
|
|
24
|
+
**LogNexus transforms Git and GitHub into a persistent, traceable knowledge graph.** It is a **100% generic, model-agnostic and editor-agnostic framework** that operates directly inside your native AI development environments:
|
|
25
|
+
- **Clients:** Claude Code, Cursor, Codex, Google Antigravity, Kimi Code, VS Code, Zed.
|
|
26
|
+
- **Models:** Anthropic Claude (Opus, Sonnet, Haiku), OpenAI (o3, o1, GPT-4o), Google Gemini (2.5/3.8 Pro & Flash), DeepSeek (R1, V3, Chat).
|
|
25
27
|
|
|
26
28
|
```
|
|
27
29
|
Issues (Why & Goals) āāā¶ Branches (Task Scopes) āāā¶ Commits (Context & Diffs) āāā¶ PR (Timeline & Review)
|
|
@@ -29,26 +31,24 @@ Issues (Why & Goals) āāā¶ Branches (Task Scopes) āāā¶ Commits (Context
|
|
|
29
31
|
āāāāāāāāāāāāāāāāāāāāāāāā Git-Backed Knowledge Graph āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
30
32
|
```
|
|
31
33
|
|
|
34
|
+
> **Framework, Not an API Proxy:** LogNexus never intercepts network calls or wraps vendor APIs. Your models remain inside their native IDEs with full access to editor buffers, interactive diff viewers, terminals, MCP servers, and local tools.
|
|
35
|
+
|
|
32
36
|
---
|
|
33
37
|
|
|
34
38
|
## Key Features
|
|
35
39
|
|
|
36
|
-
- **
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
- **Native Multi-Model Routing:**
|
|
40
|
-
- Route planning, PR synthesis, and cross-review to high-reasoning tiers (**Gemini / Claude Opus / DeepSeek Reasoner**).
|
|
41
|
-
- Ingest massive codebases using long-context windows (**Gemini** with 1M tokens).
|
|
42
|
-
- Delegate closed-contract implementation tasks to cost-effective execution engines (**DeepSeek Chat** at marginal cost).
|
|
43
|
-
- **Cross-Model Review Gates:** Enforce non-negotiable review separation (`Authored-by:` vs `Reviewed-by:`). No model merges its own code without independent verification.
|
|
40
|
+
- **Universal Multi-Model Support:** Native cognitive guidelines and prompt specifications for **Anthropic Claude**, **OpenAI**, **Google Gemini**, and **DeepSeek**.
|
|
41
|
+
- **Universal Client Compatibility:** Drop-in support for **Claude Code**, **Cursor**, **Codex**, **Google Antigravity**, and **Kimi Code / VS Code**.
|
|
42
|
+
- **Cross-Model Review Gates:** Non-negotiable review separation (`Authored-by:` vs `Reviewed-by:`). No model merges its own code without independent verification from another model family or version.
|
|
44
43
|
- **Contract-First Subtasks:** Tasks are bounded by strict decision budgets, file allowlists, and stop conditions (`feat(#42/T1)`).
|
|
45
44
|
- **Hidden Metadata Envelopes:** HTML comments preserve machine-parseable state (`<!-- lognexus: kind: state ... -->`) without cluttering human-readable markdown.
|
|
45
|
+
- **Scaffolding & Health CLI (`@digital-lake/lognexus`):** Lightweight scaffolding utility (`npx @digital-lake/lognexus init`) and environment health checking (`doctor`).
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
|
-
##
|
|
49
|
+
## Model-Tier Routing Matrix
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
LogNexus organizes development phases into three cognitive tiers. You can assign any model or native client to any tier according to your team's workflow and cost preferences:
|
|
52
52
|
|
|
53
53
|
<p align="center">
|
|
54
54
|
<img src="docs/assets/multimodel-routing-costs.png" alt="Multi-Model Routing Cost and Performance Analysis" width="85%">
|
|
@@ -56,21 +56,26 @@ Empirical benchmarks and community data demonstrate that routing specialized age
|
|
|
56
56
|
|
|
57
57
|
### Operational Tiers
|
|
58
58
|
|
|
59
|
-
| Tier |
|
|
60
|
-
|
|
61
|
-
| **tier-1 (Reasoning)** |
|
|
62
|
-
| **tier-2 (Context)** | Gemini (1M
|
|
63
|
-
| **tier-3 (Execution)** | DeepSeek Chat |
|
|
64
|
-
|
|
65
|
-
---
|
|
59
|
+
| Tier | Cognitive Role | Anthropic Claude | OpenAI | Google Gemini | DeepSeek | Primary Activities |
|
|
60
|
+
|---|---|---|---|---|---|---|
|
|
61
|
+
| **tier-1 (Reasoning)** | Deep synthesis, architectural design, narrative review | Claude Opus 3.7 / 4.x | o3, o1, GPT-5 | Gemini 2.5 / 3.8 Pro | DeepSeek R1 | Brainstorming-to-issue planning, PR journey timeline synthesis, cross-model review sign-offs. |
|
|
62
|
+
| **tier-2 (Context & Triage)** | Long context ingestion, discovery triage, structured mapping | Claude Sonnet | GPT-4.1, GPT-4o | Gemini Flash / Pro (1M context) | DeepSeek V3 | Large codebase exploration, discovery classification, knowledge retrieval. |
|
|
63
|
+
| **tier-3 (Execution)** | Surgical implementation, template filling, fast execution | Claude Haiku | GPT-4o-mini | Gemini Flash | DeepSeek Chat (V3) | Subtask commits (`feat(#N/Tk)`), atomic code changes under closed contracts, timeline logging. |
|
|
66
64
|
|
|
67
|
-
|
|
65
|
+
### Example Deployment Setups
|
|
68
66
|
|
|
69
|
-
LogNexus
|
|
67
|
+
LogNexus adapts to your existing toolstack. Configure your advisory preferences in `.lognexus/routing.md`:
|
|
70
68
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
```
|
|
70
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
71
|
+
ā POPULAR DEPLOYMENT SETUPS ā
|
|
72
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
|
|
73
|
+
ā Setup A (Anthropic Pure): Claude Opus (t1) + Claude Sonnet (t2) + Claude Haiku (t3) ā
|
|
74
|
+
ā Setup B (Google + DeepSeek): Gemini Pro (t1/t2) in Antigravity + DeepSeek Chat in Kimi ā
|
|
75
|
+
ā Setup C (OpenAI + DeepSeek): OpenAI o3 (t1) in Cursor + DeepSeek Chat (t3) for code ā
|
|
76
|
+
ā Setup D (Claude + OpenAI): Claude Opus (t1) for design + GPT-4o-mini (t3) for tasks ā
|
|
77
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
78
|
+
```
|
|
74
79
|
|
|
75
80
|
---
|
|
76
81
|
|
|
@@ -110,58 +115,79 @@ An independent model inspects the PR diff, verifies task contracts, and signs of
|
|
|
110
115
|
|
|
111
116
|
---
|
|
112
117
|
|
|
113
|
-
## Installation
|
|
118
|
+
## Installation & Setup
|
|
119
|
+
|
|
120
|
+
### 1. Scaffold Rules & Manage State with the CLI
|
|
114
121
|
|
|
115
|
-
|
|
122
|
+
Initialize `.lognexus/` rules, templates, and routing configuration:
|
|
116
123
|
```bash
|
|
117
|
-
|
|
118
|
-
|
|
124
|
+
npx @digital-lake/lognexus init
|
|
125
|
+
```
|
|
119
126
|
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
Verify your environment anytime:
|
|
128
|
+
```bash
|
|
129
|
+
npx @digital-lake/lognexus doctor
|
|
122
130
|
```
|
|
123
131
|
|
|
124
|
-
|
|
132
|
+
Inspect active branch and tier advisory:
|
|
125
133
|
```bash
|
|
126
|
-
npx
|
|
134
|
+
npx @digital-lake/lognexus status
|
|
127
135
|
```
|
|
128
136
|
|
|
129
|
-
|
|
137
|
+
Manage persistent agent state (`.lognexus/state.json`) and session recovery:
|
|
130
138
|
```bash
|
|
131
|
-
|
|
132
|
-
lognexus
|
|
139
|
+
npx @digital-lake/lognexus state sync
|
|
140
|
+
npx @digital-lake/lognexus state show
|
|
141
|
+
npx @digital-lake/lognexus state set-task T1 "Add user schema"
|
|
142
|
+
npx @digital-lake/lognexus state finish-task T1
|
|
133
143
|
```
|
|
134
144
|
|
|
135
|
-
|
|
145
|
+
Quiet Mode with Git Notes (`refs/notes/lognexus`, standard `git-ai` v3):
|
|
146
|
+
```bash
|
|
147
|
+
npx @digital-lake/lognexus note attach HEAD
|
|
148
|
+
npx @digital-lake/lognexus note show HEAD
|
|
149
|
+
npx @digital-lake/lognexus note push origin
|
|
150
|
+
```
|
|
136
151
|
|
|
137
|
-
|
|
152
|
+
### 2. Connect via Model Context Protocol (MCP)
|
|
138
153
|
|
|
139
|
-
|
|
154
|
+
LogNexus includes a native, lightweight JSON-RPC 2.0 stdio server (`lognexus mcp`) with zero external SDK dependencies. Connect it to Claude Desktop, Cursor, Google Antigravity, or any MCP-compliant client:
|
|
140
155
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
156
|
+
**`claude_desktop_config.json` or Cursor MCP settings:**
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"mcpServers": {
|
|
160
|
+
"lognexus": {
|
|
161
|
+
"command": "npx",
|
|
162
|
+
"args": ["-y", "@digital-lake/lognexus", "mcp"]
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
144
167
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
168
|
+
**Exposed Capabilities:**
|
|
169
|
+
- **Tools:** `lognexus_status`, `lognexus_state_get`, `lognexus_state_sync`, `lognexus_state_set_task`, `lognexus_state_finish_task`, `lognexus_state_clear`, `lognexus_note_show`, `lognexus_note_attach`
|
|
170
|
+
- **Resources:** `lognexus://state`, `lognexus://routing`
|
|
171
|
+
- **Prompts:** `lognexus-plan`, `lognexus-review`
|
|
148
172
|
|
|
149
|
-
|
|
150
|
-
export DEEPSEEK_API_KEY="your-api-key"
|
|
151
|
-
export DEEPSEEK_BASE_URL="https://api.deepseek.com"
|
|
152
|
-
export DEEPSEEK_MODEL="deepseek-chat"
|
|
153
|
-
```
|
|
173
|
+
### 3. Install Rules in Your Agent Environment
|
|
154
174
|
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
lognexus
|
|
158
|
-
```
|
|
175
|
+
- **Claude Code:**
|
|
176
|
+
```bash
|
|
177
|
+
claude plugin add digital-lake-ai/lognexus
|
|
178
|
+
```
|
|
179
|
+
- **Cursor / Codex / Agent Skills:**
|
|
180
|
+
```bash
|
|
181
|
+
npx skills add digital-lake-ai/lognexus
|
|
182
|
+
```
|
|
183
|
+
- **Google Antigravity:** Active automatically via `skills/lognexus/SKILL.md` or workspace skills.
|
|
184
|
+
- **Kimi Code / VS Code:** Active via `.lognexus/` workspace instructions and prompts.
|
|
159
185
|
|
|
160
186
|
---
|
|
161
187
|
|
|
162
188
|
## Disambiguation
|
|
163
189
|
|
|
164
|
-
**LogNexus** by Digital Lake is an open-source development
|
|
190
|
+
**LogNexus** by Digital Lake is an open-source development framework and Git memory system for AI agents. It is not affiliated with academic research papers on industrial log compression (e.g. ISSTA 2026).
|
|
165
191
|
|
|
166
192
|
---
|
|
167
193
|
|
|
@@ -169,10 +195,11 @@ lognexus doctor
|
|
|
169
195
|
|
|
170
196
|
LogNexus is an independent hard fork and continuation of [`shiplog`](https://github.com/devallibus/shiplog), originally created by **devallibus** under the MIT License.
|
|
171
197
|
|
|
172
|
-
We extend our deep gratitude to **devallibus** for pioneering the concept of Git-as-knowledge-graph for AI development. LogNexus builds upon that foundation by
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
-
|
|
198
|
+
We extend our deep gratitude to **devallibus** for pioneering the concept of Git-as-knowledge-graph for AI development. LogNexus builds upon that foundation by:
|
|
199
|
+
- Expanding the model ecosystem to provide first-class native support for **Google Gemini** and **DeepSeek** alongside **Claude** and **OpenAI**.
|
|
200
|
+
- Formalizing the multi-model tier routing taxonomy and closed delegation contracts.
|
|
201
|
+
- Introducing the repository scaffolding CLI (`@digital-lake/lognexus`).
|
|
202
|
+
- Providing seamless backwards-compatibility for existing `.shiplog` envelopes and workflows.
|
|
176
203
|
|
|
177
204
|
Additional inspirations and patterns are derived from [OrchestKit](https://github.com/yonatangross/orchestkit) and [Superpowers](https://github.com/obra/superpowers). Detailed license texts are preserved in the [`LICENSES/`](LICENSES/) directory and in [`NOTICE.md`](NOTICE.md).
|
|
178
205
|
|
package/dist/cli.js
CHANGED
|
@@ -1,112 +1,295 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { runDiagnostics } from "./doctor.js";
|
|
3
|
+
import { startMcpServer } from "./mcp/server.js";
|
|
4
|
+
import { attachCurrentStateToCommit } from "./notes/attach.js";
|
|
5
|
+
import { fetchNotes, getNote, listNotes, pushNotes } from "./notes/notes.js";
|
|
6
|
+
import { initProject } from "./scaffold.js";
|
|
7
|
+
import { clearState, finishSubtask, loadState, setSubtask } from "./state/manager.js";
|
|
8
|
+
import { syncStateFromGit } from "./state/sync.js";
|
|
9
|
+
import { getProjectStatus } from "./status.js";
|
|
6
10
|
function printHeader() {
|
|
7
|
-
console.log("\nš· LogNexus CLI
|
|
11
|
+
console.log("\nš· LogNexus CLI ā Digital Lake");
|
|
12
|
+
console.log(" The Universal Git-Powered Context & Rules Framework for Native AI Agents\n");
|
|
8
13
|
}
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
function printUsage() {
|
|
15
|
+
printHeader();
|
|
16
|
+
console.log(`Usage:
|
|
17
|
+
lognexus <command> [subcommand] [options]
|
|
18
|
+
|
|
19
|
+
Commands:
|
|
20
|
+
init Scaffold .lognexus/ configuration and rules in current repository
|
|
21
|
+
doctor Check Git, GitHub CLI authentication, and repository rules health
|
|
22
|
+
status Inspect current branch, active issue, and recommended tier
|
|
23
|
+
state Manage persistent agent state (.lognexus/state.json)
|
|
24
|
+
note Manage Git Notes under refs/notes/lognexus (git-ai standard)
|
|
25
|
+
mcp Start the LogNexus MCP server (stdio JSON-RPC 2.0) for native AI agents
|
|
26
|
+
help Display this help message
|
|
27
|
+
|
|
28
|
+
State Subcommands:
|
|
29
|
+
lognexus state [show] Display current active issue and task state
|
|
30
|
+
lognexus state sync Sync state from current Git branch & GitHub
|
|
31
|
+
lognexus state set-task <id> [t] Set active subtask (e.g. lognexus state set-task T1 "Add schema")
|
|
32
|
+
lognexus state finish-task <id> Mark subtask as completed (e.g. lognexus state finish-task T1)
|
|
33
|
+
lognexus state clear Reset persistent state to empty
|
|
34
|
+
|
|
35
|
+
Note Subcommands:
|
|
36
|
+
lognexus note [show] [commit] Display LogNexus Git Note for commit (default: HEAD)
|
|
37
|
+
lognexus note attach [commit] Attach current session state as Git Note to commit
|
|
38
|
+
lognexus note list List all commits with LogNexus Git Notes
|
|
39
|
+
lognexus note push [remote] Push refs/notes/lognexus to remote (default: origin)
|
|
40
|
+
lognexus note fetch [remote] Fetch refs/notes/lognexus from remote
|
|
41
|
+
|
|
42
|
+
MCP Server:
|
|
43
|
+
lognexus mcp Start MCP server on stdio (JSON-RPC 2.0) for Claude Code,
|
|
44
|
+
Cursor, VS Code, Antigravity or any MCP-compatible client
|
|
45
|
+
Tools: lognexus_status, lognexus_state_get, lognexus_state_sync, lognexus_state_set_task,
|
|
46
|
+
lognexus_state_finish_task, lognexus_state_clear, lognexus_note_show, lognexus_note_attach
|
|
47
|
+
Resources: lognexus://state, lognexus://routing
|
|
48
|
+
Prompts: lognexus-plan, lognexus-review
|
|
49
|
+
|
|
50
|
+
Examples:
|
|
51
|
+
npx @digital-lake/lognexus init
|
|
52
|
+
npx @digital-lake/lognexus state sync
|
|
53
|
+
npx @digital-lake/lognexus note attach HEAD
|
|
54
|
+
npx @digital-lake/lognexus note show HEAD
|
|
55
|
+
npx @digital-lake/lognexus mcp
|
|
56
|
+
`);
|
|
15
57
|
}
|
|
16
|
-
async function
|
|
58
|
+
async function handleInit() {
|
|
17
59
|
printHeader();
|
|
18
|
-
console.log("
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
encoding: "utf-8",
|
|
25
|
-
stdio: ["pipe", "pipe", "ignore"],
|
|
26
|
-
}).trim();
|
|
27
|
-
console.log(`[PASS] Git: ${gitVer} (inside git repository: ${isRepo})`);
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
console.log("[FAIL] Git: Git command failed or not in a git repository");
|
|
31
|
-
}
|
|
32
|
-
// 2. GitHub CLI Check
|
|
33
|
-
try {
|
|
34
|
-
const ghVer = execSync("gh --version", { encoding: "utf-8" }).split("\n")[0];
|
|
35
|
-
console.log(`[PASS] GitHub CLI: ${ghVer}`);
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
console.log("[WARN] GitHub CLI: 'gh' not found in PATH or not installed");
|
|
39
|
-
}
|
|
40
|
-
// 3. Load Configuration
|
|
41
|
-
const config = loadConfig();
|
|
42
|
-
console.log(`\n[INFO] Active Provider Strategy: ${config.provider.toUpperCase()}`);
|
|
43
|
-
console.log(` - Gemini Key: ${redactKey(config.gemini.apiKey)}`);
|
|
44
|
-
console.log(` - Gemini Model: ${config.gemini.model}`);
|
|
45
|
-
console.log(` - DeepSeek Key: ${redactKey(config.deepseek.apiKey)}`);
|
|
46
|
-
console.log(` - DeepSeek Model: ${config.deepseek.model}`);
|
|
47
|
-
// 4. Live Provider Connectivity Check (Optional)
|
|
48
|
-
if (live) {
|
|
49
|
-
console.log("\nTesting live API connectivity...");
|
|
50
|
-
if (config.gemini.apiKey) {
|
|
51
|
-
const gemini = createProvider("gemini", config);
|
|
52
|
-
const health = await gemini.healthCheck();
|
|
53
|
-
console.log(` - Gemini Live: ${health.ok ? "ā
PASS" : "ā FAIL"} ā ${health.message}`);
|
|
60
|
+
console.log("Initializing LogNexus in current repository...\n");
|
|
61
|
+
const res = initProject();
|
|
62
|
+
if (res.created.length > 0) {
|
|
63
|
+
console.log("Created files:");
|
|
64
|
+
for (const f of res.created) {
|
|
65
|
+
console.log(` [+] ${f}`);
|
|
54
66
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
67
|
+
}
|
|
68
|
+
if (res.skipped.length > 0) {
|
|
69
|
+
console.log("Existing files (skipped):");
|
|
70
|
+
for (const f of res.skipped) {
|
|
71
|
+
console.log(` [.] ${f}`);
|
|
59
72
|
}
|
|
60
73
|
}
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
console.log("\nNext Steps:");
|
|
75
|
+
console.log(" ⢠Claude Code / Cursor / Codex / Antigravity / Kimi: use /lognexus plan");
|
|
76
|
+
console.log(" ⢠Configure model tiers in .lognexus/routing.md");
|
|
77
|
+
console.log(" ⢠Verify environment anytime with: npx @digital-lake/lognexus doctor\n");
|
|
78
|
+
}
|
|
79
|
+
async function handleDoctor() {
|
|
80
|
+
printHeader();
|
|
81
|
+
console.log("Running diagnostics...\n");
|
|
82
|
+
const checks = runDiagnostics();
|
|
83
|
+
for (const c of checks) {
|
|
84
|
+
const tag = c.status === "pass" ? "[PASS]" : c.status === "warn" ? "[WARN]" : "[FAIL]";
|
|
85
|
+
console.log(`${tag} ${c.name}: ${c.message}`);
|
|
63
86
|
}
|
|
64
87
|
console.log("\nDiagnostic complete.\n");
|
|
65
88
|
}
|
|
66
|
-
function
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
89
|
+
async function handleStatus() {
|
|
90
|
+
printHeader();
|
|
91
|
+
const st = getProjectStatus();
|
|
92
|
+
console.log(`Git Repository: ${st.isInsideGit ? "Yes" : "No"}`);
|
|
93
|
+
console.log(`Current Branch: ${st.branch}`);
|
|
94
|
+
console.log(`Active Issue: ${st.activeIssue ?? "(none ā on base branch)"}`);
|
|
95
|
+
console.log(`Rules Routing Mode: ${st.routingMode}`);
|
|
96
|
+
console.log(`Recommended Tier: ${st.recommendedTier}\n`);
|
|
97
|
+
}
|
|
98
|
+
async function handleState(args) {
|
|
99
|
+
const sub = args[0]?.toLowerCase() || "show";
|
|
100
|
+
switch (sub) {
|
|
101
|
+
case "show": {
|
|
102
|
+
printHeader();
|
|
103
|
+
const state = loadState();
|
|
104
|
+
console.log("Persistent Agent State (.lognexus/state.json):\n");
|
|
105
|
+
if (state.activeIssue) {
|
|
106
|
+
console.log(`Active Issue: #${state.activeIssue.id} ā ${state.activeIssue.title}`);
|
|
107
|
+
console.log(`Branch: ${state.activeIssue.branch}`);
|
|
108
|
+
console.log(`Phase: ${state.activeIssue.phase}`);
|
|
109
|
+
console.log(`Tier: ${state.activeIssue.tier}`);
|
|
110
|
+
console.log(`Readiness: ${state.activeIssue.readiness}`);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
console.log("Active Issue: (none)");
|
|
114
|
+
}
|
|
115
|
+
console.log("");
|
|
116
|
+
if (state.currentSubtask) {
|
|
117
|
+
console.log(`Current Subtask: ${state.currentSubtask.id} (${state.currentSubtask.status})`);
|
|
118
|
+
if (state.currentSubtask.title) {
|
|
119
|
+
console.log(` Title: ${state.currentSubtask.title}`);
|
|
120
|
+
}
|
|
121
|
+
if (state.currentSubtask.contract) {
|
|
122
|
+
console.log(` Allowed Files: ${state.currentSubtask.contract.allowedFiles.join(", ") || "(all)"}`);
|
|
123
|
+
console.log(` Decision Budget: ${state.currentSubtask.contract.decisionBudget}`);
|
|
124
|
+
if (state.currentSubtask.contract.verificationCmd) {
|
|
125
|
+
console.log(` Verify Command: ${state.currentSubtask.contract.verificationCmd}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
console.log("Current Subtask: (none)");
|
|
131
|
+
}
|
|
132
|
+
console.log(`Completed Tasks: ${state.completedSubtasks.length > 0 ? state.completedSubtasks.join(", ") : "(none)"}`);
|
|
133
|
+
console.log(`Last Synchronized: ${state.lastSync}\n`);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
case "sync": {
|
|
137
|
+
printHeader();
|
|
138
|
+
console.log("Synchronizing state from current Git branch and GitHub...\n");
|
|
139
|
+
const synced = syncStateFromGit();
|
|
140
|
+
if (synced.activeIssue) {
|
|
141
|
+
console.log(`[OK] Synchronized with Issue #${synced.activeIssue.id} (${synced.activeIssue.title})`);
|
|
142
|
+
console.log(` Branch: ${synced.activeIssue.branch}`);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
console.log("[OK] Synchronized. No active issue detected on current branch.");
|
|
146
|
+
}
|
|
147
|
+
console.log("");
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case "set-task": {
|
|
151
|
+
const taskId = args[1];
|
|
152
|
+
const title = args.slice(2).join(" ");
|
|
153
|
+
if (!taskId) {
|
|
154
|
+
console.error("Error: Subtask ID is required (e.g. lognexus state set-task T1 'Add schema')\n");
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
printHeader();
|
|
158
|
+
setSubtask(taskId, title);
|
|
159
|
+
console.log(`[OK] Active subtask set to: ${taskId}${title ? ` ā ${title}` : ""}\n`);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
case "finish-task": {
|
|
163
|
+
const taskId = args[1];
|
|
164
|
+
if (!taskId) {
|
|
165
|
+
console.error("Error: Subtask ID is required (e.g. lognexus state finish-task T1)\n");
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
printHeader();
|
|
169
|
+
finishSubtask(taskId);
|
|
170
|
+
console.log(`[OK] Subtask ${taskId} marked as completed.\n`);
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case "clear": {
|
|
174
|
+
printHeader();
|
|
175
|
+
clearState();
|
|
176
|
+
console.log("[OK] Persistent state cleared.\n");
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
default:
|
|
180
|
+
console.error(`Unknown state subcommand: ${sub}\n`);
|
|
181
|
+
printUsage();
|
|
182
|
+
process.exit(1);
|
|
71
183
|
}
|
|
72
|
-
const tier = tierArg;
|
|
73
|
-
const config = loadConfig();
|
|
74
|
-
const assignment = resolveTier(tier, config);
|
|
75
|
-
console.log(`\nš· LogNexus Tier Route: [${assignment.tier}]`);
|
|
76
|
-
console.log(`Provider: ${assignment.provider.id}`);
|
|
77
|
-
console.log(`Model: ${assignment.model}`);
|
|
78
|
-
console.log(`Purpose: ${assignment.description}\n`);
|
|
79
184
|
}
|
|
80
|
-
function
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
185
|
+
async function handleNote(args) {
|
|
186
|
+
const sub = args[0]?.toLowerCase() || "show";
|
|
187
|
+
switch (sub) {
|
|
188
|
+
case "show": {
|
|
189
|
+
const commit = args[1] || "HEAD";
|
|
190
|
+
printHeader();
|
|
191
|
+
const note = getNote(commit);
|
|
192
|
+
if (note) {
|
|
193
|
+
console.log(`Git Note for commit [${commit}] (refs/notes/lognexus):\n`);
|
|
194
|
+
console.log(note);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
console.log(`No LogNexus note found attached to commit [${commit}].`);
|
|
198
|
+
console.log("Tip: Run 'lognexus note attach' to attach current state to this commit.");
|
|
199
|
+
}
|
|
200
|
+
console.log("");
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
case "attach": {
|
|
204
|
+
const commit = args[1] || "HEAD";
|
|
205
|
+
printHeader();
|
|
206
|
+
const payload = attachCurrentStateToCommit(commit);
|
|
207
|
+
console.log(`[OK] Attached LogNexus note to commit [${commit}] (refs/notes/lognexus):`);
|
|
208
|
+
console.log(` Issue: ${payload.issue ? `#${payload.issue.id} ā ${payload.issue.title}` : "(none)"}`);
|
|
209
|
+
console.log(` Subtask: ${payload.subtask ? `${payload.subtask.id} (${payload.subtask.title})` : "(none)"}`);
|
|
210
|
+
console.log(` Tier: ${payload.tier}\n`);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case "list": {
|
|
214
|
+
printHeader();
|
|
215
|
+
const notes = listNotes();
|
|
216
|
+
console.log(`LogNexus Notes (refs/notes/lognexus) ā ${notes.length} note(s):\n`);
|
|
217
|
+
if (notes.length === 0) {
|
|
218
|
+
console.log("No notes recorded yet.");
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
for (const n of notes) {
|
|
222
|
+
console.log(` ⢠Commit: ${n.commitSha} (blob: ${n.noteBlob})`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
console.log("");
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
case "push": {
|
|
229
|
+
const remote = args[1] || "origin";
|
|
230
|
+
printHeader();
|
|
231
|
+
console.log(`Pushing refs/notes/lognexus to ${remote}...`);
|
|
232
|
+
const ok = pushNotes(remote);
|
|
233
|
+
if (ok) {
|
|
234
|
+
console.log(`[OK] Notes pushed to ${remote} successfully.\n`);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
console.error(`[FAIL] Could not push notes to ${remote}.\n`);
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
case "fetch": {
|
|
242
|
+
const remote = args[1] || "origin";
|
|
243
|
+
printHeader();
|
|
244
|
+
console.log(`Fetching refs/notes/lognexus from ${remote}...`);
|
|
245
|
+
const ok = fetchNotes(remote);
|
|
246
|
+
if (ok) {
|
|
247
|
+
console.log(`[OK] Notes fetched from ${remote} successfully.\n`);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
console.error(`[FAIL] Could not fetch notes from ${remote}.\n`);
|
|
251
|
+
}
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
default:
|
|
255
|
+
console.error(`Unknown note subcommand: ${sub}\n`);
|
|
256
|
+
printUsage();
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
88
259
|
}
|
|
89
260
|
async function main() {
|
|
90
|
-
const
|
|
91
|
-
const
|
|
261
|
+
const args = process.argv.slice(2);
|
|
262
|
+
const command = args[0]?.toLowerCase();
|
|
92
263
|
switch (command) {
|
|
264
|
+
case "init":
|
|
265
|
+
await handleInit();
|
|
266
|
+
break;
|
|
93
267
|
case "doctor":
|
|
94
|
-
await
|
|
268
|
+
await handleDoctor();
|
|
95
269
|
break;
|
|
96
|
-
case "
|
|
97
|
-
|
|
270
|
+
case "status":
|
|
271
|
+
await handleStatus();
|
|
98
272
|
break;
|
|
99
|
-
case "
|
|
100
|
-
|
|
101
|
-
console.log(JSON.stringify({
|
|
102
|
-
...loadConfig(),
|
|
103
|
-
gemini: { ...loadConfig().gemini, apiKey: redactKey(loadConfig().gemini.apiKey) },
|
|
104
|
-
deepseek: { ...loadConfig().deepseek, apiKey: redactKey(loadConfig().deepseek.apiKey) },
|
|
105
|
-
}, null, 2));
|
|
273
|
+
case "state":
|
|
274
|
+
await handleState(args.slice(1));
|
|
106
275
|
break;
|
|
107
|
-
|
|
108
|
-
|
|
276
|
+
case "note":
|
|
277
|
+
await handleNote(args.slice(1));
|
|
109
278
|
break;
|
|
279
|
+
case "mcp":
|
|
280
|
+
// stdout is reserved for JSON-RPC frames: never print the banner here.
|
|
281
|
+
await startMcpServer();
|
|
282
|
+
break;
|
|
283
|
+
case "help":
|
|
284
|
+
case "--help":
|
|
285
|
+
case "-h":
|
|
286
|
+
case undefined:
|
|
287
|
+
printUsage();
|
|
288
|
+
break;
|
|
289
|
+
default:
|
|
290
|
+
console.error(`Unknown command: ${command}\n`);
|
|
291
|
+
printUsage();
|
|
292
|
+
process.exit(1);
|
|
110
293
|
}
|
|
111
294
|
}
|
|
112
295
|
main().catch((err) => {
|