@digital-lake/lognexus 1.0.0 → 1.2.0

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.
Files changed (57) hide show
  1. package/README.md +101 -7
  2. package/dist/audit/audit.d.ts +17 -1
  3. package/dist/audit/audit.d.ts.map +1 -1
  4. package/dist/audit/audit.js +55 -15
  5. package/dist/audit/audit.js.map +1 -1
  6. package/dist/cli.d.ts +1 -0
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +160 -2
  9. package/dist/cli.js.map +1 -1
  10. package/dist/commit.d.ts +27 -0
  11. package/dist/commit.d.ts.map +1 -0
  12. package/dist/commit.js +211 -0
  13. package/dist/commit.js.map +1 -0
  14. package/dist/index.d.ts +4 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +4 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/mcp/tools.d.ts.map +1 -1
  19. package/dist/mcp/tools.js +125 -0
  20. package/dist/mcp/tools.js.map +1 -1
  21. package/dist/notes/attach.d.ts +1 -0
  22. package/dist/notes/attach.d.ts.map +1 -1
  23. package/dist/notes/attach.js +29 -2
  24. package/dist/notes/attach.js.map +1 -1
  25. package/dist/notes/notes.d.ts +1 -0
  26. package/dist/notes/notes.d.ts.map +1 -1
  27. package/dist/notes/notes.js.map +1 -1
  28. package/dist/scaffold.d.ts +1 -1
  29. package/dist/scaffold.d.ts.map +1 -1
  30. package/dist/scaffold.js +4 -4
  31. package/dist/state/manager.d.ts.map +1 -1
  32. package/dist/state/manager.js +11 -1
  33. package/dist/state/manager.js.map +1 -1
  34. package/dist/telemetry/collector.d.ts +31 -0
  35. package/dist/telemetry/collector.d.ts.map +1 -0
  36. package/dist/telemetry/collector.js +257 -0
  37. package/dist/telemetry/collector.js.map +1 -0
  38. package/dist/telemetry/detector.d.ts +15 -0
  39. package/dist/telemetry/detector.d.ts.map +1 -0
  40. package/dist/telemetry/detector.js +120 -0
  41. package/dist/telemetry/detector.js.map +1 -0
  42. package/dist/telemetry/index.d.ts +5 -0
  43. package/dist/telemetry/index.d.ts.map +1 -0
  44. package/dist/telemetry/index.js +5 -0
  45. package/dist/telemetry/index.js.map +1 -0
  46. package/dist/telemetry/report.d.ts +7 -0
  47. package/dist/telemetry/report.d.ts.map +1 -0
  48. package/dist/telemetry/report.js +98 -0
  49. package/dist/telemetry/report.js.map +1 -0
  50. package/dist/telemetry/schema.d.ts +140 -0
  51. package/dist/telemetry/schema.d.ts.map +1 -0
  52. package/dist/telemetry/schema.js +78 -0
  53. package/dist/telemetry/schema.js.map +1 -0
  54. package/dist/timeline/timeline.d.ts.map +1 -1
  55. package/dist/timeline/timeline.js +8 -3
  56. package/dist/timeline/timeline.js.map +1 -1
  57. package/package.json +16 -5
package/README.md CHANGED
@@ -13,6 +13,7 @@
13
13
  <a href="https://www.npmjs.com/package/@digital-lake/lognexus"><img src="https://img.shields.io/npm/v/@digital-lake/lognexus.svg?color=blue" alt="npm version"></a>
14
14
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
15
15
  <a href="https://github.com/digital-lake-ai/lognexus"><img src="https://img.shields.io/badge/org-Digital%20Lake-indigo.svg" alt="Digital Lake"></a>
16
+ <a href="https://ko-fi.com/digitallake"><img src="https://img.shields.io/badge/Ko--fi-Fuel_the_AI-ff5e5b?logo=ko-fi&logoColor=white" alt="Ko-fi - Fuel the AI"></a>
16
17
  </p>
17
18
 
18
19
  ---
