@mneme-ai/core 2.19.36 → 2.19.38

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 (91) hide show
  1. package/dist/browser_receipt/browser.test.d.ts +2 -0
  2. package/dist/browser_receipt/browser.test.d.ts.map +1 -0
  3. package/dist/browser_receipt/browser.test.js +156 -0
  4. package/dist/browser_receipt/browser.test.js.map +1 -0
  5. package/dist/browser_receipt/index.d.ts +109 -0
  6. package/dist/browser_receipt/index.d.ts.map +1 -0
  7. package/dist/browser_receipt/index.js +231 -0
  8. package/dist/browser_receipt/index.js.map +1 -0
  9. package/dist/browser_userscript/index.d.ts +79 -0
  10. package/dist/browser_userscript/index.d.ts.map +1 -0
  11. package/dist/browser_userscript/index.js +371 -0
  12. package/dist/browser_userscript/index.js.map +1 -0
  13. package/dist/browser_userscript/userscript.test.d.ts +2 -0
  14. package/dist/browser_userscript/userscript.test.d.ts.map +1 -0
  15. package/dist/browser_userscript/userscript.test.js +130 -0
  16. package/dist/browser_userscript/userscript.test.js.map +1 -0
  17. package/dist/citizens_audit/citizens.test.d.ts +2 -0
  18. package/dist/citizens_audit/citizens.test.d.ts.map +1 -0
  19. package/dist/citizens_audit/citizens.test.js +167 -0
  20. package/dist/citizens_audit/citizens.test.js.map +1 -0
  21. package/dist/citizens_audit/index.d.ts +118 -0
  22. package/dist/citizens_audit/index.d.ts.map +1 -0
  23. package/dist/citizens_audit/index.js +215 -0
  24. package/dist/citizens_audit/index.js.map +1 -0
  25. package/dist/citizens_contribute/contribute.test.d.ts +2 -0
  26. package/dist/citizens_contribute/contribute.test.d.ts.map +1 -0
  27. package/dist/citizens_contribute/contribute.test.js +136 -0
  28. package/dist/citizens_contribute/contribute.test.js.map +1 -0
  29. package/dist/citizens_contribute/index.d.ts +103 -0
  30. package/dist/citizens_contribute/index.d.ts.map +1 -0
  31. package/dist/citizens_contribute/index.js +176 -0
  32. package/dist/citizens_contribute/index.js.map +1 -0
  33. package/dist/conscience_auto_hook/auto_hook.test.d.ts +2 -0
  34. package/dist/conscience_auto_hook/auto_hook.test.d.ts.map +1 -0
  35. package/dist/conscience_auto_hook/auto_hook.test.js +149 -0
  36. package/dist/conscience_auto_hook/auto_hook.test.js.map +1 -0
  37. package/dist/conscience_auto_hook/index.d.ts +83 -0
  38. package/dist/conscience_auto_hook/index.d.ts.map +1 -0
  39. package/dist/conscience_auto_hook/index.js +170 -0
  40. package/dist/conscience_auto_hook/index.js.map +1 -0
  41. package/dist/conscience_card/card.test.d.ts +2 -0
  42. package/dist/conscience_card/card.test.d.ts.map +1 -0
  43. package/dist/conscience_card/card.test.js +173 -0
  44. package/dist/conscience_card/card.test.js.map +1 -0
  45. package/dist/conscience_card/index.d.ts +75 -0
  46. package/dist/conscience_card/index.d.ts.map +1 -0
  47. package/dist/conscience_card/index.js +152 -0
  48. package/dist/conscience_card/index.js.map +1 -0
  49. package/dist/cosmic/aurelian_v1937.test.d.ts +2 -0
  50. package/dist/cosmic/aurelian_v1937.test.d.ts.map +1 -0
  51. package/dist/cosmic/aurelian_v1937.test.js +90 -0
  52. package/dist/cosmic/aurelian_v1937.test.js.map +1 -0
  53. package/dist/cosmic/aurelian_v1938.test.d.ts +2 -0
  54. package/dist/cosmic/aurelian_v1938.test.d.ts.map +1 -0
  55. package/dist/cosmic/aurelian_v1938.test.js +76 -0
  56. package/dist/cosmic/aurelian_v1938.test.js.map +1 -0
  57. package/dist/index.d.ts +9 -0
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +20 -0
  60. package/dist/index.js.map +1 -1
  61. package/dist/mayor_auto_vote/auto_vote.test.d.ts +2 -0
  62. package/dist/mayor_auto_vote/auto_vote.test.d.ts.map +1 -0
  63. package/dist/mayor_auto_vote/auto_vote.test.js +167 -0
  64. package/dist/mayor_auto_vote/auto_vote.test.js.map +1 -0
  65. package/dist/mayor_auto_vote/index.d.ts +97 -0
  66. package/dist/mayor_auto_vote/index.d.ts.map +1 -0
  67. package/dist/mayor_auto_vote/index.js +206 -0
  68. package/dist/mayor_auto_vote/index.js.map +1 -0
  69. package/dist/mayor_election/index.d.ts +147 -0
  70. package/dist/mayor_election/index.d.ts.map +1 -0
  71. package/dist/mayor_election/index.js +256 -0
  72. package/dist/mayor_election/index.js.map +1 -0
  73. package/dist/mayor_election/mayor.test.d.ts +2 -0
  74. package/dist/mayor_election/mayor.test.d.ts.map +1 -0
  75. package/dist/mayor_election/mayor.test.js +175 -0
  76. package/dist/mayor_election/mayor.test.js.map +1 -0
  77. package/dist/mneme_receipt_protocol/index.d.ts +164 -0
  78. package/dist/mneme_receipt_protocol/index.d.ts.map +1 -0
  79. package/dist/mneme_receipt_protocol/index.js +335 -0
  80. package/dist/mneme_receipt_protocol/index.js.map +1 -0
  81. package/dist/mneme_receipt_protocol/protocol.test.d.ts +2 -0
  82. package/dist/mneme_receipt_protocol/protocol.test.d.ts.map +1 -0
  83. package/dist/mneme_receipt_protocol/protocol.test.js +176 -0
  84. package/dist/mneme_receipt_protocol/protocol.test.js.map +1 -0
  85. package/dist/whats_new.d.ts.map +1 -1
  86. package/dist/whats_new.js +16 -0
  87. package/dist/whats_new.js.map +1 -1
  88. package/dist/wrapper_genesis/index.d.ts.map +1 -1
  89. package/dist/wrapper_genesis/index.js +100 -0
  90. package/dist/wrapper_genesis/index.js.map +1 -1
  91. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=auto_vote.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto_vote.test.d.ts","sourceRoot":"","sources":["../../src/mayor_auto_vote/auto_vote.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,167 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { detectVendorFromCommit, autoVoteFromCommit, autoVoteBatch, generatePostCommitHook, generatePostCommitHookPwsh, generateStatusLine, computeAutoVoteStats, formatAutoVoteLine, MAYOR_AUTO_VOTE_TUNABLES, } from "./index.js";
