nomark-engine 0.1.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.
- package/dist/index.js +207 -0
- package/package.json +38 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
var RESET = "\x1B[0m";
|
|
7
|
+
var BOLD = "\x1B[1m";
|
|
8
|
+
var DIM = "\x1B[2m";
|
|
9
|
+
var GREEN = "\x1B[32m";
|
|
10
|
+
var CYAN = "\x1B[36m";
|
|
11
|
+
var YELLOW = "\x1B[33m";
|
|
12
|
+
var LEDGER_FILE = "nomark-ledger.jsonl";
|
|
13
|
+
function today() {
|
|
14
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
15
|
+
}
|
|
16
|
+
function seedLedger() {
|
|
17
|
+
const meta = {
|
|
18
|
+
profile: {},
|
|
19
|
+
signals: 0,
|
|
20
|
+
by_ctx: {},
|
|
21
|
+
by_out: {},
|
|
22
|
+
avg_conf: 0,
|
|
23
|
+
avg_q: 0,
|
|
24
|
+
updated: today()
|
|
25
|
+
};
|
|
26
|
+
return `[sig:meta] ${JSON.stringify(meta)}
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
var AI_CONTEXT = `## nomark-engine \u2014 Preference Resolver
|
|
30
|
+
|
|
31
|
+
This project uses \`@nomark-ai/engine\` to resolve user preferences from a portable JSONL ledger.
|
|
32
|
+
|
|
33
|
+
### Ledger location
|
|
34
|
+
\`./nomark-ledger.jsonl\` \u2014 each line is \`[sig:TYPE] {json}\`. Five signal types:
|
|
35
|
+
- **pref** \u2014 learned preferences (dimension + target + weight, max 20)
|
|
36
|
+
- **map** \u2014 meaning maps: natural language trigger \u2192 structured intent (max 10)
|
|
37
|
+
- **asn** \u2014 field defaults with accuracy tracking (max 5)
|
|
38
|
+
- **meta** \u2014 session metadata and aggregate stats (max 1)
|
|
39
|
+
- **rub** \u2014 rubrics with graduated trust levels (max 4)
|
|
40
|
+
|
|
41
|
+
Total capacity: 40 entries (~3 KB). The ledger is the source of truth for personalization.
|
|
42
|
+
|
|
43
|
+
### Quick usage
|
|
44
|
+
|
|
45
|
+
\`\`\`typescript
|
|
46
|
+
import { createResolver, parseLedger } from '@nomark-ai/engine'
|
|
47
|
+
import * as fs from 'fs'
|
|
48
|
+
|
|
49
|
+
const ledger = fs.readFileSync('./nomark-ledger.jsonl', 'utf8')
|
|
50
|
+
const resolver = createResolver({ ledgerContent: ledger, context: 'code' })
|
|
51
|
+
const result = resolver.resolveAll()
|
|
52
|
+
|
|
53
|
+
for (const [dim, res] of Object.entries(result.dimensions)) {
|
|
54
|
+
if (res.winner && !res.unstable) {
|
|
55
|
+
// Use this preference
|
|
56
|
+
console.log(\`\${dim}: \${res.winner.target}\`)
|
|
57
|
+
} else if (res.unstable) {
|
|
58
|
+
// Not enough evidence \u2014 ask the user
|
|
59
|
+
console.log(\`\${dim}: ask\`)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
\`\`\`
|
|
63
|
+
|
|
64
|
+
### Scoring (5 factors)
|
|
65
|
+
Score = Specificity(0.30) + Evidence(0.25) + Recency(0.20) + Stability(0.15) + Portability(0.10) - contradiction_penalty
|
|
66
|
+
- Score < 0.4 = unstable \u2192 recommend asking rather than assuming
|
|
67
|
+
- Scope matching: \`*\` (global), \`context:code\`, \`topic:auth\`, or compound \`context:code+topic:auth\`
|
|
68
|
+
|
|
69
|
+
### Importing signals
|
|
70
|
+
\`\`\`bash
|
|
71
|
+
npx nomark import --platform chatgpt --file export.json
|
|
72
|
+
npx nomark import --platform claude --file export.json
|
|
73
|
+
npx nomark profile # view resolved preferences
|
|
74
|
+
npx nomark review # confirm low-confidence signals
|
|
75
|
+
\`\`\`
|
|
76
|
+
|
|
77
|
+
### Rules
|
|
78
|
+
- Never modify scoring formulas without owner approval (patented)
|
|
79
|
+
- Never change the JSONL ledger format (compatibility contract)
|
|
80
|
+
- Ledger entries are capacity-bounded \u2014 pruning evicts lowest-utility entries`;
|
|
81
|
+
function printBanner() {
|
|
82
|
+
console.log();
|
|
83
|
+
console.log(`${BOLD} nomark-engine${RESET} ${DIM}\u2014 preference resolver setup${RESET}`);
|
|
84
|
+
console.log();
|
|
85
|
+
}
|
|
86
|
+
function detectProject(dir) {
|
|
87
|
+
const pkgPath = path.join(dir, "package.json");
|
|
88
|
+
if (fs.existsSync(pkgPath)) {
|
|
89
|
+
try {
|
|
90
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
91
|
+
return { hasPackageJson: true, name: pkg.name ?? path.basename(dir) };
|
|
92
|
+
} catch {
|
|
93
|
+
return { hasPackageJson: true, name: path.basename(dir) };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { hasPackageJson: false, name: path.basename(dir) };
|
|
97
|
+
}
|
|
98
|
+
function createLedger(dir) {
|
|
99
|
+
const ledgerPath = path.join(dir, LEDGER_FILE);
|
|
100
|
+
if (fs.existsSync(ledgerPath)) {
|
|
101
|
+
return "exists";
|
|
102
|
+
}
|
|
103
|
+
fs.writeFileSync(ledgerPath, seedLedger(), "utf8");
|
|
104
|
+
return "created";
|
|
105
|
+
}
|
|
106
|
+
function writeAIContext(dir) {
|
|
107
|
+
const candidates = [
|
|
108
|
+
".claude/CLAUDE.md",
|
|
109
|
+
"CLAUDE.md",
|
|
110
|
+
".cursor/rules",
|
|
111
|
+
".github/copilot-instructions.md"
|
|
112
|
+
];
|
|
113
|
+
for (const rel of candidates) {
|
|
114
|
+
const full = path.join(dir, rel);
|
|
115
|
+
if (fs.existsSync(full)) {
|
|
116
|
+
const existing = fs.readFileSync(full, "utf8");
|
|
117
|
+
if (existing.includes("nomark-engine")) {
|
|
118
|
+
return `already in ${rel}`;
|
|
119
|
+
}
|
|
120
|
+
fs.appendFileSync(full, "\n\n" + AI_CONTEXT + "\n", "utf8");
|
|
121
|
+
return rel;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return "none";
|
|
125
|
+
}
|
|
126
|
+
function printQuickStart(project) {
|
|
127
|
+
console.log(`${BOLD} Quick start${RESET}`);
|
|
128
|
+
console.log();
|
|
129
|
+
if (project.hasPackageJson) {
|
|
130
|
+
console.log(`${DIM} 1.${RESET} Install the engine:`);
|
|
131
|
+
console.log(` ${CYAN}npm install @nomark-ai/engine${RESET}`);
|
|
132
|
+
} else {
|
|
133
|
+
console.log(`${DIM} 1.${RESET} Initialize your project, then install:`);
|
|
134
|
+
console.log(` ${CYAN}npm init -y && npm install @nomark-ai/engine${RESET}`);
|
|
135
|
+
}
|
|
136
|
+
console.log();
|
|
137
|
+
console.log(`${DIM} 2.${RESET} Import your AI history to build your ledger:`);
|
|
138
|
+
console.log(` ${CYAN}npx nomark import --platform chatgpt --file export.json${RESET}`);
|
|
139
|
+
console.log();
|
|
140
|
+
console.log(`${DIM} 3.${RESET} View your resolved preference profile:`);
|
|
141
|
+
console.log(` ${CYAN}npx nomark profile${RESET}`);
|
|
142
|
+
console.log();
|
|
143
|
+
console.log(`${DIM} 4.${RESET} Use in code:`);
|
|
144
|
+
console.log();
|
|
145
|
+
console.log(`${DIM} import { createResolver } from '@nomark-ai/engine'${RESET}`);
|
|
146
|
+
console.log(`${DIM} import * as fs from 'fs'${RESET}`);
|
|
147
|
+
console.log();
|
|
148
|
+
console.log(`${DIM} const ledger = fs.readFileSync('./nomark-ledger.jsonl', 'utf8')${RESET}`);
|
|
149
|
+
console.log(`${DIM} const resolver = createResolver({ ledgerContent: ledger })${RESET}`);
|
|
150
|
+
console.log(`${DIM} const result = resolver.resolveAll()${RESET}`);
|
|
151
|
+
console.log();
|
|
152
|
+
}
|
|
153
|
+
function main() {
|
|
154
|
+
const args = process.argv.slice(2);
|
|
155
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
156
|
+
printBanner();
|
|
157
|
+
console.log(` Usage: ${CYAN}npx nomark-engine${RESET} [options]`);
|
|
158
|
+
console.log();
|
|
159
|
+
console.log(" Options:");
|
|
160
|
+
console.log(" --context-only Print AI context block to stdout (for piping)");
|
|
161
|
+
console.log(" --no-ledger Skip ledger creation");
|
|
162
|
+
console.log(" --help Show this help");
|
|
163
|
+
console.log();
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (args.includes("--context-only")) {
|
|
167
|
+
process.stdout.write(AI_CONTEXT + "\n");
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const dir = process.cwd();
|
|
171
|
+
const project = detectProject(dir);
|
|
172
|
+
const skipLedger = args.includes("--no-ledger");
|
|
173
|
+
printBanner();
|
|
174
|
+
if (!skipLedger) {
|
|
175
|
+
const ledgerResult = createLedger(dir);
|
|
176
|
+
if (ledgerResult === "created") {
|
|
177
|
+
console.log(` ${GREEN}+${RESET} Created ${BOLD}${LEDGER_FILE}${RESET} ${DIM}(seed meta entry)${RESET}`);
|
|
178
|
+
} else {
|
|
179
|
+
console.log(` ${DIM}-${RESET} ${LEDGER_FILE} already exists ${DIM}(skipped)${RESET}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const contextTarget = writeAIContext(dir);
|
|
183
|
+
if (contextTarget === "none") {
|
|
184
|
+
console.log(` ${YELLOW}!${RESET} No AI config found ${DIM}(CLAUDE.md, .cursor/rules, etc.)${RESET}`);
|
|
185
|
+
console.log(` ${DIM}Run ${CYAN}npx nomark-engine --context-only >> CLAUDE.md${RESET} ${DIM}to add manually${RESET}`);
|
|
186
|
+
} else if (contextTarget.startsWith("already")) {
|
|
187
|
+
console.log(` ${DIM}-${RESET} AI context ${contextTarget} ${DIM}(skipped)${RESET}`);
|
|
188
|
+
} else {
|
|
189
|
+
console.log(` ${GREEN}+${RESET} Appended AI context to ${BOLD}${contextTarget}${RESET}`);
|
|
190
|
+
}
|
|
191
|
+
const gitignorePath = path.join(dir, ".gitignore");
|
|
192
|
+
if (fs.existsSync(gitignorePath)) {
|
|
193
|
+
const gitignore = fs.readFileSync(gitignorePath, "utf8");
|
|
194
|
+
if (!gitignore.includes(LEDGER_FILE)) {
|
|
195
|
+
fs.appendFileSync(gitignorePath, `
|
|
196
|
+
# nomark preference ledger (contains personal signals)
|
|
197
|
+
${LEDGER_FILE}
|
|
198
|
+
`, "utf8");
|
|
199
|
+
console.log(` ${GREEN}+${RESET} Added ${BOLD}${LEDGER_FILE}${RESET} to .gitignore`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
console.log();
|
|
203
|
+
printQuickStart(project);
|
|
204
|
+
console.log(`${DIM} Docs: https://github.com/nomark-dev/nomark-sdk${RESET}`);
|
|
205
|
+
console.log();
|
|
206
|
+
}
|
|
207
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nomark-engine",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Set up @nomark-ai/engine in your project — ledger, AI context, and quick-start in under 60 seconds",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"nomark-engine": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsup",
|
|
15
|
+
"test": "node --test 'tests/*.test.js'",
|
|
16
|
+
"typecheck": "tsc --noEmit"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"tsup": "^8.0.0",
|
|
20
|
+
"typescript": "^5.5.0"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/nomark-dev/nomark-sdk",
|
|
28
|
+
"directory": "packages/create-nomark-engine"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"nomark",
|
|
32
|
+
"ai",
|
|
33
|
+
"agent",
|
|
34
|
+
"preferences",
|
|
35
|
+
"setup",
|
|
36
|
+
"cli"
|
|
37
|
+
]
|
|
38
|
+
}
|