@@ -37,11 +38,12 @@ Issues (Why & Goals) ──▶ Branches (Task Scopes) ──▶ Commits (Context
37
38
 
38
39
  ## Key Features
39
40
 
40
- - **Universal Multi-Model Support:** Native cognitive guidelines and prompt specifications for **Anthropic Claude**, **OpenAI**, **Google Gemini**, and **DeepSeek**.
41
+ - **Universal Multi-Model Support:** Native cognitive guidelines and prompt specifications for **Anthropic Claude**, **OpenAI**, **Google Gemini**, **DeepSeek**, and **Kimi K2.7 Code**.
41
42
  - **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.
43
- - **Contract-First Subtasks:** Tasks are bounded by strict decision budgets, file allowlists, and stop conditions (`feat(#42/T1)`).
44
- - **Persistent State & Session Recovery:** Local session state engine (`.lognexus/state.json`) prevents amnesia across context compactations and conversation resets.
43
+ - **Atomic Commit Engine (`lognexus commit` & MCP `lognexus_commit`):** Validates subtask file contracts, verifies reviewer separation, injects authorship trailers, commits changes, marks subtasks completed, and attaches Git Notes in a single ~0.15s execution.
44
+ - **Cross-Model Review Gates:** Non-negotiable review separation (`Authored-by:` vs `Reviewed-by:`) enforced both at pre-flight note attachment time and during branch audits. No model merges its own code without independent verification from another model family.
45
+ - **Contract-First Subtasks & Alphanumeric Tickets:** Tasks are bounded by strict decision budgets, file allowlists, and stop conditions—supporting both GitHub issues (`feat(#42/T1)`) and Jira/Linear ticket schemes (`feat(SLM-201/T1)`).
46
+ - **Persistent State & Session Recovery:** Local session state engine (`.lognexus/state.json`) prevents amnesia across context compactations and conversation resets, retaining completed subtask metadata through the closing commit.
45
47
  - **Git Notes Engine (Quiet Mode / `git-ai` v3):** Attaches structured session payloads and contracts to commits under `refs/notes/lognexus` without changing commit SHAs.
46
48
  - **Native MCP Stdio Server (`lognexus mcp`):** Zero-dependency JSON-RPC 2.0 stdio server exposing LogNexus tools, live state resources, and prompts to Claude Desktop, Cursor, and any MCP client.
47
49
  - **Journey Timeline & Review Gate Audit:** Reconstructs the complete branch journey into structured PR descriptions (`lognexus timeline --pr-body`) and programmatically audits review gate separation (`lognexus audit`).
@@ -146,6 +148,17 @@ npx @digital-lake/lognexus state set-task T1 "Add user schema"
146
148
  npx @digital-lake/lognexus state finish-task T1
147
149
  ```
148
150
 
151
+ Execute an **Atomic Commit** (validates subtask contract, enforces review-gate separation, injects trailers, commits, marks subtask completed, and attaches Git Note in a single ~0.15s call):
152
+ ```bash
153
+ npx @digital-lake/lognexus commit -m "feat(#42/T1): add user schema" \
154
+ --author "gemini/flash (antigravity)" \
155
+ --reviewer "gemini/pro (lead-architect)" \
156
+ --finish-task
157
+
158
+ # Or read message from file (safe against Windows shell quote-stripping):
159
+ npx @digital-lake/lognexus commit -F commit-msg.txt --finish-task
160
+ ```
161
+
149
162
  Quiet Mode with Git Notes (`refs/notes/lognexus`, standard `git-ai` v3):
150
163
  ```bash
151
164
  npx @digital-lake/lognexus note attach HEAD
@@ -160,6 +173,28 @@ npx @digital-lake/lognexus timeline main --pr-body
160
173
  npx @digital-lake/lognexus audit main
161
174
  ```
162
175
 
176
+ Opt-in Telemetry, Stack Profiling & ROI Cost-Savings Engine:
177
+ ```bash
178
+ # Check telemetry status (disabled by default, 0% overhead)
179
+ npx @digital-lake/lognexus telemetry status
180
+
181
+ # Enable local telemetry (stores metrics only in .lognexus/telemetry.json)
182
+ npx @digital-lake/lognexus telemetry enable
183
+
184
+ # Or enable anonymous community telemetry (explicit GDPR opt-in)
185
+ npx @digital-lake/lognexus telemetry enable --share --accept-terms
186
+
187
+ # Generate .lognexus/telemetry.md report with ROI metrics
188
+ npx @digital-lake/lognexus telemetry report
189
+
190
+ # Inspect the exact Zero-PII payload before sending
191
+ npx @digital-lake/lognexus telemetry inspect
192
+
193
+ # Disable telemetry immediately
194
+ npx @digital-lake/lognexus telemetry disable
195
+ ```
196
+ *Read our strict Zero-PII policy in [`docs/TELEMETRY_PRIVACY.md`](docs/TELEMETRY_PRIVACY.md).*
197
+
163
198
  ### 2. Connect via Model Context Protocol (MCP)
164
199
 
165
200
  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:
@@ -176,8 +211,13 @@ LogNexus includes a native, lightweight JSON-RPC 2.0 stdio server (`lognexus mcp
176
211
  }