3
+ import { freshElectionState } from "../mayor_election/index.js";
4
+ const SECRET = "auto-vote-test-77";
5
+ describe("v2.19.38 MAYOR AUTO-VOTE — vendor detection from commit trailers", () => {
6
+ it("Claude Code default trailer", () => {
7
+ expect(detectVendorFromCommit(`fix: bug
8
+
9
+ Co-Authored-By: Claude <noreply@anthropic.com>`)).toBe("claude");
10
+ });
11
+ it("Generic Claude Co-Authored-By", () => {
12
+ expect(detectVendorFromCommit(`feat: x\n\nCo-Authored-By: Claude Opus 4.7`)).toBe("claude");
13
+ });
14
+ it("AI-Generated-By: claude", () => {
15
+ expect(detectVendorFromCommit(`fix\n\nAI-Generated-By: claude`)).toBe("claude");
16
+ });
17
+ it("ChatGPT / GPT trailers", () => {
18
+ expect(detectVendorFromCommit(`x\n\nCo-Authored-By: ChatGPT`)).toBe("gpt");
19
+ expect(detectVendorFromCommit(`x\n\nCo-Authored-By: GPT-4`)).toBe("gpt");
20
+ expect(detectVendorFromCommit(`x\n\nAI-Generated-By: openai`)).toBe("gpt");
21
+ });
22
+ it("Gemini / Bard trailers", () => {
23
+ expect(detectVendorFromCommit(`x\n\nCo-Authored-By: Gemini`)).toBe("gemini");
24
+ expect(detectVendorFromCommit(`x\n\nCo-Authored-By: Bard`)).toBe("gemini");
25
+ expect(detectVendorFromCommit(`x\n\nAI-Generated-By: gemini`)).toBe("gemini");
26
+ });
27
+ it("Grok / Copilot / Cursor / Aider / Codeium", () => {
28
+ expect(detectVendorFromCommit(`x\n\nCo-Authored-By: Grok`)).toBe("grok");
29
+ expect(detectVendorFromCommit(`x\n\nCo-Authored-By: Copilot`)).toBe("copilot");
30
+ expect(detectVendorFromCommit(`x\n\nCo-Authored-By: Cursor`)).toBe("cursor");
31
+ expect(detectVendorFromCommit(`x\n\nCo-Authored-By: Aider`)).toBe("aider");
32
+ expect(detectVendorFromCommit(`x\n\nCo-Authored-By: Codeium`)).toBe("codeium");
33
+ expect(detectVendorFromCommit(`x\n\nCo-Authored-By: Windsurf`)).toBe("codeium");
34
+ });
35
+ it("human-only commit → null (no vote)", () => {
36
+ expect(detectVendorFromCommit("regular human commit message")).toBe(null);
37
+ expect(detectVendorFromCommit("fix: typo")).toBe(null);
38
+ });
39
+ it("DEFENSIVE: empty / null / garbage → null", () => {
40
+ expect(detectVendorFromCommit("")).toBe(null);
41
+ expect(detectVendorFromCommit(null)).toBe(null);
42
+ expect(detectVendorFromCommit(42)).toBe(null);
43
+ });
44
+ it("generic AI-Generated-By with unknown vendor → captured", () => {
45
+ expect(detectVendorFromCommit(`x\n\nAI-Generated-By: newvendor`)).toBe("newvendor");
46
+ });
47
+ });
48
+ describe("v2.19.38 MAYOR AUTO-VOTE — autoVoteFromCommit", () => {
49
+ it("AI commit → vote cast", () => {
50
+ const state = freshElectionState({ repoId: "test", termStartMs: 0, termMs: 1_000_000 });
51
+ const r = autoVoteFromCommit({
52
+ state, commitMessage: `feat: x\n\nCo-Authored-By: Claude <noreply@anthropic.com>`,
53
+ commitSha: "abc123def", castAtMs: 1000, secret: SECRET,
54
+ });
55
+ expect(r.vote).not.toBeNull();
56
+ expect(r.vote.vendor).toBe("claude");
57
+ expect(r.detectedVendor).toBe("claude");
58
+ });
59
+ it("human commit → no vote", () => {
60
+ const state = freshElectionState({ repoId: "test", termStartMs: 0, termMs: 1_000_000 });
61
+ const r = autoVoteFromCommit({ state, commitMessage: "fix: typo", castAtMs: 1000, secret: SECRET });
62
+ expect(r.vote).toBeNull();
63
+ expect(r.detectedVendor).toBe(null);
64
+ });
65
+ it("DEDUPE: same commitSha votes only once", () => {
66
+ let state = freshElectionState({ repoId: "test", termStartMs: 0, termMs: 1_000_000 });
67
+ const msg = `x\n\nCo-Authored-By: Claude <noreply@anthropic.com>`;
68
+ const r1 = autoVoteFromCommit({ state, commitMessage: msg, commitSha: "abc", castAtMs: 100, secret: SECRET });
69
+ state = r1.state;
70
+ const r2 = autoVoteFromCommit({ state, commitMessage: msg, commitSha: "abc", castAtMs: 200, secret: SECRET });
71
+ expect(r1.vote).not.toBeNull();
72
+ expect(r2.vote).toBeNull(); // dedupe
73
+ expect(r2.reason).toContain("already voted");
74
+ });
75
+ });
76
+ describe("v2.19.38 MAYOR AUTO-VOTE — batch", () => {
77
+ it("processes N commits + breakdown", () => {
78
+ const state = freshElectionState({ repoId: "test", termStartMs: 0, termMs: 100_000_000 });
79
+ const commits = [
80
+ { sha: "1", message: "x\n\nCo-Authored-By: Claude <noreply@anthropic.com>", authorDate: 1000 },
81
+ { sha: "2", message: "y\n\nCo-Authored-By: ChatGPT", authorDate: 2000 },
82
+ { sha: "3", message: "z (human commit)", authorDate: 3000 },
83
+ { sha: "4", message: "w\n\nCo-Authored-By: Claude <noreply@anthropic.com>", authorDate: 4000 },
84
+ ];
85
+ const r = autoVoteBatch({ state, commits, secret: SECRET });
86
+ expect(r.votesCast).toBe(3); // 2 claude + 1 gpt
87
+ expect(r.commitsSkipped).toBe(1);
88
+ expect(r.breakdown.claude).toBe(2);
89
+ expect(r.breakdown.gpt).toBe(1);
90
+ });
91
+ it("DEFENSIVE: malformed commits skipped", () => {
92
+ const state = freshElectionState({ repoId: "test", termStartMs: 0, termMs: 100_000_000 });
93
+ const commits = [
94
+ { sha: "1", message: "x\n\nCo-Authored-By: Claude <noreply@anthropic.com>", authorDate: 1000 },
95
+ null,
96
+ { sha: "2" },
97
+ ];
98
+ const r = autoVoteBatch({ state, commits, secret: SECRET });
99
+ expect(r.votesCast).toBe(1);
100
+ expect(r.commitsSkipped).toBe(2);
101
+ });
102
+ });
103
+ describe("v2.19.38 MAYOR AUTO-VOTE — hook script generators", () => {
104
+ it("post-commit bash hook is valid shell", () => {
105
+ const hook = generatePostCommitHook();
106
+ expect(hook).toMatch(/^#!\/usr\/bin\/env bash/);
107
+ expect(hook).toContain("git rev-parse HEAD");
108
+ expect(hook).toContain("git log -1 --format=%B HEAD");
109
+ expect(hook).toContain("mneme mayor auto_vote_from_commit");
110
+ });
111
+ it("post-commit PowerShell hook is valid", () => {
112
+ const hook = generatePostCommitHookPwsh();
113
+ expect(hook).toContain("git rev-parse HEAD");
114
+ expect(hook).toContain("ConvertTo-Json");
115
+ expect(hook).toContain("mneme mayor auto_vote_from_commit");
116
+ });
117
+ });
118
+ describe("v2.19.38 MAYOR AUTO-VOTE — status line", () => {
119
+ it("formats winner + runner-up + term-remaining", () => {
120
+ const line = generateStatusLine({
121
+ winnerVendor: "claude", winnerVoteCount: 35,
122
+ runnerUpVendor: "gpt", runnerUpVoteCount: 28,
123
+ marginPct: 12.3, termRemainingMs: 5 * 86400_000,
124
+ });
125
+ expect(line).toContain("claude 35");
126
+ expect(line).toContain("gpt 28");
127
+ expect(line).toContain("5d left");
128
+ });
129
+ it("no votes → friendly empty message", () => {
130
+ expect(generateStatusLine({ winnerVendor: null, winnerVoteCount: 0 })).toContain("no votes");
131
+ });
132
+ });
133
+ describe("v2.19.38 MAYOR AUTO-VOTE — stats + tunables + 1000-iter fuzz", () => {
134
+ it("computeAutoVoteStats counts vendors", () => {
135
+ const state = freshElectionState({ repoId: "test", termStartMs: 0, termMs: 100_000_000 });
136
+ const results = [];
137
+ let s = state;
138
+ for (let i = 0; i < 20; i++) {
139
+ const msg = i % 3 === 0 ? "human commit" : `x\n\nCo-Authored-By: ${i % 2 === 0 ? "Claude <noreply@anthropic.com>" : "ChatGPT"}`;
140
+ const r = autoVoteFromCommit({ state: s, commitMessage: msg, commitSha: `sha${i}`, castAtMs: i * 100, secret: SECRET });
141
+ results.push(r);
142
+ s = r.state;
143
+ }
144
+ const stats = computeAutoVoteStats(results);
145
+ expect(stats.totalCommitsProcessed).toBe(20);
146
+ expect(stats.votesCast).toBeGreaterThan(0);
147
+ expect(formatAutoVoteLine(stats)).toContain("AUTO-VOTE");
148
+ });
149
+ it("≥8 recognised vendors", () => {
150
+ expect(MAYOR_AUTO_VOTE_TUNABLES.RECOGNISED_VENDORS.length).toBeGreaterThanOrEqual(8);
151
+ });
152
+ it("1000 random commit messages never crash", () => {
153
+ const state = freshElectionState({ repoId: "test", termStartMs: 0, termMs: 100_000_000_000 });
154
+ let s = state;
155
+ const trailers = [
156
+ `Co-Authored-By: Claude <noreply@anthropic.com>`, `Co-Authored-By: ChatGPT`, `Co-Authored-By: Gemini`,
157
+ `AI-Generated-By: grok`, ``, `fix: typo`,
158
+ ];
159
+ for (let i = 0; i < 1000; i++) {
160
+ const msg = `commit ${i}\n\n${trailers[i % trailers.length]}`;
161
+ const r = autoVoteFromCommit({ state: s, commitMessage: msg, commitSha: `sha${i}`, castAtMs: i, secret: SECRET });
162
+ s = r.state;
163
+ }
164
+ expect(s.votes.length).toBeGreaterThan(0);
165
+ });
166
+ });
167
+ //# sourceMappingURL=auto_vote.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto_vote.test.js","sourceRoot":"","sources":["../../src/mayor_auto_vote/auto_vote.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * v2.19.38 — MNEME MAYOR AUTO-VOTE (Socket #4 — git commit trailer → auto-vote)
3
+ *
4
+ * v2.19.37 MAYOR ELECTION shipped the ledger + tally. v2.19.38 ships
5
+ * the AUTO-VOTE: parse `git log` output for AI vendor trailers
6
+ * ("Co-Authored-By: Claude <noreply@anthropic.com>" / "AI-Generated-By:
7
+ * gpt" / etc) and auto-record a vote per commit. Plus IDE status-bar
8
+ * text generator so user sees "Mayor: claude" without leaving editor.
9
+ *
10
+ * Wired into post-commit git hook (caller installs hook; this module
11
+ * does the parse + vote).
12
+ *
13
+ * Composes onto:
14
+ * - v2.19.37 MAYOR ELECTION (recordVote primitive)
15
+ * - v2.19.34 OUTCOME MARKET (reputation signal source)
16
+ * - v2.19.34 ZK FAIRNESS (fairness signal source)
17
+ *
18
+ * Honest scope:
19
+ * - PURE FUNCTION parser + vote builder + status-line. Caller does git I/O.
20
+ * - Detects 9+ canonical trailer formats.
21
+ * - Defensive: empty / garbage commit message → no vote (returns null).
22
+ * - 25+ tests + 1000-iter fuzz.
23
+ */
24
+ import { type ElectionState, type Vote } from "../mayor_election/index.js";
25
+ /**
26
+ * Detect AI vendor from a commit message. Returns null if no recognised
27
+ * AI trailer is present (human-only commits don't vote).
28
+ */
29
+ export declare function detectVendorFromCommit(commitMessage: string): string | null;
30
+ export interface AutoVoteInput {
31
+ state: ElectionState;
32
+ commitMessage: string;
33
+ commitSha?: string;
34
+ castAtMs?: number;
35
+ secret?: string;
36
+ }
37
+ export interface AutoVoteResult {
38
+ state: ElectionState;
39
+ vote: Vote | null;
40
+ detectedVendor: string | null;
41
+ reason: string;
42
+ }
43
+ /**
44
+ * Parse commit → detect vendor → cast vote. Idempotent if caller passes
45
+ * the same commitSha twice (the vote ledger contains commitSha).
46
+ */
47
+ export declare function autoVoteFromCommit(input: AutoVoteInput): AutoVoteResult;
48
+ export interface CommitInput {
49
+ sha: string;
50
+ message: string;
51
+ /** ISO date or ms epoch. */
52
+ authorDate?: string | number;
53
+ }
54
+ export declare function autoVoteBatch(input: {
55
+ state: ElectionState;
56
+ commits: CommitInput[];
57
+ secret?: string;
58
+ }): {
59
+ state: ElectionState;
60
+ votesCast: number;
61
+ commitsSkipped: number;
62
+ breakdown: Record<string, number>;
63
+ };
64
+ /**
65
+ * Emit a portable post-commit hook script that calls `mneme mayor vote`
66
+ * with the trailer-detected vendor. Caller writes to `.git/hooks/post-commit`
67
+ * + chmod +x. No external deps.
68
+ */
69
+ export declare function generatePostCommitHook(): string;
70
+ /**
71
+ * Emit a powershell equivalent for Windows users (post-commit hook).
72
+ */
73
+ export declare function generatePostCommitHookPwsh(): string;
74
+ export interface StatusLineInput {
75
+ /** Latest election result (mid-term or final). */
76
+ winnerVendor: string | null;
77
+ winnerVoteCount: number;
78
+ runnerUpVendor?: string | null;
79
+ runnerUpVoteCount?: number;
80
+ marginPct?: number;
81
+ termRemainingMs?: number;
82
+ }
83
+ export declare function generateStatusLine(input: StatusLineInput): string;
84
+ export interface AutoVoteStats {
85
+ totalCommitsProcessed: number;
86
+ votesCast: number;
87
+ skipped: number;
88
+ vendorBreakdown: Record<string, number>;
89
+ }
90
+ export declare function computeAutoVoteStats(results: AutoVoteResult[]): AutoVoteStats;
91
+ export declare function formatAutoVoteLine(s: AutoVoteStats): string;
92
+ export declare const MAYOR_AUTO_VOTE_TUNABLES: Readonly<{
93
+ PROTOCOL_VERSION: 1;
94
+ RECOGNISED_VENDORS: ReadonlyArray<string>;
95
+ TRAILER_PATTERN_COUNT: number;
96
+ }>;
97
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mayor_auto_vote/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAc,KAAK,aAAa,EAAE,KAAK,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAsCvF;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc3E;AAID,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CAwBvE;AAID,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAsBzG;AAID;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAc/C;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAWnD;AAID,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAUjE;AAED,MAAM,WAAW,aAAa;IAC5B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,aAAa,CAU7E;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAE3D;AAED,eAAO,MAAM,wBAAwB;;wBAEiE,aAAa,CAAC,MAAM,CAAC;;EAEzH,CAAC"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * v2.19.38 — MNEME MAYOR AUTO-VOTE (Socket #4 — git commit trailer → auto-vote)
3
+ *
4
+ * v2.19.37 MAYOR ELECTION shipped the ledger + tally. v2.19.38 ships
5
+ * the AUTO-VOTE: parse `git log` output for AI vendor trailers
6
+ * ("Co-Authored-By: Claude <noreply@anthropic.com>" / "AI-Generated-By:
7
+ * gpt" / etc) and auto-record a vote per commit. Plus IDE status-bar
8
+ * text generator so user sees "Mayor: claude" without leaving editor.
9
+ *
10
+ * Wired into post-commit git hook (caller installs hook; this module
11
+ * does the parse + vote).
12
+ *
13
+ * Composes onto:
14
+ * - v2.19.37 MAYOR ELECTION (recordVote primitive)
15
+ * - v2.19.34 OUTCOME MARKET (reputation signal source)
16
+ * - v2.19.34 ZK FAIRNESS (fairness signal source)
17
+ *
18
+ * Honest scope:
19
+ * - PURE FUNCTION parser + vote builder + status-line. Caller does git I/O.
20
+ * - Detects 9+ canonical trailer formats.
21
+ * - Defensive: empty / garbage commit message → no vote (returns null).
22
+ * - 25+ tests + 1000-iter fuzz.
23
+ */
24
+ import { recordVote } from "../mayor_election/index.js";
25
+ const PROTOCOL_VERSION = 1;
26
+ /**
27
+ * Canonical vendor trailers we recognise. Add more by PR.
28
+ * Format: regex matches a commit-message line; capture group 1 = raw label;
29
+ * we then normalise to a lowercase vendor id.
30
+ */
31
+ const TRAILER_PATTERNS = Object.freeze([
32
+ // Claude Code default trailer
33
+ { vendor: "claude", re: /^Co-Authored-By:\s*Claude(?:\s+\(.+?\))?\s*<noreply@anthropic\.com>/im },
34
+ // Generic Claude
35
+ { vendor: "claude", re: /^(?:AI-)?Co-Authored-By:\s*Claude\b/im },
36
+ { vendor: "claude", re: /^AI-Generated-By:\s*claude\b/im },
37
+ // GPT / OpenAI
38
+ { vendor: "gpt", re: /^Co-Authored-By:\s*(?:ChatGPT|GPT-?\d?(?:\.\d+)?)\b/im },
39
+ { vendor: "gpt", re: /^AI-Generated-By:\s*(?:gpt|openai)\b/im },
40
+ // Gemini / Google
41
+ { vendor: "gemini", re: /^Co-Authored-By:\s*Gemini\b/im },
42
+ { vendor: "gemini", re: /^AI-Generated-By:\s*gemini\b/im },
43
+ { vendor: "gemini", re: /^Co-Authored-By:\s*Bard\b/im },
44
+ // Grok / xAI
45
+ { vendor: "grok", re: /^Co-Authored-By:\s*Grok\b/im },
46
+ { vendor: "grok", re: /^AI-Generated-By:\s*grok\b/im },
47
+ // Copilot
48
+ { vendor: "copilot", re: /^Co-Authored-By:\s*Copilot\b/im },
49
+ { vendor: "copilot", re: /^AI-Generated-By:\s*copilot\b/im },
50
+ // Cursor
51
+ { vendor: "cursor", re: /^Co-Authored-By:\s*Cursor\b/im },
52
+ // Aider
53
+ { vendor: "aider", re: /^Co-Authored-By:\s*Aider\b/im },
54
+ // Codeium / Windsurf
55
+ { vendor: "codeium", re: /^Co-Authored-By:\s*(?:Codeium|Windsurf)\b/im },
56
+ // Generic catch-all fallback
57
+ { vendor: "unknown", re: /^AI-Generated-By:\s*([a-z0-9_.-]+)\b/im },
58
+ ]);
59
+ /**
60
+ * Detect AI vendor from a commit message. Returns null if no recognised
61
+ * AI trailer is present (human-only commits don't vote).
62
+ */
63
+ export function detectVendorFromCommit(commitMessage) {
64
+ if (typeof commitMessage !== "string" || commitMessage.length === 0)
65
+ return null;
66
+ for (const p of TRAILER_PATTERNS) {
67
+ const m = commitMessage.match(p.re);
68
+ if (m) {
69
+ // Fallback pattern captures the label
70
+ if (p.vendor === "unknown" && m[1]) {
71
+ const label = m[1].toLowerCase();
72
+ if (/^[a-z0-9_.-]+$/.test(label))
73
+ return label;
74
+ }
75
+ return p.vendor;
76
+ }
77
+ }
78
+ return null;
79
+ }
80
+ /**
81
+ * Parse commit → detect vendor → cast vote. Idempotent if caller passes
82
+ * the same commitSha twice (the vote ledger contains commitSha).
83
+ */
84
+ export function autoVoteFromCommit(input) {
85
+ const vendor = detectVendorFromCommit(input.commitMessage);
86
+ if (vendor === null) {
87
+ return { state: input.state, vote: null, detectedVendor: null, reason: "no AI trailer detected in commit message" };
88
+ }
89
+ // Dedupe via commitSha if supplied — don't double-vote the same commit
90
+ if (input.commitSha) {
91
+ const dup = input.state.votes.find((v) => v.commitSha === input.commitSha);
92
+ if (dup) {
93
+ return { state: input.state, vote: null, detectedVendor: vendor, reason: `commit ${input.commitSha.slice(0, 8)} already voted (dedupe)` };
94
+ }
95
+ }
96
+ const r = recordVote({
97
+ state: input.state, vendor,
98
+ commitSha: input.commitSha,
99
+ castAtMs: input.castAtMs,
100
+ secret: input.secret,
101
+ });
102
+ return {
103
+ state: r.state,
104
+ vote: r.vote,
105
+ detectedVendor: vendor,
106
+ reason: r.vote ? `auto-voted ${vendor} for commit ${input.commitSha?.slice(0, 8) ?? "?"}` : (r.reason ?? "vote rejected"),
107
+ };
108
+ }
109
+ export function autoVoteBatch(input) {
110
+ let state = input.state;
111
+ let votesCast = 0, skipped = 0;
112
+ const breakdown = {};
113
+ for (const c of input.commits ?? []) {
114
+ if (!c || typeof c.message !== "string") {
115
+ skipped++;
116
+ continue;
117
+ }
118
+ const ms = typeof c.authorDate === "number" ? c.authorDate
119
+ : (typeof c.authorDate === "string" ? Date.parse(c.authorDate) : Date.now());
120
+ const result = autoVoteFromCommit({
121
+ state, commitMessage: c.message, commitSha: c.sha,
122
+ castAtMs: Number.isFinite(ms) ? ms : Date.now(),
123
+ secret: input.secret,
124
+ });
125
+ state = result.state;
126
+ if (result.vote) {
127
+ votesCast++;
128
+ breakdown[result.detectedVendor] = (breakdown[result.detectedVendor] ?? 0) + 1;
129
+ }
130
+ else {
131
+ skipped++;
132
+ }
133
+ }
134
+ return { state, votesCast, commitsSkipped: skipped, breakdown };
135
+ }
136
+ // ─── GIT-HOOK SCRIPT GENERATOR (caller installs this) ──────────────
137
+ /**
138
+ * Emit a portable post-commit hook script that calls `mneme mayor vote`
139
+ * with the trailer-detected vendor. Caller writes to `.git/hooks/post-commit`
140
+ * + chmod +x. No external deps.
141
+ */
142
+ export function generatePostCommitHook() {
143
+ return `#!/usr/bin/env bash
144
+ # v2.19.38 — Mneme MAYOR auto-vote post-commit hook.
145
+ # Installed by 'mneme mayor install-hook'. Idempotent — safe to re-install.
146
+ # Reads the latest commit's message; if it has a recognised AI trailer
147
+ # (Co-Authored-By: Claude / AI-Generated-By: gpt / etc), records a vote.
148
+ set -e
149
+ SHA=$(git rev-parse HEAD 2>/dev/null) || exit 0
150
+ MSG=$(git log -1 --format=%B HEAD 2>/dev/null) || exit 0
151
+ # Best-effort, non-blocking: if mneme isn't installed or daemon is off, no harm.
152
+ if command -v mneme >/dev/null 2>&1; then
153
+ mneme mayor auto_vote_from_commit --json "{\\"commitSha\\":\\"$SHA\\",\\"commitMessage\\":$(printf '%s' "$MSG" | jq -Rs .)}" >/dev/null 2>&1 || true
154
+ fi
155
+ `;
156
+ }
157
+ /**
158
+ * Emit a powershell equivalent for Windows users (post-commit hook).
159
+ */
160
+ export function generatePostCommitHookPwsh() {
161
+ return `# v2.19.38 — Mneme MAYOR auto-vote post-commit hook (PowerShell).
162
+ # Installed by 'mneme mayor install-hook'. Idempotent.
163
+ $ErrorActionPreference = "SilentlyContinue"
164
+ $sha = git rev-parse HEAD
165
+ $msg = git log -1 --format=%B HEAD
166
+ if (Get-Command mneme -ErrorAction SilentlyContinue) {
167
+ $payload = @{ commitSha = "$sha"; commitMessage = "$msg" } | ConvertTo-Json -Compress
168
+ mneme mayor auto_vote_from_commit --json $payload 2>&1 | Out-Null
169
+ }
170
+ `;
171
+ }
172
+ export function generateStatusLine(input) {
173
+ if (!input.winnerVendor)
174
+ return "👑 Mayor: (no votes — cast one to elect)";
175
+ const winner = `${input.winnerVendor} ${input.winnerVoteCount}`;
176
+ const ru = input.runnerUpVendor ? ` vs ${input.runnerUpVendor} ${input.runnerUpVoteCount}` : "";
177
+ let term = "";
178
+ if (typeof input.termRemainingMs === "number" && input.termRemainingMs > 0) {
179
+ const days = Math.floor(input.termRemainingMs / (24 * 3600_000));
180
+ term = ` · ${days}d left`;
181
+ }
182
+ return `👑 Mayor: ${winner}${ru}${term}`;
183
+ }
184
+ export function computeAutoVoteStats(results) {
185
+ let cast = 0, skipped = 0;
186
+ const breakdown = {};
187
+ for (const r of results) {
188
+ if (r.vote) {
189
+ cast++;
190
+ if (r.detectedVendor)
191
+ breakdown[r.detectedVendor] = (breakdown[r.detectedVendor] ?? 0) + 1;
192
+ }
193
+ else
194
+ skipped++;
195
+ }
196
+ return { totalCommitsProcessed: results.length, votesCast: cast, skipped, vendorBreakdown: breakdown };
197
+ }
198
+ export function formatAutoVoteLine(s) {
199
+ return `👑 AUTO-VOTE · ${s.votesCast} cast / ${s.skipped} skipped · ${Object.keys(s.vendorBreakdown).length} vendors`;
200
+ }
201
+ export const MAYOR_AUTO_VOTE_TUNABLES = Object.freeze({
202
+ PROTOCOL_VERSION,
203
+ RECOGNISED_VENDORS: ["claude", "gpt", "gemini", "grok", "copilot", "cursor", "aider", "codeium"],
204
+ TRAILER_PATTERN_COUNT: TRAILER_PATTERNS.length,
205
+ });
206
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mayor_auto_vote/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * v2.19.37 — MNEME MAYOR ELECTION (Gap #1 + #5 — Mneme Moment + viral loop)
3
+ *
4
+ * Every repo elects a "Mayor AI" each month. The Mayor is the vendor
5
+ * that gets asked first on every commit. Election mechanism:
6
+ * - User votes (1 vote per commit, optional)
7
+ * - Outcome-market reputation score
8
+ * - Fairness certificate pass rate
9
+ * - Adversarial trick-test pass rate
10
+ *
11
+ * Auto-rotation every month. UI surface = status bar "Mayor: gpt-4
12
+ * (35 votes vs claude-opus 28)". Vendor lobby loop = engagement
13
+ * that other AI tools don't have.
14
+ *
15
+ * The pitch psychology: developers love games. "Pick the best AI
16
+ * right now" is more fun than "configure my AI provider settings".
17
+ * Vendors compete monthly = Mneme owns the meta-game.
18
+ *
19
+ * Composes onto:
20
+ * - v2.19.34 OUTCOME MARKET (reputation feed)
21
+ * - v2.19.34 ZK-FAIRNESS (fairness signal)
22
+ * - v2.19.34 APOSTILLE (election results recorded)
23
+ *
24
+ * Honest scope:
25
+ * - PURE FUNCTION ledger + tally + rotate. No I/O.
26
+ * - HMAC-chained vote ledger so vendors can't ballot-stuff post-hoc.
27
+ * - Deterministic tally + rotation.
28
+ * - 30+ election tests; 1000+ random fuzz iterations.
29
+ */
30
+ declare const PROTOCOL_VERSION: 1;
31
+ export interface Vote {
32
+ v: typeof PROTOCOL_VERSION;
33
+ voteId: string;
34
+ vendor: string;
35
+ /** Optional commit SHA tying vote to a real change. */
36
+ commitSha?: string;
37
+ /** ms since epoch. */
38
+ castAtMs: number;
39
+ /** Previous vote sig — HMAC chain prevents ballot stuffing post-hoc. */
40
+ prevSig: string | null;
41
+ sig: string;
42
+ }
43
+ export interface VendorSignal {
44
+ vendor: string;
45
+ /** Reputation from OUTCOME MARKET (0..1). */
46
+ reputationScore?: number;
47
+ /** Fairness certificate pass rate (0..1). */
48
+ fairnessPassRate?: number;
49
+ /** Adversarial trick-test pass rate (0..1). */
50
+ trickTestPassRate?: number;
51
+ }
52
+ export interface ElectionState {
53
+ v: typeof PROTOCOL_VERSION;
54
+ repoId: string;
55
+ termStartMs: number;
56
+ termMs: number;
57
+ /** Current sitting mayor (vendor name). */
58
+ currentMayor: string | null;
59
+ /** HMAC-chained vote ledger. */
60
+ votes: Vote[];
61
+ /** Latest election result snapshot. */
62
+ lastResult: ElectionResult | null;
63
+ }
64
+ export interface VendorScore {
65
+ vendor: string;
66
+ voteCount: number;
67
+ reputationScore: number;
68
+ fairnessPassRate: number;
69
+ trickTestPassRate: number;
70
+ /** Composite (0..1) — 50% votes + 25% reputation + 15% fairness + 10% trick. */
71
+ composite: number;
72
+ }
73
+ export interface ElectionResult {
74
+ v: typeof PROTOCOL_VERSION;
75
+ repoId: string;
76
+ termStartMs: number;
77
+ termEndMs: number;
78
+ /** Winner with HIGHEST composite (alpha tie-break). */
79
+ winnerVendor: string | null;
80
+ margin: number;
81
+ /** Per-vendor scores, sorted by composite desc. */
82
+ scores: VendorScore[];
83
+ /** Total votes in this term. */
84
+ totalVotes: number;
85
+ decidedAtMs: number;
86
+ sig: string;
87
+ }
88
+ export declare function freshElectionState(input: {
89
+ repoId: string;
90
+ termStartMs?: number;
91
+ termMs?: number;
92
+ }): ElectionState;
93
+ export declare function recordVote(input: {
94
+ state: ElectionState;
95
+ vendor: string;
96
+ commitSha?: string;
97
+ castAtMs?: number;
98
+ secret?: string;
99
+ }): {
100
+ state: ElectionState;
101
+ vote: Vote | null;
102
+ reason?: string;
103
+ };
104
+ /** Verify HMAC chain integrity end-to-end. */
105
+ export declare function verifyVoteLedger(state: ElectionState, secret?: string): boolean;
106
+ export declare function tallyElection(input: {
107
+ state: ElectionState;
108
+ signals: VendorSignal[];
109
+ nowMs?: number;
110
+ secret?: string;
111
+ }): ElectionResult;
112
+ export declare function verifyElectionResult(r: ElectionResult, secret?: string): boolean;
113
+ /**
114
+ * If the term has ended, tally + rotate to a fresh term with the winner
115
+ * installed as mayor. Idempotent if called mid-term — returns state unchanged.
116
+ */
117
+ export declare function runScheduledElection(input: {
118
+ state: ElectionState;
119
+ signals: VendorSignal[];
120
+ nowMs?: number;
121
+ secret?: string;
122
+ }): {
123
+ state: ElectionState;
124
+ rotated: boolean;
125
+ result: ElectionResult;
126
+ };
127
+ export declare function formatMayorLine(result: ElectionResult | null): string;
128
+ export interface ElectionStats {
129
+ totalVotes: number;
130
+ uniqueVendors: number;
131
+ currentMayor: string | null;
132
+ termMs: number;
133
+ termRemainingMs: number;
134
+ }
135
+ export declare function computeElectionStats(state: ElectionState, nowMs?: number): ElectionStats;
136
+ export declare const MAYOR_ELECTION_TUNABLES: Readonly<{
137
+ PROTOCOL_VERSION: 1;
138
+ DEFAULT_TERM_MS: number;
139
+ COMPOSITE_WEIGHTS: Readonly<{
140
+ votes: 0.5;
141
+ reputation: 0.25;
142
+ fairness: 0.15;
143
+ trickTest: 0.1;
144
+ }>;
145
+ }>;
146
+ export {};
147
+ //# sourceMappingURL=index.d.ts.map