@nitra/cursor 12.15.0 → 12.16.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/CHANGELOG.md +16 -0
- package/bin/n-cursor.js +2 -11
- package/lib/docs/index.md +9 -6
- package/lib/docs/pi-agent-fix.md +28 -0
- package/lib/docs/pi-agent-skill.md +36 -0
- package/lib/docs/pi-model-tiers.md +46 -0
- package/lib/docs/pi-one-shot.md +34 -0
- package/lib/docs/pi-telemetry-store.md +33 -0
- package/lib/docs/pi-trace.md +27 -0
- package/lib/docs/pi-write-guard.md +32 -0
- package/lib/pi-agent-fix.mjs +253 -0
- package/lib/pi-agent-skill.mjs +181 -0
- package/lib/pi-model-tiers.mjs +109 -0
- package/lib/pi-one-shot.mjs +129 -0
- package/lib/pi-telemetry-store.mjs +0 -0
- package/lib/pi-trace.mjs +40 -0
- package/lib/pi-write-guard.mjs +147 -0
- package/package.json +5 -1
- package/rules/bun/docs/main.md +7 -6
- package/rules/doc-files/js/docgen-files-batch.mjs +20 -5
- package/rules/doc-files/js/docgen-gen.mjs +42 -25
- package/rules/doc-files/js/docgen-judge-measure.mjs +16 -13
- package/rules/doc-files/js/docgen-judge.mjs +11 -9
- package/rules/doc-files/js/docs/docgen-files-batch.md +3 -20
- package/rules/doc-files/js/docs/docgen-gen.md +3 -20
- package/rules/doc-files/js/docs/docgen-judge-measure.md +3 -18
- package/rules/doc-files/js/docs/docgen-judge.md +3 -22
- package/rules/npm-module/js/docs/skill_meta.md +22 -15
- package/rules/npm-module/js/skill_meta.mjs +5 -1
- package/rules/python/docs/main.md +11 -11
- package/rules/rust/docs/main.md +5 -5
- package/rules/text/js/cspell-fix.mjs +15 -16
- package/rules/text/js/docs/cspell-fix.md +16 -9
- package/rules/text/main.mjs +4 -4
- package/schemas/skill-meta.json +8 -0
- package/scripts/docs/skills-cli.md +21 -25
- package/scripts/docs/update-blue-oak.md +8 -8
- package/scripts/lib/adr/docs/normalize-cli.md +3 -20
- package/scripts/lib/adr/docs/normalize-pipeline.md +3 -33
- package/scripts/lib/adr/normalize-cli.mjs +2 -2
- package/scripts/lib/adr/normalize-pipeline.mjs +78 -44
- package/scripts/lib/docs/discover-checkable-rules.md +6 -6
- package/scripts/lib/docs/inline-template-links.md +8 -6
- package/scripts/lib/docs/list-project-rules-mdc.md +5 -3
- package/scripts/lib/docs/root-notice.md +13 -16
- package/scripts/lib/docs/run-lint.md +10 -8
- package/scripts/lib/docs/skill-meta.md +29 -10
- package/scripts/lib/fix/docs/discover-t0-patterns.md +10 -13
- package/scripts/lib/fix/docs/escalation-log.md +10 -9
- package/scripts/lib/fix/docs/index.md +0 -1
- package/scripts/lib/fix/docs/orchestrator.md +15 -13
- package/scripts/lib/fix/escalation-log.mjs +1 -1
- package/scripts/lib/fix/orchestrator.mjs +67 -32
- package/scripts/lib/run-lint.mjs +2 -10
- package/scripts/lib/skill-meta.mjs +22 -0
- package/scripts/skills-cli.mjs +52 -14
- package/scripts/utils/ast-extract.mjs +105 -0
- package/scripts/utils/docs/ast-extract.md +30 -0
- package/scripts/utils/docs/walkDir.md +17 -20
- package/lib/docs/llm.md +0 -33
- package/lib/docs/models.md +0 -48
- package/lib/docs/omlx-trace.md +0 -49
- package/lib/docs/omlx.md +0 -41
- package/lib/llm.mjs +0 -215
- package/lib/models.mjs +0 -75
- package/lib/omlx-trace.mjs +0 -158
- package/lib/omlx.mjs +0 -220
- package/scripts/lib/fix/analyze-escalation.mjs +0 -353
- package/scripts/lib/fix/docs/analyze-escalation.md +0 -44
- package/scripts/lib/fix/docs/llm-fix-apply.md +0 -31
- package/scripts/lib/fix/docs/llm-lint-fix.md +0 -31
- package/scripts/lib/fix/docs/llm-worker.md +0 -33
- package/scripts/lib/fix/docs/verbose-block.md +0 -27
- package/scripts/lib/fix/llm-fix-apply.mjs +0 -113
- package/scripts/lib/fix/llm-lint-fix.mjs +0 -82
- package/scripts/lib/fix/llm-worker.mjs +0 -332
- package/scripts/lib/fix/verbose-block.mjs +0 -82
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
* Повертає той самий operations[]-контракт, що й single-shot — apply-логіка спільна.
|
|
25
25
|
*/
|
|
26
26
|
import { z } from 'zod'
|
|
27
|
-
import {
|
|
28
|
-
import { CLOUD_MIN, resolveModel } from '../../../lib/
|
|
27
|
+
import { runOneShot } from '../../../lib/pi-one-shot.mjs'
|
|
28
|
+
import { CLOUD_MIN, resolveModel } from '../../../lib/pi-model-tiers.mjs'
|
|
29
29
|
|
|
30
30
|
// ─────────────────────────── Stage 0: retrieval (JS) ───────────────────────────
|
|
31
31
|
|
|
@@ -168,36 +168,44 @@ const LOCAL = () => resolveModel('min')
|
|
|
168
168
|
* @param {Array<{role:string,content:string}>} messages чат-повідомлення для LLM
|
|
169
169
|
* @param {(raw:string)=>any} parse валідатор (кидає на невалідному)
|
|
170
170
|
* @param {{label:string, allowCloud:boolean, attempts?:number, stats:object, maxTokens?:number}} cfg конфіг каскаду (мітка, дозвіл на хмару, спроби, лічильники, ліміт токенів)
|
|
171
|
-
* @returns {any} результат parse
|
|
171
|
+
* @returns {Promise<any>} результат parse
|
|
172
172
|
* @throws {Error} якщо всі спроби провалені
|
|
173
173
|
*/
|
|
174
|
-
function callWithCascade(messages, parse, cfg) {
|
|
174
|
+
async function callWithCascade(messages, parse, cfg) {
|
|
175
175
|
const attempts = cfg.attempts ?? 2
|
|
176
|
-
const temps = [0.1, 0.4, 0.7]
|
|
177
176
|
let lastErr = null
|
|
178
177
|
for (let a = 0; a < attempts; a++) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
} catch (error) {
|
|
189
|
-
lastErr = error
|
|
190
|
-
if (classifyOmlxError(error.message) === 'infra') break
|
|
178
|
+
cfg.stats.localCalls++
|
|
179
|
+
const res = await runOneShot({ messages, modelSpec: LOCAL(), timeoutMs: 120_000, caller: `adr-pipe:${cfg.label}` })
|
|
180
|
+
if (!res.error) {
|
|
181
|
+
try {
|
|
182
|
+
return parse(res.content)
|
|
183
|
+
} catch (error) {
|
|
184
|
+
lastErr = error // невалідний вихід → наступна спроба
|
|
185
|
+
continue
|
|
186
|
+
}
|
|
191
187
|
}
|
|
188
|
+
lastErr = new Error(res.error)
|
|
189
|
+
// infra (registry/session/модель недоступна) → ретрай локально марний.
|
|
190
|
+
if (/registry:|session:|не знайдена/i.test(res.error)) break
|
|
192
191
|
}
|
|
193
192
|
if (cfg.allowCloud && CLOUD_MIN) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
193
|
+
cfg.stats.cloudCalls++
|
|
194
|
+
cfg.stats.escalations++
|
|
195
|
+
const res = await runOneShot({
|
|
196
|
+
messages,
|
|
197
|
+
modelSpec: CLOUD_MIN,
|
|
198
|
+
timeoutMs: 120_000,
|
|
199
|
+
caller: `adr-pipe:${cfg.label}:cloud`
|
|
200
|
+
})
|
|
201
|
+
if (!res.error) {
|
|
202
|
+
try {
|
|
203
|
+
return parse(res.content)
|
|
204
|
+
} catch (error) {
|
|
205
|
+
lastErr = error
|
|
206
|
+
}
|
|
207
|
+
} else {
|
|
208
|
+
lastErr = new Error(res.error)
|
|
201
209
|
}
|
|
202
210
|
}
|
|
203
211
|
cfg.stats.failures++
|
|
@@ -244,20 +252,27 @@ same=true ЛИШЕ якщо це по суті одне рішення (дубл
|
|
|
244
252
|
* @param {{votes?:number, minConf?:number}} [vote] override голосів і порога на тип ребра
|
|
245
253
|
* @returns {{same:boolean, votes:object[]}} підтвердження same та сирі голоси
|
|
246
254
|
*/
|
|
247
|
-
function judgeEdge(aTitle, aBody, bTitle, bBody, cfg, vote = {}) {
|
|
255
|
+
async function judgeEdge(aTitle, aBody, bTitle, bBody, cfg, vote = {}) {
|
|
248
256
|
const nVotes = vote.votes ?? cfg.votes ?? 2
|
|
249
257
|
const minConf = vote.minConf ?? 0.5
|
|
250
258
|
const user = `Запис A — "${aTitle}":\n${aBody.slice(0, 1500)}\n\n---\n\nЗапис B — "${bTitle}":\n${bBody.slice(0, 1500)}\n\nЦе одне й те саме рішення?`
|
|
251
|
-
const parse =
|
|
259
|
+
const parse = raw => EdgeSchema.parse(extractJson(raw))
|
|
252
260
|
const votes = []
|
|
253
261
|
for (let v = 0; v < nVotes; v++) {
|
|
254
262
|
try {
|
|
255
|
-
votes.push(
|
|
263
|
+
votes.push(
|
|
264
|
+
await callWithCascade([{ role: 'system', content: EDGE_SYS }, { role: 'user', content: user }], parse, {
|
|
265
|
+
label: 'edge',
|
|
266
|
+
allowCloud: cfg.allowCloud,
|
|
267
|
+
stats: cfg.stats,
|
|
268
|
+
maxTokens: 300
|
|
269
|
+
})
|
|
270
|
+
)
|
|
256
271
|
} catch {
|
|
257
272
|
votes.push({ same: false, confidence: 0, reason: 'judge failed → conservative different' })
|
|
258
273
|
}
|
|
259
274
|
}
|
|
260
|
-
const sameCount = votes.filter(
|
|
275
|
+
const sameCount = votes.filter(v => v.same && v.confidence >= minConf).length
|
|
261
276
|
return { same: sameCount === votes.length, votes }
|
|
262
277
|
}
|
|
263
278
|
|
|
@@ -275,11 +290,16 @@ const KIND_SYS = `Ти оцінюєш чернетку архітектурно
|
|
|
275
290
|
Поверни ЛИШЕ JSON: { "kind": "standalone"|"trivial", "reason": "<коротко українською>" }
|
|
276
291
|
Якщо сумніваєшся — "standalone" (краще зберегти).`
|
|
277
292
|
|
|
278
|
-
function judgeKind(title, body, cfg) {
|
|
293
|
+
async function judgeKind(title, body, cfg) {
|
|
279
294
|
const user = `Чернетка — "${title}":\n${body.slice(0, 2500)}\n\nstandalone чи trivial?`
|
|
280
|
-
const parse =
|
|
295
|
+
const parse = raw => KindSchema.parse(extractJson(raw))
|
|
281
296
|
try {
|
|
282
|
-
return callWithCascade([{ role: 'system', content: KIND_SYS }, { role: 'user', content: user }], parse, {
|
|
297
|
+
return await callWithCascade([{ role: 'system', content: KIND_SYS }, { role: 'user', content: user }], parse, {
|
|
298
|
+
label: 'kind',
|
|
299
|
+
allowCloud: cfg.allowCloud,
|
|
300
|
+
stats: cfg.stats,
|
|
301
|
+
maxTokens: 200
|
|
302
|
+
})
|
|
283
303
|
} catch {
|
|
284
304
|
return { kind: 'standalone', reason: 'judge failed → conservative standalone' }
|
|
285
305
|
}
|
|
@@ -424,20 +444,28 @@ export function assembleMadr({ title, date, sections: s }) {
|
|
|
424
444
|
].join('\n')
|
|
425
445
|
}
|
|
426
446
|
|
|
427
|
-
export function genMadr(title, body, captured, cfg, file = '') {
|
|
447
|
+
export async function genMadr(title, body, captured, cfg, file = '') {
|
|
428
448
|
const date = madrDate(captured, file)
|
|
429
449
|
const slug = slugify(title)
|
|
430
450
|
const user = `Чернетка "${title}":\n\n${body.slice(0, 4000)}\n\nВитягни зміст рішення у JSON.`
|
|
431
|
-
const parse =
|
|
451
|
+
const parse = raw => {
|
|
432
452
|
const sections = normalizeSections(extractJson(raw))
|
|
433
|
-
if (!sections.context && !sections.chosen && !sections.rationale)
|
|
453
|
+
if (!sections.context && !sections.chosen && !sections.rationale) {
|
|
454
|
+
throw new Error('empty extraction (no context/decision)')
|
|
455
|
+
}
|
|
434
456
|
const content = assembleMadr({ title, date, sections })
|
|
435
457
|
const v = validateMadr(content)
|
|
436
458
|
if (!v.ok) throw new Error(`MADR invalid: ${v.errors.join('; ')}`)
|
|
437
459
|
return content
|
|
438
460
|
}
|
|
439
461
|
try {
|
|
440
|
-
const content = callWithCascade([{ role: 'system', content: GEN_SYS }, { role: 'user', content: user }], parse, {
|
|
462
|
+
const content = await callWithCascade([{ role: 'system', content: GEN_SYS }, { role: 'user', content: user }], parse, {
|
|
463
|
+
label: 'gen',
|
|
464
|
+
allowCloud: cfg.allowCloud,
|
|
465
|
+
stats: cfg.stats,
|
|
466
|
+
attempts: 3,
|
|
467
|
+
maxTokens: 2048
|
|
468
|
+
})
|
|
441
469
|
return { content, slug, valid: true }
|
|
442
470
|
} catch (error) {
|
|
443
471
|
cfg.stats.madrInvalid++
|
|
@@ -451,7 +479,7 @@ export function genMadr(title, body, captured, cfg, file = '') {
|
|
|
451
479
|
// новий зміст-прозу; заголовок із детермінованою датою додає genMerge.
|
|
452
480
|
const MERGE_SYS = `Ти готуєш короткий додаток до існуючого ADR. Напиши ЛИШЕ новий зміст (проза/bullets), якого ще НЕМА в цільовому ADR — уточнення/виправлення/продовження. Стисло, українською, без заголовків, без code-fence, без передмови.`
|
|
453
481
|
|
|
454
|
-
function genMerge(title, body, captured, targetTitle, cfg, file = '') {
|
|
482
|
+
async function genMerge(title, body, captured, targetTitle, cfg, file = '') {
|
|
455
483
|
const date = madrDate(captured, file)
|
|
456
484
|
const user = `Цільовий ADR: "${targetTitle}".\nЧернетка-доповнення "${title}" (${date}):\n${body.slice(0, 2500)}\n\nЛише новий зміст, без заголовка.`
|
|
457
485
|
const head = `## Update ${date}`
|
|
@@ -464,7 +492,13 @@ function genMerge(title, body, captured, targetTitle, cfg, file = '') {
|
|
|
464
492
|
return `${head}\n\n${cleaned}`
|
|
465
493
|
}
|
|
466
494
|
try {
|
|
467
|
-
return callWithCascade([{ role: 'system', content: MERGE_SYS }, { role: 'user', content: user }], parse, {
|
|
495
|
+
return await callWithCascade([{ role: 'system', content: MERGE_SYS }, { role: 'user', content: user }], parse, {
|
|
496
|
+
label: 'merge',
|
|
497
|
+
allowCloud: cfg.allowCloud,
|
|
498
|
+
stats: cfg.stats,
|
|
499
|
+
attempts: 2,
|
|
500
|
+
maxTokens: 1500
|
|
501
|
+
})
|
|
468
502
|
} catch {
|
|
469
503
|
return `${head}\n\n(доповнення з чернетки "${title}")`
|
|
470
504
|
}
|
|
@@ -498,7 +532,7 @@ const noop = () => {
|
|
|
498
532
|
* @param {{allowCloud?:boolean, votes?:number, onProgress?:(m:string)=>void}} [opts] хмарна ескалація, кількість голосів і колбек прогресу
|
|
499
533
|
* @returns {{operations:object[], stats:object, trace:object}} операції apply-ops, лічильники та діагностичний trace
|
|
500
534
|
*/
|
|
501
|
-
export function normalizePipeline(drafts, cleanList, opts = {}) {
|
|
535
|
+
export async function normalizePipeline(drafts, cleanList, opts = {}) {
|
|
502
536
|
const allowCloud = opts.allowCloud ?? false
|
|
503
537
|
const log = opts.onProgress ?? noop
|
|
504
538
|
const stats = { localCalls: 0, cloudCalls: 0, escalations: 0, failures: 0, madrInvalid: 0 }
|
|
@@ -522,7 +556,7 @@ export function normalizePipeline(drafts, cleanList, opts = {}) {
|
|
|
522
556
|
const dsu = makeDSU(drafts.length)
|
|
523
557
|
const confirmedDD = []
|
|
524
558
|
for (const [i, j] of dd) {
|
|
525
|
-
const r = judgeEdge(titles[i], drafts[i].body, titles[j], drafts[j].body, cfg, { votes: 3, minConf: 0.6 })
|
|
559
|
+
const r = await judgeEdge(titles[i], drafts[i].body, titles[j], drafts[j].body, cfg, { votes: 3, minConf: 0.6 })
|
|
526
560
|
if (r.same) { dsu.union(i, j); confirmedDD.push([i, j]) }
|
|
527
561
|
}
|
|
528
562
|
log(`edge-judge: ${confirmedDD.length}/${dd.length} draft-draft ребер підтверджено`)
|
|
@@ -534,7 +568,7 @@ export function normalizePipeline(drafts, cleanList, opts = {}) {
|
|
|
534
568
|
for (const [i, cands] of dcByDraft) {
|
|
535
569
|
for (const c of cands) {
|
|
536
570
|
const cTitle = stripAdrName(c)
|
|
537
|
-
const r = judgeEdge(titles[i], drafts[i].body, cTitle, cTitle, cfg)
|
|
571
|
+
const r = await judgeEdge(titles[i], drafts[i].body, cTitle, cTitle, cfg)
|
|
538
572
|
if (r.same) { cleanTarget[i] = c; break }
|
|
539
573
|
}
|
|
540
574
|
}
|
|
@@ -578,7 +612,7 @@ export function normalizePipeline(drafts, cleanList, opts = {}) {
|
|
|
578
612
|
// одинаки без clean-target → kind-judge
|
|
579
613
|
for (let i = 0; i < drafts.length; i++) {
|
|
580
614
|
if (decision[i].op === 'kind') {
|
|
581
|
-
const k = judgeKind(titles[i], drafts[i].body, cfg)
|
|
615
|
+
const k = await judgeKind(titles[i], drafts[i].body, cfg)
|
|
582
616
|
decision[i] = k.kind === 'trivial' ? { op: 'delete', reason: k.reason } : { op: 'rewrite' }
|
|
583
617
|
}
|
|
584
618
|
}
|
|
@@ -587,7 +621,7 @@ export function normalizePipeline(drafts, cleanList, opts = {}) {
|
|
|
587
621
|
const slugByIdx = Array.from({ length: drafts.length }).fill(null)
|
|
588
622
|
for (let i = 0; i < drafts.length; i++) {
|
|
589
623
|
if (decision[i].op !== 'rewrite') continue
|
|
590
|
-
const g = genMadr(titles[i], drafts[i].body, captured[i], cfg, drafts[i].file)
|
|
624
|
+
const g = await genMadr(titles[i], drafts[i].body, captured[i], cfg, drafts[i].file)
|
|
591
625
|
slugByIdx[i] = g.slug
|
|
592
626
|
if (g.valid) {
|
|
593
627
|
operations.push({ op: 'rewrite', file: drafts[i].file, slug: g.slug, content: g.content })
|
|
@@ -603,11 +637,11 @@ export function normalizePipeline(drafts, cleanList, opts = {}) {
|
|
|
603
637
|
if (d.op === 'merge-anchor') {
|
|
604
638
|
const slug = slugByIdx[d.anchorIdx]
|
|
605
639
|
if (!slug) { log(`merge-anchor ${drafts[i].file}: anchor gen failed → skip`); continue }
|
|
606
|
-
const add = genMerge(titles[i], drafts[i].body, captured[i], titles[d.anchorIdx], cfg, drafts[i].file)
|
|
640
|
+
const add = await genMerge(titles[i], drafts[i].body, captured[i], titles[d.anchorIdx], cfg, drafts[i].file)
|
|
607
641
|
operations.push({ op: 'merge-into', file: drafts[i].file, target: `${slug}.md`, additions: add })
|
|
608
642
|
} else if (d.op === 'merge-existing') {
|
|
609
643
|
const cTitle = stripAdrName(d.target)
|
|
610
|
-
const add = genMerge(titles[i], drafts[i].body, captured[i], cTitle, cfg, drafts[i].file)
|
|
644
|
+
const add = await genMerge(titles[i], drafts[i].body, captured[i], cTitle, cfg, drafts[i].file)
|
|
611
645
|
operations.push({ op: 'merge-into', file: drafts[i].file, target: d.target, additions: add })
|
|
612
646
|
} else if (d.op === 'delete') {
|
|
613
647
|
operations.push({ op: 'delete', file: drafts[i].file, reason: d.reason })
|
|
@@ -3,24 +3,24 @@ type: JS Module
|
|
|
3
3
|
title: discover-checkable-rules.mjs
|
|
4
4
|
resource: npm/scripts/lib/discover-checkable-rules.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: d06cd969
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
## Огляд
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Визначає наявність JS-концернів та policy-концернів у заданому каталозі правила. Сканує всі каталоги правил, шукаючи JS-концерни у файлах `rules/<id>/js/<concern>.mjs` та policy-концерни, що асоціюються з парою `<concern>.rego` та `target.json`. Повертає список правил, які містять такі прогонні частини. Файли з префіксом `_` або `*.test.mjs` ігноруються.
|
|
14
14
|
|
|
15
15
|
## Поведінка
|
|
16
16
|
|
|
17
|
-
discoverOneRule описує
|
|
18
|
-
discoverCheckableRules сканує каталог
|
|
17
|
+
discoverOneRule описує правило, виявляючи JS-концерни та policy-концерни в заданому каталозі правила.
|
|
18
|
+
discoverCheckableRules сканує каталог правил і повертає список правил, які мають JS-концерни або policy-концерни, фільтруючи ті, що не мають прогонних частин.
|
|
19
19
|
|
|
20
20
|
## Публічний API
|
|
21
21
|
|
|
22
|
-
discoverOneRule —
|
|
23
|
-
discoverCheckableRules —
|
|
22
|
+
- discoverOneRule — Створює об'єкт для одного правила, що перевіряє конкретний каталог.
|
|
23
|
+
- discoverCheckableRules — Знаходить правила у каталозі `rules/`, які мають відповідні скрипти (у `js/`) або політики (у `policy/`). Ігнорує правила, що містять лише документацію.
|
|
24
24
|
|
|
25
25
|
## Гарантії поведінки
|
|
26
26
|
|
|
@@ -3,22 +3,24 @@ type: JS Module
|
|
|
3
3
|
title: inline-template-links.mjs
|
|
4
4
|
resource: npm/scripts/lib/inline-template-links.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 252fb1e1
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Огляд
|
|
12
|
+
|
|
13
|
+
Модуль збагачує текстовий контент, використовуючи конфігурації з package.json.snippet.json та package.json. Функція inlineTemplateLinks замінює текстові посилання на шаблони вбудованими блоками, якщо відповідні файли знаходяться у директорії правил. Функція appendDiscoveredMdcFiles доповнює текст вмістом усіх знайдених файлів `.mdc` з піддиректорій `js/` та `policy/` у директорії правил.
|
|
12
14
|
|
|
13
15
|
## Поведінка
|
|
14
16
|
|
|
15
|
-
inlineTemplateLinks замінює посилання на шаблони в тексті на вбудовані блоки з вмістом
|
|
16
|
-
appendDiscoveredMdcFiles додає вміст усіх знайдених файлів
|
|
17
|
+
inlineTemplateLinks замінює посилання на шаблони в тексті на вбудовані блоки з вмістом файлу, якщо ці файли існують у вказаній директорії правил.
|
|
18
|
+
appendDiscoveredMdcFiles додає до кінця тексту вміст усіх знайдених файлів `.mdc` з піддиректорій `js/` та `policy/` у директорії правил.
|
|
17
19
|
|
|
18
20
|
## Публічний API
|
|
19
21
|
|
|
20
|
-
inlineTemplateLinks — Замінює посилання
|
|
21
|
-
appendDiscoveredMdcFiles — Додає всі знайдені файли
|
|
22
|
+
inlineTemplateLinks — Замінює посилання на шаблони в Markdown на вбудовані блоки, якщо шлях містить `/template/`. Помилка виникає, якщо цільовий файл посилання відсутній.
|
|
23
|
+
appendDiscoveredMdcFiles — Додає всі знайдені файли `.mdc` з папок `js/` та `policy/<concern>/`. Файли з `js/` йдуть першими, а потім файли з підпапок `policy/<concern>/` (у алфавітному порядку за `concern`, а потім за назвою файлу).
|
|
22
24
|
|
|
23
25
|
## Гарантії поведінки
|
|
24
26
|
|
|
@@ -3,17 +3,19 @@ type: JS Module
|
|
|
3
3
|
title: list-project-rules-mdc.mjs
|
|
4
4
|
resource: npm/scripts/lib/list-project-rules-mdc.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 59fe0e6e
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Огляд
|
|
12
|
+
|
|
13
|
+
Цей модуль визначає шлях до правил у проєкті-споживачі, що константою експортується як CURSOR_RULES_DIR=".cursor/rules". Він надає відсортований список імен файлів `.mdc` з каталогу правил. Це дозволяє розділити логіку диспетчеризації командного інтерфейсу та логіку перевірки конформності. Функція зчитує та повертає список файлів, якщо каталог правил існує.
|
|
12
14
|
|
|
13
15
|
## Поведінка
|
|
14
16
|
|
|
15
17
|
CURSOR_RULES_DIR — Вказує на каталог правил у проєкті-споживачі.
|
|
16
|
-
listProjectRulesMdcFiles — Повертає відсортований список імен файлів
|
|
18
|
+
listProjectRulesMdcFiles — Повертає відсортований список імен файлів `.mdc` з каталогу правил проєкту-споживача, якщо цей каталог існує.
|
|
17
19
|
|
|
18
20
|
## Публічний API
|
|
19
21
|
|
|
@@ -3,30 +3,27 @@ type: JS Module
|
|
|
3
3
|
title: root-notice.mjs
|
|
4
4
|
resource: npm/scripts/lib/root-notice.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 65db7d81
|
|
7
|
+
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
+
score: 100
|
|
7
9
|
---
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
## Огляд
|
|
12
|
+
|
|
13
|
+
Цей модуль вшиває інструкцію для агента у файл `SKILL.md`. Інструкція вказує, що скіл мутує проєкт у поточному каталозі, але виконується in-place (без worktree-ізоляції), що відповідає конфігурації `meta.json` $\to$ `requireRoot: true` і `worktree: false`. Це застосовується до скілів, які змінюють `meta.json` або `package.json` безпосередньо, на відміну від worktree-скілів, які мають свій `root-assert` у `worktree-notice.mjs`. Блок є інструкцією агенту, що читає `SKILL.md`, і є ре-синк ідемпотентним: наявний блок замінюється, при `false` — видаляється. Програмний аналог для CLI-команд — `assertCwdIsProjectRoot`. Інструкція позначається маркерами `ROOT_START` ("<!-- n-cursor:root:start -->") та `ROOT_END` ("<!-- n-cursor:root:end -->").
|
|
10
14
|
|
|
11
15
|
## Поведінка
|
|
12
16
|
|
|
13
|
-
ROOT_START:
|
|
14
|
-
ROOT_END:
|
|
15
|
-
injectRootNotice:
|
|
17
|
+
ROOT_START: Позначає початок блоку інструкції щодо перевірки кореня репозиторію.
|
|
18
|
+
ROOT_END: Позначає кінець блоку інструкції щодо перевірки кореня репозиторію.
|
|
19
|
+
injectRootNotice: Вставляє, оновлює або видаляє блок інструкції щодо перевірки кореня репозиторію у вмісті файлу `SKILL.md` на основі булевого прапорця.
|
|
16
20
|
|
|
17
21
|
## Публічний API
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
ROOT_START — маркер початку основного блоку документації.
|
|
24
|
+
ROOT_END — маркер завершення основного блоку документації.
|
|
25
|
+
injectRootNotice — додає, змінює або видаляє захисний блок у файлі `SKILL.md`.
|
|
22
26
|
|
|
23
27
|
## Гарантії поведінки
|
|
24
28
|
|
|
25
|
-
-
|
|
26
|
-
- Якщо `requireRoot: false`, то блок не вставляється.
|
|
27
|
-
- Вставка відбувається лише між маркерами.
|
|
28
|
-
- Вставка ре-синк ідемпотентно: наявний блок замінюється.
|
|
29
|
-
- `ROOT_START` викликається перед вставкою блоку.
|
|
30
|
-
- `ROOT_END` викликається після вставки блоку.
|
|
31
|
-
- `injectRootNotice` викликається під час вставки блоку.
|
|
32
|
-
- Немає кешування.
|
|
29
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -3,26 +3,28 @@ type: JS Module
|
|
|
3
3
|
title: run-lint.mjs
|
|
4
4
|
resource: npm/scripts/lib/run-lint.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 3c7deca0
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Огляд
|
|
12
|
+
|
|
13
|
+
Модуль визначає набір правил лінтування, спираючись на конфігурації `meta.json` та `.n-cursor.json`. Він використовує `selectLintRules` для вибору та сортування цих правил, а потім ініціалізує процес перевірки конформності та форматування за допомогою `runLint` у різних режимах (scoped, hook, delta, full).
|
|
12
14
|
|
|
13
15
|
## Поведінка
|
|
14
16
|
|
|
15
|
-
selectLintRules
|
|
16
|
-
runLint запускає
|
|
17
|
+
selectLintRules вибирає і алфавітно сортує ідентифікатори правил для лінтування на основі їхньої метаінформації та стану активації в `.n-cursor.json`.
|
|
18
|
+
runLint запускає лінт-оркестрацію, виконуючи різні режими залежно від наданих опцій: scoped (за назвами правил), hook (за явним списком файлів), delta (зміна відносно origin) або full (весь репозиторій), включаючи конформність та форматування у fix-режимі.
|
|
17
19
|
|
|
18
20
|
## Публічний API
|
|
19
21
|
|
|
20
|
-
selectLintRules —
|
|
22
|
+
selectLintRules — обирає ідентифікатори правил для контексту, у алфавітному порядку.
|
|
21
23
|
runLint — ініціює процес лінтування.
|
|
22
24
|
full — аналізує весь репозиторій, порівнюючи поточний стан із початковим.
|
|
23
|
-
readOnly — лише виявляє
|
|
24
|
-
rules — виконує повний прогін лише для заданого набору
|
|
25
|
-
files —
|
|
25
|
+
readOnly — лише виявляє проблеми без внесення змін.
|
|
26
|
+
rules — виконує повний прогін лише для заданого набору правил.
|
|
27
|
+
files — застосовує правила до конкретного переліку файлів у режимі хука.
|
|
26
28
|
|
|
27
29
|
## Гарантії поведінки
|
|
28
30
|
|
|
@@ -3,26 +3,45 @@ type: JS Module
|
|
|
3
3
|
title: skill-meta.mjs
|
|
4
4
|
resource: npm/scripts/lib/skill-meta.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: fd8085f3
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
|
+
issues: judge:inaccurate:0.99
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
9
11
|
---
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
Спільний парсер метаданих скіла з `npm/skills/<id>/main.json`. Цей механізм зчитує та інтерпретує конфігурацію скіла, використовуючи `main.json` як єдине джерело правди. Він визначає умову автоактивації (`auto`, де `SKILL_ALWAYS` означає безумовну активацію), необхідність роботи з кореневою директорією (`requireRoot`), та визначає, чи повинен скіл виконуватися ізольовано в окремому git-worktree (`worktree`).
|
|
16
|
+
|
|
17
|
+
Поведінка
|
|
18
|
+
SKILL_ALWAYS — Константа-рядок, яка позначає, що скіл має бути активований завжди.
|
|
19
|
+
SKILL_TIERS — Список допустимих рівнів моделі для виконання скіла.
|
|
20
|
+
DEFAULT_SKILL_TIER — Константа-рядок, яка встановлює рівень моделі за замовчуванням, якщо він не вказаний у метаданих.
|
|
21
|
+
parseSkillAutoSpec — Визначає умови, за яких скіл може бути автоматично активований, ґрунтуючись на конфігурації `main.json`.
|
|
22
|
+
skillRequiresRoot — Визначає, чи вимагає скіл запуску з кореневої директорії репозиторію. Зверніть увагу, що скіли з `worktree:true` не вимагають цього поля явно, оскільки коренем є сам worktree.
|
|
23
|
+
skillTier — Визначає рівень моделі, який буде використаний для виконання скіла, враховуючи конфігурацію `main.json` або повертаючи `DEFAULT_SKILL_TIER`.
|
|
24
|
+
readSkillMetaRaw — Зчитує та парсить сирі метадані скіла з файлу `main.json`. При виявленні помилок парсингу або в IO-операціях, функція не генерує винятки, а повертає `null` (fail-safe).
|
|
12
25
|
|
|
13
26
|
## Поведінка
|
|
14
27
|
|
|
15
|
-
SKILL_ALWAYS —
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
28
|
+
SKILL_ALWAYS — Константа, що позначає безумовну активацію скіла.
|
|
29
|
+
SKILL_TIERS — Список допустимих рівнів моделі для виконання скіла.
|
|
30
|
+
DEFAULT_SKILL_TIER — Тир моделі, який застосовується за замовчуванням, якщо рівень не вказаний у метаданих.
|
|
31
|
+
parseSkillAutoSpec — Визначає, як скіл може бути автоматично активований на основі конфігурації `main.json`.
|
|
32
|
+
skillRequiresRoot — Визначає, чи повинен скіл виконуватися з кореневої директорії репозиторію, базуючись на налаштуваннях `main.json`.
|
|
33
|
+
skillTier — Визначає рівень моделі, який буде використано для виконання скіла, приймаючи в до уваги значення з `main.json` або повертаючи `DEFAULT_SKILL_TIER`.
|
|
34
|
+
readSkillMetaRaw — Зчитує та парсить метадані скіла з файлу `main.json` за вказаним шляхом, обробляючи можливі помилки формату.
|
|
19
35
|
|
|
20
36
|
## Публічний API
|
|
21
37
|
|
|
22
|
-
SKILL_ALWAYS —
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
38
|
+
**SKILL_ALWAYS** — позначка, що робить скіл автоматично активним у будь-якій ситуації.
|
|
39
|
+
**SKILL_TIERS** — список допустимих рівнів (тирів) моделей, які можуть виконувати скіл через `pi`-runner.
|
|
40
|
+
**DEFAULT_SKILL_TIER** — рівень моделі, який використовується за замовчуванням для скілів, якщо `main.json` цього скіла не вказує конкретний рівень.
|
|
41
|
+
**parseSkillAutoSpec** — визначає, чи має скіл автоматично запускатися на основі конфігурації в `main.json`.
|
|
42
|
+
**skillRequiresRoot** — позначає, чи повинен скіл виконуватися з кореневої директорії репозиторію; це захист від несанкціонованого запуску.
|
|
43
|
+
**skillTier** — визначає необхідний рівень моделі для виконання скіла, використовуючи значення з `main.json` або встановлюючи `DEFAULT_SKILL_TIER`.
|
|
44
|
+
**readSkillMetaRaw** — зчитує та аналізує метадані конкретного скіла з файлу `main.json`.
|
|
26
45
|
|
|
27
46
|
## Гарантії поведінки
|
|
28
47
|
|
|
@@ -3,28 +3,25 @@ type: JS Module
|
|
|
3
3
|
title: discover-t0-patterns.mjs
|
|
4
4
|
resource: npm/scripts/lib/fix/discover-t0-patterns.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 3f3b47e0
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
## Огляд
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Сканує директорії `npm/rules/{rule}/js/fix-*.mjs` та `npm/rules/{rule}/policy/{concern}/fix-*.mjs` для всіх правил. Динамічно імпортує кожен знайдений файл `fix-*.mjs` та збирає масиви `patterns`. Результат ініціалізується через top-level await у `t0.mjs` і представляє унікальний список усіх виявлених T0-паттернів. Функція не виконує операцій запису та перехоплює помилки, повертаючи `null` у випадку збоїв замість викидання винятків.
|
|
14
14
|
|
|
15
15
|
## Поведінка
|
|
16
16
|
|
|
17
|
-
1. Перевіряє існування
|
|
18
|
-
2.
|
|
19
|
-
3. Для кожного
|
|
20
|
-
а.
|
|
21
|
-
б.
|
|
22
|
-
в.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
е. У разі помилки імпорту, помилка виводиться в консоль, але процес продовжується.
|
|
26
|
-
4. Після обробки всіх правил, виконується дедуплікація загального списку паттернів за їхніми ідентифікаторами.
|
|
27
|
-
5. Повертається фінальний, унікальний масив T0-паттернів.
|
|
17
|
+
1. Перевіряє існування шляху `rulesDir`. Якщо шлях не існує, повертає порожній масив.
|
|
18
|
+
2. Знаходить усі файли з шаблонами у шляхах `*/js/fix-*.mjs` та `*/policy/*/fix-*.mjs` у межах `rulesDir`.
|
|
19
|
+
3. Для кожного знайденого файлу:
|
|
20
|
+
а. Намагається динамічно імпортувати вміст файлу.
|
|
21
|
+
б. Якщо імпорт успішний і вміст містить масив `patterns`, додає ці паттерни до загального списку.
|
|
22
|
+
в. Якщо імпорт не вдається, реєструє помилку, але продовжує роботу.
|
|
23
|
+
4. Фільтрує загальний список паттернів, щоб уникнути дублікатів, зберігаючи лише перше входження кожного паттерна за його ідентифікатором.
|
|
24
|
+
5. Повертає відфільтрований масив унікальних T0-паттернів.
|
|
28
25
|
|
|
29
26
|
## Публічний API
|
|
30
27
|
|
|
@@ -3,25 +3,26 @@ type: JS Module
|
|
|
3
3
|
title: escalation-log.mjs
|
|
4
4
|
resource: npm/scripts/lib/fix/escalation-log.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 91898427
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Огляд
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Файл створює append-only JSONL-лог ескалації конформність-фіксу (спека 2026-06-19-fix-escalation-cascade-design). Він фіксує кожен запис на рунг драбини, що включає деталі використаної моделі (`model`), подання зворотного зв'язку (`withFeedback`), результат виклику (`callOk`/`callError`), оцінку, чи допомогло це усунути порушення (`recheckOk`), залишковий `violation` та самоаналіз моделі (`diagnosis`). Цей лог доповнює always-on wire-trace (`lib/pi-trace.mjs`) і формує логіку для join за полем `caller` (`fix:<rule>:<rung>`). Запис відбувається за певним шільною: або через kill-switch `N_CURSOR_FIX_ESCALATION_LOG`, або за явним шляхом, дефолтно у `<cwd>/.n-cursor/fix-escalation.jsonl`.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
## Поведінка
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Поведінка:
|
|
18
|
+
escalationLogPath визначає шлях до файлу журналу ескалації конформності. Якщо встановлено змінну середовища N_CURSOR_FIX_ESCALATION_LOG, використовується цей шлях; інакше, за замовчуванням, це .n-cursor/fix-escalation.jsonl у поточній робочій директорії.
|
|
19
|
+
logEscalation записує один запис про рунг у JSONL-лог, якщо шлях до логу визначено. Запис містить метадані про спробу фіксування, результати виклику та аналіз. Помилки під час запису логу ігноруються.
|
|
18
20
|
|
|
19
21
|
## Публічний API
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
escalationLogPath — вказує на місце зберігання логу ескалацій, якщо функція не вимкнена.
|
|
24
|
+
logEscalation — записує один подію виконання в спеціальний лог у форматі JSONL, ігноруючи внутрішні помилки запису.
|
|
23
25
|
|
|
24
26
|
## Гарантії поведінки
|
|
25
27
|
|
|
26
|
-
-
|
|
27
|
-
- Перехоплює помилки запису і не пропускає винятків назовні (fail-safe).
|
|
28
|
+
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
@@ -8,7 +8,6 @@ resource: npm/scripts/lib/fix/
|
|
|
8
8
|
|
|
9
9
|
| Файл | Тип |
|
|
10
10
|
| ----------------------------------------------------- | --------- |
|
|
11
|
-
| [analyze-escalation.mjs](analyze-escalation.md) | JS Module |
|
|
12
11
|
| [discover-t0-patterns.mjs](discover-t0-patterns.md) | JS Module |
|
|
13
12
|
| [escalation-log.mjs](escalation-log.md) | JS Module |
|
|
14
13
|
| [llm-fix-apply.mjs](llm-fix-apply.md) | JS Module |
|