177
212
  ```
178
213
 
214
+ **Or install automatically via Smithery:**
215
+ ```bash
216
+ npx -y @smithery/cli install @digital-lake/lognexus --client claude
217
+ ```
218
+
179
219
  **Exposed Capabilities:**
180
- - **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`, `lognexus_timeline`, `lognexus_audit`
220
+ - **Tools:** `lognexus_status`, `lognexus_state_get`, `lognexus_state_sync`, `lognexus_state_set_task`, `lognexus_state_finish_task`, `lognexus_state_clear`, `lognexus_commit`, `lognexus_note_show`, `lognexus_note_attach`, `lognexus_timeline`, `lognexus_audit`, `lognexus_telemetry`
181
221
  - **Resources:** `lognexus://state`, `lognexus://routing`
182
222
  - **Prompts:** `lognexus-plan`, `lognexus-review`
183
223
 
@@ -196,6 +236,44 @@ LogNexus includes a native, lightweight JSON-RPC 2.0 stdio server (`lognexus mcp
196
236
 
197
237
  ---
198
238
 
239
+ ## ⚡ Production Telemetry & Field Benchmark
240
+
241
+ <div align="center">
242
+
243
+ ![Corpus Analyzed](https://img.shields.io/badge/CORPUS_GOVERNED-250%2C000%2B_LOC-0e7490?style=for-the-badge&labelColor=0d1117)
244
+ ![Git Notes Coverage](https://img.shields.io/badge/GIT_NOTES_COVERAGE-100%25_(38%2F38)-238636?style=for-the-badge&labelColor=0d1117)
245
+ ![Traceability Audit](https://img.shields.io/badge/REVIEW_GATE_AUDIT-100%25_PASS-6e40c9?style=for-the-badge&labelColor=0d1117)
246
+ ![Test Suite Health](https://img.shields.io/badge/UNIT_TESTS-536_PASSED_(0_WARN)-238636?style=for-the-badge&labelColor=0d1117)
247
+
248
+ </div>
249
+
250
+ LogNexus was battle-tested in a high-intensity production deployment governing the end-to-end engineering of **Taranis**—a deterministic static analysis CLI and AI migration skill operating over **250,000+ lines of legacy code** with 22 AST/CFG rules (`SPH-001`..`SPH-022`).
251
+
252
+ ```
253
+ ╔══════════════════════════════════════════════════════════════════════════════════════════════╗
254
+ ║ LOGNEXUS TELEMETRY HUD // PRODUCTION SWARM BENCHMARK (CASE STUDY: TARANIS) ║
255
+ ╠═════════════════════════════════════════════╦════════════════════════════════════════════════╣
256
+ ║ ▸ GOVERNED FEATURES 12 Issues (#1-#12) ║ ▸ ORPHAN / UNTRACKED COMMITS 0 (0.0%) ║
257
+ ║ ▸ VERIFIED COMMITS 38 / 38 Signed ║ ▸ SELF-APPROVAL VIOLATIONS 0 Blocked ║
258
+ ║ ▸ GIT NOTES ATTACHED 100% (git-ai v3) ║ ▸ SCOPE CREEP INCIDENTS 0 (Allowlist) ║
259
+ ║ ▸ TEST SUITE INTEGRITY 536 Passed (100%) ║ ▸ ATOMIC COMMIT LATENCY ~0.15s / op ║
260
+ ╚═════════════════════════════════════════════╩════════════════════════════════════════════════╝
261
+ ```
262
+
263
+ ### Multi-Model Swarm Performance Matrix
264
+
265
+ By enforcing **Closed Delegation Contracts** (`allowedFiles`, `forbiddenFiles`, `decisionBudget: "none"`) and **Cross-Model Review Gates**, LogNexus coordinated three distinct AI model families in production without a single context leak or rogue commit:
266
+
267
+ | Model Family | Assigned Tier | Production Strengths Observed | Optimal Contract Fit |
268
+ | :--- | :---: | :--- | :--- |
269
+ | **Google Antigravity / Gemini Pro** | `tier-1` & `tier-2`<br>*(Architect & Orchestrator)* | • Zero-drift multi-branch coordination<br>• Strict review-gate enforcement (`lognexus audit`)<br>• Rapid root-cause regression triage | Architecture synthesis, closed contract authoring, cross-model code review, release governance. |
270
+ | **DeepSeek V3 / R1** | `tier-3`<br>*(Scoped Implementer)* | • Ultra-low latency & token cost<br>• Exceptional at mathematical AST parsing, pushdown automata & CFG tokenization<br>• Strict adherence to stop conditions when hitting out-of-scope test assertions | Algorithmic engines, deterministic parsers, isolated single-file modules (`<500` LOC). |
271
+ | **Kimi K2.7 Code** | `tier-2` & `tier-3`<br>*(High-Context Implementer)* | • Massive context retention with zero file truncation on large modules (`>500` LOC)<br>• Flawless single-shot multi-file generation (rule catalogs + visitors + test suites) | Large-context refactorings, multi-file rule catalogs, CI/CD matrices & standalone packaging. |
272
+
273
+ > **Key Takeaway:** Contract-driven development paired with `refs/notes/lognexus` completely eliminated scope creep by Tier-3 implementers while keeping the public Git commit graph 100% clean and human-readable.
274
+
275
+ ---
276
+
199
277
  ## Disambiguation
200
278
 
201
279
  **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).
@@ -207,15 +285,31 @@ LogNexus includes a native, lightweight JSON-RPC 2.0 stdio server (`lognexus mcp
207
285
  LogNexus is an independent hard fork and continuation of [`shiplog`](https://github.com/devallibus/shiplog), originally created by **devallibus** under the MIT License.
208
286
 
209
287
  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:
210
- - Expanding the model ecosystem to provide first-class native support for **Google Gemini** and **DeepSeek** alongside **Claude** and **OpenAI**.
288
+ - Expanding the model ecosystem to provide first-class native support for **Google Gemini**, **DeepSeek**, and **Kimi** alongside **Claude** and **OpenAI**.
211
289
  - Formalizing the multi-model tier routing taxonomy and closed delegation contracts.
212
- - Introducing the repository scaffolding CLI (`@digital-lake/lognexus`).
290
+ - Introducing the repository scaffolding CLI, Atomic Commit Engine, and native MCP server (`@digital-lake/lognexus`).
213
291
  - Providing seamless backwards-compatibility for existing `.shiplog` envelopes and workflows.
214
292
 
215
293
  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).
216
294
 
217
295
  ---
218
296
 
297
+ <div align="center">
298
+
299
+ ### Did you find this project useful? 🤖⚡
300
+
301
+ Maintaining and evolving open-source agentic infrastructure takes time, dedication, and... quite a few **AI tokens** to power multi-model benchmarking, automated testing, and continuous architecture updates.
302
+
303
+ If **LogNexus** saved you time, prevented context amnesia in your workflows, and you'd like to help cover the API and compute costs to keep it evolving, consider fueling the AI with a token:
304
+
305
+ [![Ko-fi - Fuel the AI](https://img.shields.io/badge/Ko--fi-Fuel_the_AI-ff5e5b?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/digitallake)
306
+
307
+ *Every contribution goes straight into compute power, multi-model benchmarks, new MCP capabilities, and continuous improvements!*
308
+
309
+ </div>
310
+
311
+ ---
312
+
219
313
  ## License
220
314
 
221
315
  LogNexus is released under the [MIT License](LICENSE).
@@ -1,7 +1,7 @@
1
1
  export interface AuditViolation {
2
2
  commitSha: string;
3
3
  shortSha: string;
4
- rule: "commit-format" | "authored-by-trailer" | "git-note-presence" | "contract-files" | "review-gate-separation";
4
+ rule: "commit-format" | "authored-by-trailer" | "git-note-presence" | "contract-files" | "review-gate-separation" | "base-branch-range";
5
5
  message: string;
6
6
  severity: "error" | "warn";
7
7
  }
@@ -14,6 +14,22 @@ export interface AuditResult {
14
14
  warnings: number;
15
15
  };
16
16
  }
17
+ export declare const TICKET_PATTERN_SOURCE = "(?:#\\d+|[A-Z][A-Z0-9]*-\\d+)";
18
+ export declare const COMMIT_FORMAT_PATTERN: RegExp;
19
+ export declare const SUBJECT_TASK_PATTERN: RegExp;
20
+ export interface Identity {
21
+ full: string;
22
+ family: string;
23
+ }
24
+ export declare function parseIdentity(value: string | null): Identity | null;
25
+ export declare function extractTrailers(commitBody: string): {
26
+ author: string | null;
27
+ reviewer: string | null;
28
+ };
29
+ export declare function checkSelfApproval(authorStr: string | null, reviewerStr: string | null): {
30
+ isSelfApproval: boolean;
31
+ message?: string;
32
+ };
17
33
  export declare function auditBranch(baseBranch?: string, targetDir?: string): AuditResult;
18
34
  export declare function formatAuditResult(result: AuditResult): string;
19
35
  //# sourceMappingURL=audit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/audit/audit.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EACA,eAAe,GACf,qBAAqB,GACrB,mBAAmB,GACnB,gBAAgB,GAChB,wBAAwB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAgLD,wBAAgB,WAAW,CACzB,UAAU,GAAE,MAAe,EAC3B,SAAS,GAAE,MAAsB,GAChC,WAAW,CAab;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAW7D"}
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/audit/audit.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EACA,eAAe,GACf,qBAAqB,GACrB,mBAAmB,GACnB,gBAAgB,GAChB,wBAAwB,GACxB,mBAAmB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAGD,eAAO,MAAM,qBAAqB,kCAAkC,CAAC;AACrE,eAAO,MAAM,qBAAqB,QAEjC,CAAC;AACF,eAAO,MAAM,oBAAoB,QAGhC,CAAC;AAaF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,CAUnE;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG;IACnD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAiBA;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB;IAAE,cAAc,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAc/C;AA4ID,wBAAgB,WAAW,CACzB,UAAU,GAAE,MAAe,EAC3B,SAAS,GAAE,MAAsB,GAChC,WAAW,CAyBb;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAW7D"}
@@ -2,10 +2,12 @@ import { execSync } from "node:child_process";
2
2
  import { getNote } from "../notes/notes.js";
3
3
  import { getJourneyTimeline } from "../timeline/timeline.js";
4
4
  const VALID_TYPES = "feat, fix, docs, refactor, test, chore, style, perf";
5
- const COMMIT_FORMAT_PATTERN = /^(feat|fix|docs|refactor|test|chore|style|perf)\(#\d+(\/T\d+(?:-T?\d+)?)?\): \S+/;
6
- const SUBJECT_TASK_PATTERN = /\(#\d+\/(T\d+(?:-T?\d+)?)\)/i;
5
+ export const TICKET_PATTERN_SOURCE = "(?:#\\d+|[A-Z][A-Z0-9]*-\\d+)";
6
+ export const COMMIT_FORMAT_PATTERN = new RegExp(`^(feat|fix|docs|refactor|test|chore|style|perf)\\(${TICKET_PATTERN_SOURCE}(\\/T\\d+(?:-T?\\d+)?)?\\): \\S+`);
7
+ export const SUBJECT_TASK_PATTERN = new RegExp(`\\(${TICKET_PATTERN_SOURCE}\\/(T\\d+(?:-T?\\d+)?)\\)`, "i");
7
8
  const IDENTITY_PATTERN = /(\S+\/\S+)/;
8
- function parseIdentity(value) {
9
+ const TRAILER_PATTERN = /^\s*(Authored-by|Reviewed-by|Last-code-by|Updated-by):\s*(.+)$/gim;
10
+ export function parseIdentity(value) {
9
11
  if (value === null)
10
12
  return null;
11
13
  const match = value.match(IDENTITY_PATTERN);
@@ -15,6 +17,36 @@ function parseIdentity(value) {
15
17
  }
16
18
  return { full: value.trim().toLowerCase(), family: match[1].toLowerCase() };
17
19
  }
20
+ export function extractTrailers(commitBody) {
21
+ let author = null;
22
+ let reviewer = null;
23
+ for (const match of commitBody.matchAll(TRAILER_PATTERN)) {
24
+ const key = match[1].toLowerCase();
25
+ const value = match[2].trim();
26
+ if (value === "")
27
+ continue;
28
+ if (key === "authored-by") {
29
+ author = value;
30
+ }
31
+ else if (key === "reviewed-by") {
32
+ reviewer = value;
33
+ }
34
+ }
35
+ return { author, reviewer };
36
+ }
37
+ export function checkSelfApproval(authorStr, reviewerStr) {
38
+ const author = parseIdentity(authorStr);
39
+ const reviewer = parseIdentity(reviewerStr);
40
+ if (author !== null && reviewer !== null) {
41
+ if (author.full === reviewer.full || author.family === reviewer.family) {
42
+ return {
43
+ isSelfApproval: true,
44
+ message: `Self-approval detected: author '${authorStr}' and reviewer '${reviewerStr}' share the same identity or model family ('${author.family}').`,
45
+ };
46
+ }
47
+ }
48
+ return { isSelfApproval: false };
49
+ }
18
50
  function normalizePath(value) {
19
51
  return value.replace(/\\/g, "/").replace(/^\.\//, "").trim();
20
52
  }
@@ -76,18 +108,15 @@ function auditCommit(item, targetDir) {
76
108
  severity: "error",
77
109
  });
78
110
  }
79
- const authorIdentity = parseIdentity(item.author);
80
- const reviewerIdentity = parseIdentity(item.reviewer);
81
- if (authorIdentity !== null && reviewerIdentity !== null) {
82
- if (authorIdentity.full === reviewerIdentity.full ||
83
- authorIdentity.family === reviewerIdentity.family) {
84
- violations.push({
85
- ...base,
86
- rule: "review-gate-separation",
87
- message: `Self-approval detected: author '${item.author}' and reviewer '${item.reviewer}' share the same identity.`,
88
- severity: "error",
89
- });
90
- }
111
+ const selfApprovalCheck = checkSelfApproval(item.author, item.reviewer);
112
+ if (selfApprovalCheck.isSelfApproval) {
113
+ violations.push({
114
+ ...base,
115
+ rule: "review-gate-separation",
116
+ message: selfApprovalCheck.message ??
117
+ `Self-approval detected: author '${item.author}' and reviewer '${item.reviewer}' share the same identity.`,
118
+ severity: "error",
119
+ });
91
120
  }
92
121
  const note = getNote(item.sha, { cwd: targetDir });
93
122
  if (note === null) {
@@ -145,6 +174,17 @@ function auditCommit(item, targetDir) {
145
174
  export function auditBranch(baseBranch = "main", targetDir = process.cwd()) {
146
175
  const timeline = getJourneyTimeline(baseBranch, targetDir);
147
176
  const violations = timeline.items.flatMap((item) => auditCommit(item, targetDir));
177
+ const normalizedCurrent = timeline.branch.replace(/^refs\/heads\//, "");
178
+ const normalizedBase = baseBranch.replace(/^refs\/heads\//, "").replace(/^origin\//, "");
179
+ if (normalizedCurrent === normalizedBase && timeline.commitCount === 0) {
180
+ violations.push({
181
+ commitSha: "HEAD",
182
+ shortSha: "HEAD",
183
+ rule: "base-branch-range",
184
+ message: `Auditing base branch '${baseBranch}' directly: 0 commits in range ${baseBranch}..${timeline.branch}. Run from a feature branch or specify a base commit/range.`,
185
+ severity: "error",
186
+ });
187
+ }
148
188
  const errors = violations.filter((violation) => violation.severity === "error").length;
149
189
  const warnings = violations.length - errors;
150
190
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/audit/audit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/audit/audit.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env node
2
+ export { type ParsedCommitArgs, parseCommitArgs } from "./commit.js";
2
3
  export declare function getCliVersion(): string;
3
4
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAkBA,wBAAgB,aAAa,IAAI,MAAM,CAWtC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA4BA,OAAO,EAAE,KAAK,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAErE,wBAAgB,aAAa,IAAI,MAAM,CAWtC"}
package/dist/cli.js CHANGED
@@ -3,6 +3,7 @@ import { existsSync, readFileSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { auditBranch, formatAuditResult } from "./audit/audit.js";
6
+ import { executeAtomicCommit, parseCommitArgs } from "./commit.js";
6
7
  import { runDiagnostics } from "./doctor.js";
7
8
  import { startMcpServer } from "./mcp/server.js";
8
9
  import { attachCurrentStateToCommit } from "./notes/attach.js";
@@ -11,8 +12,11 @@ import { initProject } from "./scaffold.js";
11
12
  import { clearState, finishSubtask, loadState, setSubtask } from "./state/manager.js";
12
13
  import { syncStateFromGit } from "./state/sync.js";
13
14
  import { getProjectStatus } from "./status.js";
15
+ import { buildAnonymousCommunityPayload, clearTelemetry, disableTelemetry, enableTelemetry, isTelemetryGloballyDisabled, loadTelemetry, } from "./telemetry/collector.js";
16
+ import { generateTelemetryReportFile } from "./telemetry/report.js";
14
17
  import { getJourneyTimeline } from "./timeline/timeline.js";
15
18
  const __cliDir = dirname(fileURLToPath(import.meta.url));
19
+ export { parseCommitArgs } from "./commit.js";
16
20
  export function getCliVersion() {
17
21
  try {
18
22
  const pkgPath = join(__cliDir, "..", "package.json");
@@ -25,7 +29,7 @@ export function getCliVersion() {
25
29
  catch {
26
30
  // fallback
27
31
  }
28
- return "1.0.0";
32
+ return "1.2.0";
29
33
  }
30
34
  function printHeader() {
31
35
  console.log("\n🔷 LogNexus CLI — Digital Lake");
@@ -40,14 +44,36 @@ Commands:
40
44
  init Scaffold .lognexus/ configuration and rules in current repository
41
45
  doctor Check Git, GitHub CLI authentication, and repository rules health
42
46
  status Inspect current branch, active issue, and recommended tier
47
+ commit Atomic commit with trailers, contract validation, and Git Note
43
48
  state Manage persistent agent state (.lognexus/state.json)
44
49
  note Manage Git Notes under refs/notes/lognexus (git-ai standard)
45
50
  timeline Reconstruct the branch Journey Timeline and draft a PR body
46
51
  audit Audit commit conventions, authorship trailers and review gate
52
+ telemetry Opt-in performance monitoring, stack profiler and ROI report
47
53
  mcp Start the LogNexus MCP server (stdio JSON-RPC 2.0) for native AI agents
48
54
  version, -v Display the version of LogNexus
49
55
  help, -h Display this help message
50
56
 
57
+ Telemetry Subcommands:
58
+ lognexus telemetry [status] Show current telemetry mode and project metrics
59
+ lognexus telemetry enable Enable local telemetry (zero network calls)
60
+ lognexus telemetry enable --share --accept-terms
61
+ Enable anonymous community telemetry (GDPR opt-in)
62
+ lognexus telemetry inspect Inspect the exact Zero-PII payload before sending
63
+ lognexus telemetry report [-o f] Generate .lognexus/telemetry.md report with ROI metrics
64
+ lognexus telemetry disable Disable all telemetry immediately
65
+ lognexus telemetry clear Reset local telemetry store
66
+
67
+ Commit Command:
68
+ lognexus commit -m "<msg>" [options]
69
+ lognexus commit -F <file> [options]
70
+ -m, --message "<msg>" Commit message (e.g. feat(#15/T1): add feature)
71
+ -F, --file <file> Read commit message from file
72
+ --author "<identity>" Author trailer (e.g. gemini/flash (antigravity))
73
+ --reviewer "<identity>" Optional reviewer trailer (e.g. gemini/pro)
74
+ --finish-task Mark active subtask as completed in state
75
+ --allow-empty Allow creating empty commits
76
+
51
77
  State Subcommands:
52
78
  lognexus state [show] Display current active issue and task state
53
79
  lognexus state sync Sync state from current Git branch & GitHub
@@ -106,8 +132,9 @@ async function handleInit() {
106
132
  }
107
133
  }
108
134
  console.log("\nNext Steps:");
109
- console.log(" • Claude Code / Cursor / Codex / Antigravity / Kimi: use /lognexus plan");
135
+ console.log(" • Claude Code / Cursor / Codex / Antigravity / Gemini / Kimi: use /lognexus plan");
110
136
  console.log(" • Configure model tiers in .lognexus/routing.md");
137
+ console.log(" • Tip: install locally with 'npm i -D @digital-lake/lognexus' for instant execution (~0.15s)");
111
138
  console.log(" • Verify environment anytime with: npx @digital-lake/lognexus doctor\n");
112
139
  }
113
140
  async function handleDoctor() {
@@ -343,10 +370,141 @@ async function handleAudit(args) {
343
370
  process.exit(1);
344
371
  }
345
372
  }
373
+ async function handleCommit(args) {
374
+ let parsed;
375
+ try {
376
+ parsed = parseCommitArgs(args);
377
+ }
378
+ catch (err) {
379
+ const msg = err instanceof Error ? err.message : String(err);
380
+ console.error(`Error: ${msg}\n`);
381
+ printUsage();
382
+ process.exit(1);
383
+ }
384
+ if (!parsed.message) {
385
+ console.error("Error: Commit message is required (e.g. lognexus commit -m 'feat(#15/T1): add feature' or -F <file>)\n");
386
+ printUsage();
387
+ process.exit(1);
388
+ }
389
+ printHeader();
390
+ try {
391
+ const res = executeAtomicCommit({
392
+ message: parsed.message,
393
+ author: parsed.author,
394
+ reviewer: parsed.reviewer,
395
+ finishTask: parsed.finishTask,
396
+ allowEmpty: parsed.allowEmpty,
397
+ });
398
+ console.log(`[OK] Committed [${res.shortSha}] ${res.subject}`);
399
+ console.log(` Authored-by: ${res.author}`);
400
+ if (res.reviewer) {
401
+ console.log(` Reviewed-by: ${res.reviewer}`);
402
+ }
403
+ if (res.subtaskCompleted) {
404
+ console.log(` Subtask: ${res.subtaskCompleted} (marked completed)`);
405
+ }
406
+ console.log(" Git Note: Attached to HEAD (refs/notes/lognexus)\n");
407
+ }
408
+ catch (err) {
409
+ const msg = err instanceof Error ? err.message : String(err);
410
+ console.error(`[FAIL] Commit failed: ${msg}\n`);
411
+ process.exit(1);
412
+ }
413
+ }
414
+ async function handleTelemetry(args) {
415
+ const sub = args[0]?.toLowerCase() || "status";
416
+ switch (sub) {
417
+ case "status": {
418
+ printHeader();
419
+ const store = loadTelemetry();
420
+ const globallyDisabled = isTelemetryGloballyDisabled();
421
+ console.log("LogNexus Telemetry Status:\n");
422
+ console.log(` Globally Disabled (DO_NOT_TRACK): ${globallyDisabled ? "Yes (Forced OFF)" : "No"}`);
423
+ console.log(` Operating Mode: ${store.mode.toUpperCase()}`);
424
+ console.log(` Anonymous Project ID: ${store.anonymousProjectId}`);
425
+ console.log(` Community Consent: ${store.consent.accepted ? "Accepted (Shared)" : "No (Local Only)"}`);
426
+ if (store.consent.acceptedAt) {
427
+ console.log(` Consent Recorded At: ${store.consent.acceptedAt}`);
428
+ }
429
+ console.log(` Detected Stacks: ${store.detectedStacks.join(", ") || "(none)"}`);
430
+ console.log(` Total Commits Monitored: ${store.summary.totalCommits}`);
431
+ console.log(` Estimated Cost Savings: ${store.summary.estimatedCostSavingsPct}%\n`);
432
+ break;
433
+ }
434
+ case "enable": {
435
+ printHeader();
436
+ const share = args.includes("--share");
437
+ const acceptTerms = args.includes("--accept-terms");
438
+ try {
439
+ const res = enableTelemetry({ share, acceptTerms });
440
+ if (res.mode === "community") {
441
+ console.log("[OK] Telemetry enabled in COMMUNITY mode.");
442
+ console.log(" Terms accepted. Anonymous non-sensitive metrics will help mature MCP & routing.");
443
+ console.log(" Full policy & payload schema: docs/TELEMETRY_PRIVACY.md\n");
444
+ }
445
+ else {
446
+ console.log("[OK] Telemetry enabled in LOCAL mode.");
447
+ console.log(" Metrics are stored strictly locally in .lognexus/telemetry.json.");
448
+ console.log(" Zero network calls are made. Run 'lognexus telemetry report' to generate a report.\n");
449
+ }
450
+ }
451
+ catch (err) {
452
+ const msg = err instanceof Error ? err.message : String(err);
453
+ console.error(`[FAIL] ${msg}\n`);
454
+ process.exit(1);
455
+ }
456
+ break;
457
+ }
458
+ case "disable": {
459
+ printHeader();
460
+ disableTelemetry();
461
+ console.log("[OK] Telemetry disabled. Zero metrics will be recorded or transmitted.\n");
462
+ break;
463
+ }
464
+ case "inspect": {
465
+ printHeader();
466
+ const store = loadTelemetry();
467
+ const payload = buildAnonymousCommunityPayload(store);
468
+ console.log("Anonymous Telemetry Payload (Zero-PII Audit):\n");
469
+ console.log(JSON.stringify(payload, null, 2));
470
+ console.log("\nNote: No code, file paths, file names, commit messages, or identities are included.\n");
471
+ break;
472
+ }
473
+ case "report": {
474
+ printHeader();
475
+ let outputPath;
476
+ const outIdx = args.findIndex((a) => a === "--output" || a === "-o");
477
+ if (outIdx !== -1 && args[outIdx + 1]) {
478
+ outputPath = args[outIdx + 1];
479
+ }
480
+ const res = generateTelemetryReportFile(process.cwd(), outputPath);
481
+ console.log("[OK] Telemetry & ROI Performance Report generated:");
482
+ console.log(` Output file: ${res.filePath}\n`);
483
+ console.log(res.content);
484
+ break;
485
+ }
486
+ case "clear": {
487
+ printHeader();
488
+ clearTelemetry();
489
+ console.log("[OK] Local telemetry store cleared and reset.\n");
490
+ break;
491
+ }
492
+ default:
493
+ console.error(`Unknown telemetry subcommand: ${sub}\n`);
494
+ printUsage();
495
+ process.exit(1);
496
+ }
497
+ }
346
498
  async function main() {
347
499
  const args = process.argv.slice(2);
348
500
  const command = args[0]?.toLowerCase();
349
501
  switch (command) {
502
+ case "commit":
503
+ await handleCommit(args.slice(1));
504
+ break;
505
+ case "telemetry":
506
+ await handleTelemetry(args.slice(1));
507
+ break;
350
508
  case "init":
351
509
  await handleInit();
352
510
  break;