@nitra/cursor 12.6.1 → 12.8.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/.claude-template/settings.template.json +1 -1
- package/.pi-template/extensions/n-cursor-adr/docs/index.md +2 -2
- package/CHANGELOG.md +25 -5
- package/bin/docs/n-cursor.md +4 -20
- package/bin/n-cursor.js +8 -54
- package/docs/index.md +3 -3
- package/docs/stryker.config.md +20 -28
- package/lib/docs/index.md +5 -5
- package/lib/docs/llm.md +4 -4
- package/package.json +2 -2
- package/rules/abie/docs/fix.md +8 -8
- package/rules/abie/docs/index.md +4 -3
- package/rules/abie/docs/main.md +29 -0
- package/rules/abie/js/docs/index.md +6 -6
- package/rules/abie/lib/docs/index.md +9 -9
- package/rules/abie/{fix.mjs → main.mjs} +5 -3
- package/rules/adr/docs/index.md +1 -0
- package/rules/adr/docs/main.md +29 -0
- package/rules/adr/{fix.mjs → main.mjs} +5 -3
- package/rules/bun/docs/fix.md +5 -5
- package/rules/bun/docs/index.md +4 -3
- package/rules/bun/docs/main.md +30 -0
- package/rules/bun/js/docs/index.md +2 -2
- package/rules/bun/js/docs/layout.md +11 -36
- package/rules/bun/{fix.mjs → main.mjs} +5 -3
- package/rules/capacitor/docs/fix.md +10 -10
- package/rules/capacitor/docs/index.md +4 -3
- package/rules/capacitor/docs/main.md +29 -0
- package/rules/capacitor/js/docs/index.md +2 -2
- package/rules/capacitor/{fix.mjs → main.mjs} +5 -3
- package/rules/changelog/docs/fix.md +11 -11
- package/rules/changelog/docs/index.md +4 -3
- package/rules/changelog/docs/main.md +27 -0
- package/rules/changelog/js/docs/consistency.md +12 -12
- package/rules/changelog/js/docs/index.md +2 -2
- package/rules/changelog/lib/docs/index.md +2 -2
- package/rules/changelog/main.mjs +20 -0
- package/rules/ci4/docs/fix.md +4 -4
- package/rules/ci4/docs/index.md +4 -3
- package/rules/ci4/docs/main.md +30 -0
- package/rules/ci4/js/docs/index.md +2 -2
- package/rules/ci4/main.mjs +20 -0
- package/rules/doc-files/docs/index.md +4 -3
- package/rules/doc-files/docs/main.md +31 -0
- package/rules/doc-files/js/docgen-crc.mjs +2 -8
- package/rules/doc-files/js/docgen-extract.mjs +5 -3
- package/rules/doc-files/js/docgen-files-batch.mjs +63 -4
- package/rules/doc-files/js/docgen-gen.mjs +11 -3
- package/rules/doc-files/js/docgen-judge-measure.mjs +67 -18
- package/rules/doc-files/js/docgen-judge.mjs +8 -1
- package/rules/doc-files/js/docgen-scan.mjs +99 -11
- package/rules/doc-files/js/docs/docgen-crc.md +25 -14
- package/rules/doc-files/js/docs/docgen-extract.md +15 -13
- package/rules/doc-files/js/docs/docgen-files-batch.md +15 -15
- package/rules/doc-files/js/docs/docgen-gen.md +15 -26
- package/rules/doc-files/js/docs/docgen-judge-measure.md +14 -12
- package/rules/doc-files/js/docs/docgen-scan.md +34 -34
- package/rules/doc-files/js/docs/index.md +16 -15
- package/rules/doc-files/js/docs/run-lint.md +27 -0
- package/rules/doc-files/{lint/lint.mjs → js/run-lint.mjs} +23 -9
- package/rules/doc-files/{js/lint.mjs → main.mjs} +60 -10
- package/rules/docker/docs/fix.md +6 -6
- package/rules/docker/docs/index.md +4 -3
- package/rules/docker/docs/main.md +28 -0
- package/rules/docker/js/docs/index.md +2 -2
- package/rules/docker/js/docs/lint.md +26 -54
- package/rules/docker/js/lint.mjs +11 -0
- package/rules/docker/lib/docker-hadolint.mjs +1 -1
- package/rules/docker/lib/docs/docker-hadolint.md +16 -173
- package/rules/docker/lib/docs/index.md +5 -5
- package/rules/docker/main.mjs +20 -0
- package/rules/efes/docs/fix.md +8 -8
- package/rules/efes/docs/index.md +4 -3
- package/rules/efes/docs/main.md +29 -0
- package/rules/efes/main.mjs +20 -0
- package/rules/feedback/docs/fix.md +5 -5
- package/rules/feedback/docs/index.md +4 -3
- package/rules/feedback/docs/main.md +30 -0
- package/rules/feedback/main.mjs +20 -0
- package/rules/ga/docs/fix.md +5 -5
- package/rules/ga/docs/index.md +4 -3
- package/rules/ga/docs/main.md +29 -0
- package/rules/ga/js/docs/index.md +3 -3
- package/rules/ga/{lint/lint.mjs → main.mjs} +36 -10
- package/rules/graphql/docs/fix.md +8 -8
- package/rules/graphql/docs/index.md +4 -3
- package/rules/graphql/docs/main.md +36 -0
- package/rules/graphql/js/docs/index.md +2 -2
- package/rules/graphql/lib/docs/index.md +2 -2
- package/rules/graphql/main.mjs +20 -0
- package/rules/hasura/docs/fix.md +11 -11
- package/rules/hasura/docs/index.md +4 -3
- package/rules/hasura/docs/main.md +30 -0
- package/rules/hasura/js/docs/index.md +2 -2
- package/rules/hasura/main.mjs +20 -0
- package/rules/image-avif/docs/fix.md +3 -3
- package/rules/image-avif/docs/index.md +4 -3
- package/rules/image-avif/docs/main.md +30 -0
- package/rules/image-avif/js/docs/avif_generation.md +20 -233
- package/rules/image-avif/js/docs/index.md +2 -2
- package/rules/image-avif/main.mjs +20 -0
- package/rules/image-compress/docs/fix.md +2 -2
- package/rules/image-compress/docs/index.md +4 -3
- package/rules/image-compress/docs/main.md +29 -0
- package/rules/image-compress/js/docs/index.md +3 -3
- package/rules/image-compress/js/docs/package_setup.md +12 -11
- package/rules/image-compress/{js/lint.mjs → main.mjs} +21 -5
- package/rules/js-bun-db/docs/fix.md +5 -5
- package/rules/js-bun-db/docs/index.md +4 -3
- package/rules/js-bun-db/docs/main.md +30 -0
- package/rules/js-bun-db/js/docs/index.md +2 -2
- package/rules/js-bun-db/lib/docs/index.md +2 -2
- package/rules/js-bun-db/main.mjs +20 -0
- package/rules/js-bun-redis/docs/fix.md +6 -6
- package/rules/js-bun-redis/docs/index.md +4 -3
- package/rules/js-bun-redis/docs/main.md +29 -0
- package/rules/js-bun-redis/js/docs/index.md +2 -2
- package/rules/js-bun-redis/lib/docs/index.md +2 -2
- package/rules/js-bun-redis/main.mjs +20 -0
- package/rules/js-lint/docs/fix.md +9 -9
- package/rules/js-lint/docs/index.md +4 -3
- package/rules/js-lint/docs/main.md +29 -0
- package/rules/js-lint/js/check.mjs +268 -0
- package/rules/js-lint/js/docs/check.md +39 -0
- package/rules/js-lint/js/docs/index.md +4 -4
- package/rules/js-lint/js/docs/tooling.md +12 -32
- package/rules/js-lint/js/tooling.mjs +1 -265
- package/rules/js-lint/{js/lint.mjs → main.mjs} +19 -2
- package/rules/js-lint-ci/docs/fix.md +3 -3
- package/rules/js-lint-ci/docs/index.md +4 -3
- package/rules/js-lint-ci/docs/main.md +27 -0
- package/rules/js-lint-ci/js/docs/index.md +2 -2
- package/rules/js-lint-ci/main.mjs +33 -0
- package/rules/js-mssql/docs/fix.md +5 -5
- package/rules/js-mssql/docs/index.md +4 -3
- package/rules/js-mssql/docs/main.md +30 -0
- package/rules/js-mssql/js/docs/index.md +2 -2
- package/rules/js-mssql/lib/docs/index.md +2 -2
- package/rules/js-mssql/main.mjs +20 -0
- package/rules/js-run/docs/fix.md +8 -8
- package/rules/js-run/docs/index.md +4 -3
- package/rules/js-run/docs/main.md +30 -0
- package/rules/js-run/js/docs/index.md +2 -2
- package/rules/js-run/lib/docs/index.md +7 -7
- package/rules/js-run/main.mjs +20 -0
- package/rules/k8s/docs/fix.md +4 -4
- package/rules/k8s/docs/index.md +4 -3
- package/rules/k8s/docs/main.md +40 -0
- package/rules/k8s/js/docs/index.md +12 -0
- package/rules/k8s/{lint/lint.mjs → main.mjs} +32 -10
- package/rules/nginx-default-tpl/docs/fix.md +7 -7
- package/rules/nginx-default-tpl/docs/index.md +4 -3
- package/rules/nginx-default-tpl/docs/main.md +30 -0
- package/rules/nginx-default-tpl/js/docs/index.md +2 -2
- package/rules/nginx-default-tpl/js/docs/template.md +2 -2
- package/rules/nginx-default-tpl/main.mjs +20 -0
- package/rules/npm-module/docs/fix.md +8 -8
- package/rules/npm-module/docs/index.md +4 -3
- package/rules/npm-module/docs/main.md +29 -0
- package/rules/npm-module/js/docs/index.md +5 -5
- package/rules/npm-module/js/docs/rule_meta.md +17 -16
- package/rules/npm-module/js/header_doc_pointer.mjs +1 -3
- package/rules/npm-module/js/rule_meta.mjs +13 -3
- package/rules/npm-module/main.mjs +20 -0
- package/rules/php/docs/fix.md +6 -6
- package/rules/php/docs/index.md +4 -3
- package/rules/php/docs/main.md +33 -0
- package/rules/php/js/docs/index.md +3 -3
- package/rules/php/js/docs/tooling.md +10 -10
- package/rules/php/{lint/lint.mjs → main.mjs} +32 -6
- package/rules/python/docs/fix.md +11 -11
- package/rules/python/docs/index.md +4 -3
- package/rules/python/docs/main.md +31 -0
- package/rules/python/js/docs/index.md +3 -3
- package/rules/python/js/docs/tooling.md +17 -17
- package/rules/python/{lint/lint.mjs → main.mjs} +31 -6
- package/rules/rego/docs/fix.md +5 -5
- package/rules/rego/docs/index.md +4 -3
- package/rules/rego/docs/main.md +37 -0
- package/rules/rego/js/docs/index.md +3 -3
- package/rules/rego/{lint/lint.mjs → main.mjs} +27 -5
- package/rules/release/docs/index.md +5 -4
- package/rules/release/docs/main.md +29 -0
- package/rules/release/docs/release.md +0 -3
- package/rules/release/lib/docs/index.md +4 -4
- package/rules/release/release.mdc +10 -0
- package/rules/rust/docs/fix.md +4 -4
- package/rules/rust/docs/index.md +4 -3
- package/rules/rust/docs/main.md +27 -0
- package/rules/rust/js/docs/index.md +3 -3
- package/rules/rust/lib/docs/index.md +2 -2
- package/rules/rust/{js/lint.mjs → main.mjs} +27 -4
- package/rules/security/docs/fix.md +6 -6
- package/rules/security/docs/index.md +4 -3
- package/rules/security/docs/main.md +28 -0
- package/rules/security/js/docs/index.md +4 -4
- package/rules/security/main.mjs +45 -0
- package/rules/style-lint/docs/fix.md +3 -3
- package/rules/style-lint/docs/index.md +4 -3
- package/rules/style-lint/docs/main.md +29 -0
- package/rules/style-lint/js/docs/index.md +3 -3
- package/rules/style-lint/{js/lint.mjs → main.mjs} +19 -1
- package/rules/tauri/docs/fix.md +11 -11
- package/rules/tauri/docs/index.md +4 -3
- package/rules/tauri/docs/main.md +29 -0
- package/rules/tauri/js/docs/index.md +3 -3
- package/rules/tauri/main.mjs +20 -0
- package/rules/test/docs/fix.md +5 -5
- package/rules/test/docs/index.md +4 -3
- package/rules/test/docs/main.md +30 -0
- package/rules/test/js/data/stryker_config/docs/index.md +4 -4
- package/rules/test/js/data/vitest_config/docs/index.md +2 -2
- package/rules/test/js/docs/index.md +7 -7
- package/rules/test/main.mjs +20 -0
- package/rules/text/docs/fix.md +11 -11
- package/rules/text/docs/index.md +4 -3
- package/rules/text/docs/main.md +29 -0
- package/rules/text/{lint → js}/cspell-fix.mjs +7 -2
- package/rules/text/js/docs/cspell-fix.md +30 -0
- package/rules/text/js/docs/formatting.md +12 -45
- package/rules/text/js/docs/index.md +8 -4
- package/rules/text/js/docs/run-dotenv-linter.md +31 -0
- package/rules/text/js/docs/run-shellcheck.md +28 -0
- package/rules/text/js/docs/run-v8r.md +29 -0
- package/rules/text/{lint/lint.mjs → main.mjs} +41 -10
- package/rules/tool-surface/docs/index.md +4 -3
- package/rules/tool-surface/docs/main.md +29 -0
- package/rules/tool-surface/main.mjs +20 -0
- package/rules/tool-surface/meta.json +6 -1
- package/rules/vue/docs/fix.md +6 -6
- package/rules/vue/docs/index.md +4 -3
- package/rules/vue/docs/main.md +29 -0
- package/rules/vue/js/docs/index.md +2 -2
- package/rules/vue/lib/docs/index.md +2 -2
- package/rules/vue/main.mjs +20 -0
- package/rules/worktree/docs/fix.md +11 -11
- package/rules/worktree/docs/index.md +4 -3
- package/rules/worktree/docs/main.md +28 -0
- package/rules/worktree/main.mjs +20 -0
- package/scripts/coverage-classify/docs/index.md +6 -6
- package/scripts/dispatcher/docs/index.md +2 -2
- package/scripts/docs/index.md +16 -15
- package/scripts/docs/post-tool-use-check.md +29 -0
- package/scripts/docs/sync-claude-config.md +64 -92
- package/scripts/lib/adr/docs/normalize-cli.md +0 -3
- package/scripts/lib/adr/docs/normalize-pipeline.md +0 -3
- package/scripts/lib/docs/gha-workflow.md +25 -317
- package/scripts/lib/docs/index.md +36 -35
- package/scripts/lib/docs/list-project-rules-mdc.md +5 -4
- package/scripts/lib/docs/list-rule-ids.md +15 -148
- package/scripts/lib/docs/read-n-cursor-config-lite.md +12 -16
- package/scripts/lib/docs/run-lint-step.md +13 -13
- package/scripts/lib/docs/run-lint.md +30 -0
- package/scripts/lib/docs/run-rule-cli.md +14 -10
- package/scripts/lib/docs/run-standard-lint.md +29 -10
- package/scripts/lib/docs/run-standard-rule.md +12 -11
- package/scripts/lib/docs/timing-summary.md +11 -12
- package/scripts/lib/docs/worktree-notice.md +0 -3
- package/scripts/lib/fix/analyze-escalation.mjs +4 -1
- package/scripts/lib/fix/docs/index.md +11 -10
- package/scripts/lib/fix/docs/orchestrator.md +23 -18
- package/scripts/lib/fix/docs/run-conformance-check.md +33 -0
- package/scripts/lib/fix/docs/run-fix-check.md +3 -3
- package/scripts/lib/fix/docs/t0.md +10 -9
- package/scripts/lib/fix/orchestrator.mjs +31 -8
- package/scripts/lib/fix/{run-fix-check.mjs → run-conformance-check.mjs} +13 -13
- package/scripts/lib/fix/t0.mjs +6 -3
- package/scripts/lib/list-project-rules-mdc.mjs +1 -1
- package/scripts/lib/list-rule-ids.mjs +12 -3
- package/scripts/lib/read-n-cursor-config-lite.mjs +2 -2
- package/{rules/lint/js/orchestrate.mjs → scripts/lib/run-lint.mjs} +42 -22
- package/scripts/lib/run-rule-cli.mjs +4 -4
- package/scripts/lib/run-standard-lint.mjs +19 -6
- package/scripts/lib/run-standard-rule.mjs +4 -4
- package/scripts/lib/timing-summary.mjs +1 -1
- package/scripts/{post-tool-use-fix.mjs → post-tool-use-check.mjs} +9 -9
- package/scripts/sync-claude-config.mjs +2 -2
- package/scripts/utils/docs/index.md +14 -14
- package/skills/doc-aggregate/js/docs/index.md +3 -3
- package/skills/doc-files/.changes/260612-0002.md +1 -0
- package/skills/doc-files/.changes/260612-0006.md +1 -0
- package/skills/doc-files/.changes/260612-0008.md +1 -0
- package/skills/doc-files/.changes/260612-0012.md +1 -0
- package/skills/doc-files/.changes/260612-0031.md +1 -0
- package/skills/doc-files/.changes/260612-0036.md +1 -0
- package/skills/doc-files/.changes/260612-0114.md +1 -0
- package/skills/start-check/js/docs/index.md +2 -2
- package/skills/taze/js/docs/index.md +2 -2
- package/types/bin/n-cursor.d.ts +1 -1
- package/rules/changelog/fix.mjs +0 -18
- package/rules/ci4/fix.mjs +0 -18
- package/rules/doc-files/fix.mjs +0 -19
- package/rules/doc-files/js/docs/lint.md +0 -34
- package/rules/doc-files/lint/docs/index.md +0 -11
- package/rules/doc-files/lint/docs/lint.md +0 -35
- package/rules/docker/fix.mjs +0 -18
- package/rules/docker/lint/docs/index.md +0 -11
- package/rules/docker/lint/docs/lint.md +0 -200
- package/rules/docker/lint/lint.mjs +0 -95
- package/rules/efes/fix.mjs +0 -18
- package/rules/feedback/fix.mjs +0 -18
- package/rules/ga/fix.mjs +0 -18
- package/rules/ga/js/docs/lint.md +0 -20
- package/rules/ga/js/lint.mjs +0 -12
- package/rules/ga/lint/docs/index.md +0 -11
- package/rules/ga/lint/docs/lint.md +0 -31
- package/rules/graphql/fix.mjs +0 -18
- package/rules/hasura/fix.mjs +0 -18
- package/rules/image-avif/fix.mjs +0 -18
- package/rules/image-compress/fix.mjs +0 -18
- package/rules/image-compress/js/docs/lint.md +0 -24
- package/rules/js-bun-db/fix.mjs +0 -18
- package/rules/js-bun-redis/fix.mjs +0 -18
- package/rules/js-lint/fix.mjs +0 -18
- package/rules/js-lint/js/docs/lint.md +0 -32
- package/rules/js-lint-ci/fix.mjs +0 -18
- package/rules/js-lint-ci/js/docs/lint.md +0 -22
- package/rules/js-lint-ci/js/lint.mjs +0 -15
- package/rules/js-mssql/fix.mjs +0 -18
- package/rules/js-run/fix.mjs +0 -18
- package/rules/k8s/fix.mjs +0 -18
- package/rules/k8s/js/lint.mjs +0 -14
- package/rules/k8s/lint/docs/index.md +0 -11
- package/rules/k8s/lint/docs/lint.md +0 -413
- package/rules/lint/docs/fix.md +0 -25
- package/rules/lint/docs/index.md +0 -11
- package/rules/lint/fix.mjs +0 -18
- package/rules/lint/js/docs/index.md +0 -11
- package/rules/lint/js/docs/orchestrate.md +0 -31
- package/rules/lint/meta.json +0 -1
- package/rules/nginx-default-tpl/fix.mjs +0 -18
- package/rules/npm-module/fix.mjs +0 -18
- package/rules/php/fix.mjs +0 -18
- package/rules/php/js/docs/lint.md +0 -20
- package/rules/php/js/lint.mjs +0 -15
- package/rules/php/lint/docs/index.md +0 -11
- package/rules/php/lint/docs/lint.md +0 -219
- package/rules/python/fix.mjs +0 -18
- package/rules/python/js/docs/lint.md +0 -21
- package/rules/python/js/lint.mjs +0 -14
- package/rules/python/lint/docs/index.md +0 -11
- package/rules/python/lint/docs/lint.md +0 -29
- package/rules/rego/fix.mjs +0 -18
- package/rules/rego/js/docs/lint.md +0 -21
- package/rules/rego/js/lint.mjs +0 -12
- package/rules/rego/lint/docs/index.md +0 -11
- package/rules/rego/lint/docs/lint.md +0 -208
- package/rules/rust/fix.mjs +0 -18
- package/rules/rust/js/docs/lint.md +0 -21
- package/rules/security/fix.mjs +0 -18
- package/rules/security/js/docs/lint.md +0 -175
- package/rules/security/js/lint.mjs +0 -26
- package/rules/style-lint/fix.mjs +0 -18
- package/rules/style-lint/js/docs/lint.md +0 -31
- package/rules/tauri/fix.mjs +0 -18
- package/rules/test/fix.mjs +0 -18
- package/rules/text/fix.mjs +0 -18
- package/rules/text/js/docs/lint.md +0 -23
- package/rules/text/js/lint.mjs +0 -15
- package/rules/text/lint/docs/cspell-fix.md +0 -32
- package/rules/text/lint/docs/index.md +0 -15
- package/rules/text/lint/docs/lint.md +0 -36
- package/rules/text/lint/docs/run-dotenv-linter.md +0 -161
- package/rules/text/lint/docs/run-shellcheck.md +0 -216
- package/rules/text/lint/docs/run-v8r.md +0 -201
- package/rules/tool-surface/fix.mjs +0 -18
- package/rules/vue/fix.mjs +0 -18
- package/rules/worktree/fix.mjs +0 -18
- /package/rules/release/{fix.mjs → main.mjs} +0 -0
- /package/rules/text/{lint → js}/run-dotenv-linter.mjs +0 -0
- /package/rules/text/{lint → js}/run-shellcheck.mjs +0 -0
- /package/rules/text/{lint → js}/run-v8r.mjs +0 -0
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
/** @see ./docs/docgen-files-batch.md */
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
existsSync,
|
|
4
|
+
mkdirSync,
|
|
5
|
+
readdirSync,
|
|
6
|
+
readFileSync,
|
|
7
|
+
rmdirSync,
|
|
8
|
+
statSync,
|
|
9
|
+
unlinkSync,
|
|
10
|
+
writeFileSync
|
|
11
|
+
} from 'node:fs'
|
|
3
12
|
import { basename, dirname, join, relative } from 'node:path'
|
|
4
13
|
|
|
5
14
|
import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
|
|
6
15
|
import { classifyOmlxError, preflightLocalModel } from '../../../lib/llm.mjs'
|
|
7
16
|
import { generateDoc, DEFAULT_LOCAL_MODEL } from './docgen-gen.mjs'
|
|
8
17
|
import { crc32, stampDoc, readDocQuality, readDocModel, QUALITY_THRESHOLD } from './docgen-crc.mjs'
|
|
9
|
-
import { resolveRoot, scanForDocFiles } from './docgen-scan.mjs'
|
|
18
|
+
import { resolveRoot, scanForDocFiles, scanOrphanedDocs } from './docgen-scan.mjs'
|
|
10
19
|
|
|
11
20
|
/**
|
|
12
21
|
* Парсить `--limit N` / `--from N` / прапори режимів для дозапуску великого прогону.
|
|
@@ -153,7 +162,9 @@ const OKF_RESOURCE_RE = /^resource:[ \t]+(.+)$/mu
|
|
|
153
162
|
* @returns {void}
|
|
154
163
|
*/
|
|
155
164
|
function generateDirIndex(docsAbsDir, root) {
|
|
156
|
-
const allMd = readdirSync(docsAbsDir)
|
|
165
|
+
const allMd = readdirSync(docsAbsDir)
|
|
166
|
+
.filter(f => f.endsWith('.md'))
|
|
167
|
+
.sort()
|
|
157
168
|
|
|
158
169
|
// Якщо index.md вже є дока для source-файлу (має docgen.source → index.*) — не чіпаємо
|
|
159
170
|
if (allMd.includes('index.md')) {
|
|
@@ -215,6 +226,46 @@ function reportStats(stats) {
|
|
|
215
226
|
}
|
|
216
227
|
}
|
|
217
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Видаляє сирітські доки (source-файл не існує) і оновлює/прибирає index.md.
|
|
231
|
+
* Якщо після видалення в docs/-директорії лишились тільки index.md або нічого — очищує її.
|
|
232
|
+
* @param {string} root абсолютний корінь
|
|
233
|
+
* @returns {number} кількість видалених doc-файлів
|
|
234
|
+
*/
|
|
235
|
+
export function purgeOrphanedDocs(root) {
|
|
236
|
+
const orphans = scanOrphanedDocs(root)
|
|
237
|
+
if (orphans.length === 0) return 0
|
|
238
|
+
let deleted = 0
|
|
239
|
+
const docsDirs = new Set()
|
|
240
|
+
for (const docRel of orphans) {
|
|
241
|
+
try {
|
|
242
|
+
unlinkSync(join(root, docRel))
|
|
243
|
+
docsDirs.add(dirname(join(root, docRel)))
|
|
244
|
+
deleted++
|
|
245
|
+
} catch {
|
|
246
|
+
// race condition або вже видалено — ігноруємо
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
for (const docsAbsDir of docsDirs) {
|
|
250
|
+
if (!existsSync(docsAbsDir)) continue
|
|
251
|
+
const remaining = readdirSync(docsAbsDir)
|
|
252
|
+
const docFiles = remaining.filter(f => f.endsWith('.md') && f !== 'index.md')
|
|
253
|
+
if (docFiles.length === 0) {
|
|
254
|
+
// Лише index.md або порожня директорія — прибираємо повністю
|
|
255
|
+
const indexPath = join(docsAbsDir, 'index.md')
|
|
256
|
+
if (existsSync(indexPath)) unlinkSync(indexPath)
|
|
257
|
+
try {
|
|
258
|
+
rmdirSync(docsAbsDir)
|
|
259
|
+
} catch {
|
|
260
|
+
/* не порожня — пропускаємо */
|
|
261
|
+
}
|
|
262
|
+
} else {
|
|
263
|
+
generateDirIndex(docsAbsDir, root)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return deleted
|
|
267
|
+
}
|
|
268
|
+
|
|
218
269
|
/**
|
|
219
270
|
* `doc-files gen` — згенерувати документацію для застарілих/відсутніх док.
|
|
220
271
|
* @param {string[]} argv аргументи після назви субкоманди
|
|
@@ -224,11 +275,19 @@ export async function runDocFilesGenCli(argv) {
|
|
|
224
275
|
const root = resolveRoot(argv)
|
|
225
276
|
const { from, limit, overwrite } = parseGenArgs(argv)
|
|
226
277
|
|
|
278
|
+
// Видаляємо orphan-доки до генерації (незалежно від наявності stale)
|
|
279
|
+
const deleted = purgeOrphanedDocs(root)
|
|
280
|
+
if (deleted > 0) {
|
|
281
|
+
console.log(`🗑 doc-files: видалено ${deleted} сирітських доки(ів)`)
|
|
282
|
+
}
|
|
283
|
+
|
|
227
284
|
const all = scanForDocFiles(root)
|
|
228
285
|
const targets = selectTargets(root, all, { overwrite }).slice(from, from + limit)
|
|
229
286
|
|
|
230
287
|
if (targets.length === 0) {
|
|
231
|
-
|
|
288
|
+
if (deleted === 0) {
|
|
289
|
+
console.log('✓ doc-files: усі файлові доки свіжі й не-degraded. Нічого генерувати.')
|
|
290
|
+
}
|
|
232
291
|
return 0
|
|
233
292
|
}
|
|
234
293
|
|
|
@@ -133,7 +133,10 @@ export function splitProtected(md) {
|
|
|
133
133
|
break
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
|
-
const body = lines
|
|
136
|
+
const body = lines
|
|
137
|
+
.slice(start + 1, end)
|
|
138
|
+
.join('\n')
|
|
139
|
+
.trim()
|
|
137
140
|
const without = [...lines.slice(0, start), ...lines.slice(end)].join('\n')
|
|
138
141
|
return { body: body || null, without }
|
|
139
142
|
}
|
|
@@ -395,7 +398,10 @@ export const DEFAULT_LOCAL_MODEL = env.N_CURSOR_DOCGEN_MODEL ?? resolveModel('mi
|
|
|
395
398
|
* @param {{ model?: string, threshold?: number, existingMd?: string|null }} [opts] model-id, поріг degraded, наявна дока (для збереження захищеної секції)
|
|
396
399
|
* @returns {{ md: string, ms: number, llmMs: number, llmCalls: number, score: number|null, issues: string[], degraded: boolean, model: string }} документ і метадані генерації (ms — увесь файл; llmMs/llmCalls — лише LLM; решта ms — оркестрація)
|
|
397
400
|
*/
|
|
398
|
-
export function generateDoc(
|
|
401
|
+
export function generateDoc(
|
|
402
|
+
file,
|
|
403
|
+
{ model = DEFAULT_LOCAL_MODEL, threshold = QUALITY_THRESHOLD, existingMd = null } = {}
|
|
404
|
+
) {
|
|
399
405
|
const src = readFileSync(file, 'utf8')
|
|
400
406
|
// Pre-send guard: весь src вшивається у промпт як є (екстракт фактів його НЕ
|
|
401
407
|
// замінює). Для гігантів (vendored/генерат) це переповнює контекст → інстант-skip
|
|
@@ -403,7 +409,9 @@ export function generateDoc(file, { model = DEFAULT_LOCAL_MODEL, threshold = QUA
|
|
|
403
409
|
const estTokens = Math.round(Buffer.byteLength(src, 'utf8') / 4)
|
|
404
410
|
const budget = srcTokenBudget()
|
|
405
411
|
if (estTokens > budget) {
|
|
406
|
-
throw new Error(
|
|
412
|
+
throw new Error(
|
|
413
|
+
`docgen pre-send guard: джерело ~${estTokens} токенів > бюджет ${budget} (0.5× контексту) — Prompt too long, skip`
|
|
414
|
+
)
|
|
407
415
|
}
|
|
408
416
|
const facts = extractFacts(src, file)
|
|
409
417
|
const t0 = Date.now()
|
|
@@ -64,8 +64,16 @@ function judgeCached(src, doc) {
|
|
|
64
64
|
const hit = cacheGet(key)
|
|
65
65
|
if (hit) return { ...hit, cached: true }
|
|
66
66
|
const user = `SOURCE FILE:\n\`\`\`\n${src.slice(0, 12000)}\n\`\`\`\n\nGENERATED DOC:\n\`\`\`md\n${doc.slice(0, 8000)}\n\`\`\`\n\nReturn the JSON verdict.`
|
|
67
|
-
const raw = callLlm(
|
|
68
|
-
|
|
67
|
+
const raw = callLlm(
|
|
68
|
+
[
|
|
69
|
+
{ role: 'system', content: SYSTEM },
|
|
70
|
+
{ role: 'user', content: user }
|
|
71
|
+
],
|
|
72
|
+
JUDGE_MODEL,
|
|
73
|
+
{ timeoutMs: JUDGE_TIMEOUT, temperature: 0 }
|
|
74
|
+
)
|
|
75
|
+
const a = raw.indexOf('{'),
|
|
76
|
+
b = raw.lastIndexOf('}')
|
|
69
77
|
if (a === -1 || b === -1) throw new Error('no JSON in judge reply: ' + raw.slice(0, 160))
|
|
70
78
|
const v = JSON.parse(raw.slice(a, b + 1))
|
|
71
79
|
cacheSet(key, v)
|
|
@@ -81,17 +89,34 @@ function main() {
|
|
|
81
89
|
console.error('Usage: node docgen-judge-measure.mjs <file1> <file2> ...')
|
|
82
90
|
process.exit(2)
|
|
83
91
|
}
|
|
84
|
-
console.error(
|
|
92
|
+
console.error(
|
|
93
|
+
`[measure] gen=${GEN_MODEL} judge=${JUDGE_MODEL} threshold=${THRESHOLD} files=${files.length} cache=${CACHE_DIR}`
|
|
94
|
+
)
|
|
85
95
|
|
|
86
96
|
const rows = []
|
|
87
97
|
for (const [i, file] of files.entries()) {
|
|
88
98
|
const tag = `(${i + 1}/${files.length}) ${file}`
|
|
89
99
|
let src
|
|
90
|
-
try {
|
|
100
|
+
try {
|
|
101
|
+
src = readFileSync(file, 'utf8')
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error(`[skip] ${tag}: read ${error.message}`)
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
91
106
|
|
|
92
107
|
let gen
|
|
93
|
-
try {
|
|
94
|
-
|
|
108
|
+
try {
|
|
109
|
+
gen = genCached(file, src)
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.error(`[gen-err] ${tag}: ${error.message.slice(0, 120)}`)
|
|
112
|
+
rows.push({ file, error: 'gen', detail: error.message.slice(0, 200) })
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
if (gen.score === null) {
|
|
116
|
+
console.error(`[unsupported] ${tag}`)
|
|
117
|
+
rows.push({ file, score: null, unsupported: true })
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
95
120
|
|
|
96
121
|
const passed = gen.score >= THRESHOLD
|
|
97
122
|
const row = { file, score: gen.score, degraded: gen.degraded, passed, genCached: gen.cached }
|
|
@@ -100,9 +125,18 @@ function main() {
|
|
|
100
125
|
if (passed) {
|
|
101
126
|
try {
|
|
102
127
|
const v = judgeCached(src, gen.md)
|
|
103
|
-
row.verdict = v.verdict
|
|
104
|
-
|
|
105
|
-
|
|
128
|
+
row.verdict = v.verdict
|
|
129
|
+
row.confidence = v.confidence
|
|
130
|
+
row.reason = v.reason
|
|
131
|
+
row.offending = v.offending
|
|
132
|
+
row.judgeCached = v.cached
|
|
133
|
+
console.error(
|
|
134
|
+
` [judge${v.cached ? '*' : ''}] ${v.verdict} (${v.confidence}) — ${(v.reason || '').slice(0, 90)}`
|
|
135
|
+
)
|
|
136
|
+
} catch (error) {
|
|
137
|
+
row.judgeError = error.message.slice(0, 200)
|
|
138
|
+
console.error(` [judge-err] ${error.message.slice(0, 120)}`)
|
|
139
|
+
}
|
|
106
140
|
}
|
|
107
141
|
rows.push(row)
|
|
108
142
|
}
|
|
@@ -119,17 +153,26 @@ function main() {
|
|
|
119
153
|
const report = {
|
|
120
154
|
config: { genModel: GEN_MODEL, judgeModel: JUDGE_MODEL, threshold: THRESHOLD },
|
|
121
155
|
counts: {
|
|
122
|
-
files: files.length,
|
|
156
|
+
files: files.length,
|
|
157
|
+
generated: scored.length,
|
|
123
158
|
unsupported: rows.filter(r => r.unsupported).length,
|
|
124
159
|
genErrors: rows.filter(r => r.error === 'gen').length,
|
|
125
160
|
passedDetScorer: scored.filter(r => r.passed).length,
|
|
126
|
-
judged: M,
|
|
161
|
+
judged: M,
|
|
162
|
+
judgeErrors: rows.filter(r => r.judgeError).length
|
|
127
163
|
},
|
|
128
|
-
falsePositiveRate: {
|
|
129
|
-
|
|
130
|
-
|
|
164
|
+
falsePositiveRate: {
|
|
165
|
+
// серед PASSED+judged
|
|
166
|
+
accurate: byVerdict.accurate,
|
|
167
|
+
generic: byVerdict.generic,
|
|
168
|
+
inaccurate: byVerdict.inaccurate,
|
|
169
|
+
badPct: pct(bad),
|
|
170
|
+
inaccuratePct: pct(byVerdict.inaccurate),
|
|
171
|
+
genericPct: pct(byVerdict.generic)
|
|
131
172
|
},
|
|
132
|
-
offenders: passedRows
|
|
173
|
+
offenders: passedRows
|
|
174
|
+
.filter(r => r.verdict !== 'accurate')
|
|
175
|
+
.map(r => ({ file: r.file, score: r.score, verdict: r.verdict, confidence: r.confidence, reason: r.reason })),
|
|
133
176
|
rows
|
|
134
177
|
}
|
|
135
178
|
|
|
@@ -138,10 +181,16 @@ function main() {
|
|
|
138
181
|
writeFileSync(out, JSON.stringify(report, null, 2))
|
|
139
182
|
|
|
140
183
|
console.log('\n===== Q4 MEASUREMENT =====')
|
|
141
|
-
console.log(
|
|
184
|
+
console.log(
|
|
185
|
+
`generated: ${report.counts.generated}/${files.length} (unsupported=${report.counts.unsupported}, gen-errors=${report.counts.genErrors})`
|
|
186
|
+
)
|
|
142
187
|
console.log(`passed det-scorer (score≥${THRESHOLD}): ${report.counts.passedDetScorer} judged: ${M}`)
|
|
143
|
-
console.log(
|
|
144
|
-
|
|
188
|
+
console.log(
|
|
189
|
+
`among PASSED+judged → accurate=${byVerdict.accurate} generic=${byVerdict.generic} inaccurate=${byVerdict.inaccurate}`
|
|
190
|
+
)
|
|
191
|
+
console.log(
|
|
192
|
+
`>>> det-scorer FALSE-POSITIVE rate: ${pct(bad)}% (inaccurate=${pct(byVerdict.inaccurate)}%, generic=${pct(byVerdict.generic)}%)`
|
|
193
|
+
)
|
|
145
194
|
console.log(`decision guide: <~5% → don't build gate; >~15% → build (inaccurate-only)`)
|
|
146
195
|
console.log(`report: ${out}`)
|
|
147
196
|
}
|
|
@@ -58,7 +58,14 @@ export function parseDocVerdict(rawText) {
|
|
|
58
58
|
*/
|
|
59
59
|
export function judgeDoc(src, doc, { model = JUDGE_MODEL, timeoutMs = 120_000 } = {}) {
|
|
60
60
|
const user = `SOURCE FILE:\n\`\`\`\n${src.slice(0, 12_000)}\n\`\`\`\n\nGENERATED DOC:\n\`\`\`md\n${doc.slice(0, 8000)}\n\`\`\`\n\nReturn the JSON verdict.`
|
|
61
|
-
const raw = callLlm(
|
|
61
|
+
const raw = callLlm(
|
|
62
|
+
[
|
|
63
|
+
{ role: 'system', content: JUDGE_SYSTEM },
|
|
64
|
+
{ role: 'user', content: user }
|
|
65
|
+
],
|
|
66
|
+
model,
|
|
67
|
+
{ timeoutMs, temperature: 0 }
|
|
68
|
+
)
|
|
62
69
|
return parseDocVerdict(raw)
|
|
63
70
|
}
|
|
64
71
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/** @see ./docs/docgen-scan.md */
|
|
2
2
|
import { join, dirname, basename, extname, relative, resolve, sep, isAbsolute, posix } from 'node:path'
|
|
3
|
-
import { existsSync, readdirSync, statSync } from 'node:fs'
|
|
3
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'
|
|
4
4
|
import { execFileSync } from 'node:child_process'
|
|
5
5
|
import { once } from 'node:events'
|
|
6
6
|
import { env } from 'node:process'
|
|
7
7
|
|
|
8
8
|
import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
|
|
9
9
|
import { isDocgenIgnored } from './docgen-ignore.mjs'
|
|
10
|
-
import { QUALITY_THRESHOLD, readDocQuality, staleness } from './docgen-crc.mjs'
|
|
10
|
+
import { QUALITY_THRESHOLD, parseDocFrontmatter, readDocQuality, staleness } from './docgen-crc.mjs'
|
|
11
11
|
|
|
12
12
|
/** Кодові розширення, для яких генеруємо документацію. */
|
|
13
13
|
const SOURCE_EXTENSIONS = new Set(['.js', '.mjs', '.ts', '.vue', '.py', '.rs'])
|
|
@@ -78,6 +78,70 @@ export function describeFile(root, sourcePath) {
|
|
|
78
78
|
return { sourcePath, docPath, stale, reason }
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Знаходить "сирітські" доки: `docs/<stem>.md` із `resource:` + `docgen.crc` у frontmatter,
|
|
83
|
+
* у яких відповідний source-файл (resource:) вже не існує. Перевіряє лише файли,
|
|
84
|
+
* згенеровані `fix-doc-files` (наявність `docgen.crc` у frontmatter). Directory Index
|
|
85
|
+
* (resource із `/` на кінці) та ручні доки без `resource:` або без CRC — ігноруються.
|
|
86
|
+
* @param {string} root абсолютний корінь обходу
|
|
87
|
+
* @returns {string[]} posix-шляхи сирітських doc-файлів від кореня
|
|
88
|
+
*/
|
|
89
|
+
export function scanOrphanedDocs(root) {
|
|
90
|
+
const orphans = []
|
|
91
|
+
|
|
92
|
+
/** @param {string} docsAbsDir абсолютний шлях docs/-директорії */
|
|
93
|
+
function scanDocsDir(docsAbsDir) {
|
|
94
|
+
let entries
|
|
95
|
+
try {
|
|
96
|
+
entries = readdirSync(docsAbsDir, { withFileTypes: true })
|
|
97
|
+
} catch {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
for (const entry of entries) {
|
|
101
|
+
if (!entry.isFile() || !entry.name.endsWith('.md')) continue
|
|
102
|
+
const fullPath = join(docsAbsDir, entry.name)
|
|
103
|
+
let content
|
|
104
|
+
try {
|
|
105
|
+
content = readFileSync(fullPath, 'utf8')
|
|
106
|
+
} catch {
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
const { data } = parseDocFrontmatter(content)
|
|
110
|
+
// Пропускаємо: Directory Index (resource з `/`), ручні доки (немає resource або CRC)
|
|
111
|
+
if (!data?.source || data.source.endsWith('/') || !data.crc) continue
|
|
112
|
+
if (!existsSync(join(root, data.source))) {
|
|
113
|
+
orphans.push(relative(root, fullPath).split(sep).join('/'))
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Обходить дерево, шукаючи docs/-директорії для orphan-перевірки.
|
|
119
|
+
* docs/ — входимо завжди (батьківська пройшла ignore-перевірку);
|
|
120
|
+
* інші — перевіряємо через isDocgenIgnored. */
|
|
121
|
+
function walk(dir) {
|
|
122
|
+
let entries
|
|
123
|
+
try {
|
|
124
|
+
entries = readdirSync(dir, { withFileTypes: true })
|
|
125
|
+
} catch {
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
for (const entry of entries) {
|
|
129
|
+
if (!entry.isDirectory()) continue
|
|
130
|
+
const fullPath = join(dir, entry.name)
|
|
131
|
+
if (entry.name === 'docs') {
|
|
132
|
+
scanDocsDir(fullPath)
|
|
133
|
+
} else {
|
|
134
|
+
const relPath = relative(root, fullPath).split(sep).join('/')
|
|
135
|
+
if (isDocgenIgnored(relPath, 'dir')) continue
|
|
136
|
+
walk(fullPath)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
walk(root)
|
|
142
|
+
return orphans
|
|
143
|
+
}
|
|
144
|
+
|
|
81
145
|
/**
|
|
82
146
|
* Підмножина шляхів, які git вважає ігнорованими (`.gitignore` + global excludes).
|
|
83
147
|
* Один батч-виклик `git check-ignore --stdin`. Tracked-файли git не репортить як
|
|
@@ -96,7 +160,12 @@ function gitIgnoredPaths(root, relPaths) {
|
|
|
96
160
|
encoding: 'utf8',
|
|
97
161
|
stdio: ['pipe', 'pipe', 'ignore'] // git пише «not a git repository» у stderr — глушимо
|
|
98
162
|
})
|
|
99
|
-
return new Set(
|
|
163
|
+
return new Set(
|
|
164
|
+
out
|
|
165
|
+
.split('\n')
|
|
166
|
+
.map(s => s.trim())
|
|
167
|
+
.filter(Boolean)
|
|
168
|
+
)
|
|
100
169
|
} catch {
|
|
101
170
|
// exit 1 (жоден не ігнорується) і 128 (не git-репо) → execFileSync кидає; обидва = «не фільтруємо».
|
|
102
171
|
return new Set()
|
|
@@ -137,7 +206,10 @@ export function scanForDocFiles(root) {
|
|
|
137
206
|
}
|
|
138
207
|
|
|
139
208
|
walk(root)
|
|
140
|
-
const ignored = gitIgnoredPaths(
|
|
209
|
+
const ignored = gitIgnoredPaths(
|
|
210
|
+
root,
|
|
211
|
+
results.map(r => r.sourcePath)
|
|
212
|
+
)
|
|
141
213
|
return ignored.size ? results.filter(r => !ignored.has(r.sourcePath)) : results
|
|
142
214
|
}
|
|
143
215
|
|
|
@@ -307,20 +379,36 @@ export async function runDocFilesCheckCli(argv) {
|
|
|
307
379
|
}
|
|
308
380
|
|
|
309
381
|
const stale = sources.map(src => describeFile(root, src)).filter(f => f.stale)
|
|
310
|
-
|
|
382
|
+
// В git-режимі (Stop-гейт) додатково шукаємо сирітські доки без source-файлу
|
|
383
|
+
const orphans = gitMode ? scanOrphanedDocs(root) : []
|
|
311
384
|
|
|
312
|
-
|
|
385
|
+
if (stale.length === 0 && orphans.length === 0) return 0
|
|
386
|
+
|
|
387
|
+
// Великий прогін stale: Stop-гейт не блокує, але orphan-check продовжуємо
|
|
313
388
|
if (gitMode && stale.length > gateMax) {
|
|
314
389
|
console.error(
|
|
315
390
|
`⚠ doc-files: застарілих док ${stale.length} (> ${gateMax}) — гейт не блокує. Запусти масовий прогін:\n npx @nitra/cursor fix-doc-files`
|
|
316
391
|
)
|
|
317
|
-
return 0
|
|
392
|
+
if (orphans.length === 0) return 0
|
|
393
|
+
const oList = orphans.map(f => ` - ${f}`).join('\n')
|
|
394
|
+
console.error(
|
|
395
|
+
`✗ doc-files: сирітських доків (source видалено) ${orphans.length}:\n${oList}\n→ очисти: npx @nitra/cursor fix-doc-files`
|
|
396
|
+
)
|
|
397
|
+
return 2
|
|
318
398
|
}
|
|
319
399
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
400
|
+
if (stale.length > 0) {
|
|
401
|
+
const list = stale.map(f => ` - ${f.sourcePath} (${f.reason})`).join('\n')
|
|
402
|
+
console.error(
|
|
403
|
+
`✗ doc-files: документація застаріла/відсутня для ${stale.length} файл(ів):\n${list}\n→ перегенеруй: /doc-files`
|
|
404
|
+
)
|
|
405
|
+
}
|
|
406
|
+
if (orphans.length > 0) {
|
|
407
|
+
const oList = orphans.map(f => ` - ${f}`).join('\n')
|
|
408
|
+
console.error(
|
|
409
|
+
`✗ doc-files: сирітських доків (source видалено) ${orphans.length}:\n${oList}\n→ очисти: npx @nitra/cursor fix-doc-files`
|
|
410
|
+
)
|
|
411
|
+
}
|
|
324
412
|
return 2
|
|
325
413
|
}
|
|
326
414
|
|
|
@@ -3,28 +3,39 @@ type: JS Module
|
|
|
3
3
|
title: docgen-crc.mjs
|
|
4
4
|
resource: npm/rules/doc-files/js/docgen-crc.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 0c277bb7
|
|
7
|
+
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
+
score: 100
|
|
7
9
|
---
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
## Огляд
|
|
12
|
+
|
|
13
|
+
Модуль забезпечує роботу з метаданими та оцінкою якості документів. Він дозволяє парсити метадані з Markdown-файлів за допомогою `parseDocFrontmatter`, створювати та заповнювати блоки метаданих за допомогою `buildDocFrontmatter`. Документи можуть бути промарковані за допомогою `stampDoc`. Якість документа оцінюється за допомогою `readDocQuality`, а його актуальність визначається функцією `staleness`, яка використовує `crc32` для перевірки хеш-суми. Модель документа зчитується через `readDocModel`.
|
|
10
14
|
|
|
11
15
|
## Поведінка
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
QUALITY_THRESHOLD визначає поріг якості, нижче якого дока вважається неякісним.
|
|
18
|
+
crc32 обчислює CRC32 вмісту в hex-форматі.
|
|
19
|
+
parseDocFrontmatter парсить YAML-блок у вмісті md-файлу, виділяючи метадані та тіло.
|
|
20
|
+
buildDocFrontmatter створює OKF-сумісний YAML-блок для доки, включаючи метадані.
|
|
21
|
+
stampDoc замінює або додає свіжий YAML-блок у тіло md-доку, використовуючи дані джерела та оцінку.
|
|
22
|
+
readDocCrc зчитує CRC32 з YAML-блоку md-доки за заданим абсолютним шляхом.
|
|
23
|
+
readDocQuality зчитує оцінку якості (score, issues, retried, judgeModel) з YAML-блоку md-доки за абсолютним шляхом.
|
|
24
|
+
readDocModel зчитує повний ID моделі-генератора з YAML-блоку md-доки за абсолютним шляхом.
|
|
25
|
+
staleness визначає, чи є дока застарілою, порівнюючи CRC джерела з CRC у доці за абсолютними шляхами.
|
|
17
26
|
|
|
18
27
|
## Публічний API
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
QUALITY_THRESHOLD — Визначає рівень якості документа: дока з низьким показником вважається неякісним.
|
|
30
|
+
crc32 — Генерує 32-бітний контрольний сума вмісту у шістнадцятковому форматі.
|
|
31
|
+
parseDocFrontmatter — Витягує метадані з початку документа. Якщо метаданих немає, повертає порожні дані.
|
|
32
|
+
buildDocFrontmatter — Створює блок метаданих, сумісний з OKF, включаючи дані про генерацію документа (CRC, модель, якість).
|
|
33
|
+
stampDoc — Додає метадані до документа, що фіксують його стан.
|
|
34
|
+
readDocCrc — Зчитує контрольний сума з метаданих документа.
|
|
35
|
+
readDocQuality — Зчитує рівень якості, збережений у метаданих документа.
|
|
36
|
+
readDocModel — Зчитує назву моделі, використаної для генерації документа.
|
|
37
|
+
staleness — Визначає, чи є документ актуальним, порівнюючи його з джерелом.
|
|
25
38
|
|
|
26
39
|
## Гарантії поведінки
|
|
27
40
|
|
|
28
|
-
-
|
|
29
|
-
- Frontmatter — єдиний машинний виняток із правила «чистий Markdown»; тіло доки модуль не редагує.
|
|
30
|
-
- Відсутні поля якості читаються як «не оцінено» (`score: null`), а не як нуль.
|
|
41
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -3,31 +3,33 @@ type: JS Module
|
|
|
3
3
|
title: docgen-extract.mjs
|
|
4
4
|
resource: npm/rules/doc-files/js/docgen-extract.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 369662fe
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Огляд
|
|
12
|
+
|
|
13
|
+
Модуль витягує структурований факт-лист з вмісту файлів, звертаючись до мережі. Функція `extractFacts` аналізує вміст файлів, визначаючи публічні експорти, локальні символи та поведінкові маркери для Rust та JavaScript/TypeScript файлів. При цьому ігноруються системні та залежності, включаючи каталоги `.github`, `.git`, `node_modules`, `base/`, `ua/` та `.firebase`. Результати аналізу кешуються протягом одного прогону.
|
|
12
14
|
|
|
13
15
|
## Поведінка
|
|
14
16
|
|
|
15
17
|
1. Витягує факт-лист з вмісту файлу.
|
|
16
18
|
2. Визначає мову файлу за розширенням.
|
|
17
19
|
3. Якщо мова — Rust, виконує аналіз Rust-коду:
|
|
18
|
-
а. Витягує модульний
|
|
19
|
-
б. Визначає публічні експорти (структури, функції,
|
|
20
|
+
а. Витягує модульний заголовок (`//!`).
|
|
21
|
+
б. Визначає публічні експорти (структури, функції, класи), виходячи з префіксів `pub` та атрибутів експозиції.
|
|
20
22
|
в. Визначає локальні (приватні) символи, які не є публічними.
|
|
21
|
-
г. Класифікує імпорти (`
|
|
22
|
-
д. Визначає поведінкові маркери (
|
|
23
|
+
г. Класифікує імпорти (`use`) як стандартні, зовнішні чи внутрішні.
|
|
24
|
+
д. Визначає поведінкові маркери (наприклад, чи є код лише для читання, чи обробляє помилки).
|
|
23
25
|
4. Якщо мова — JavaScript/TypeScript/MJS, виконує аналіз JS-коду:
|
|
24
|
-
а. Витягує
|
|
25
|
-
б.
|
|
26
|
-
в. Класифікує імпорти
|
|
27
|
-
г. Визначає локальні (
|
|
28
|
-
д. Визначає поведінкові маркери (
|
|
29
|
-
5.
|
|
30
|
-
6. Повертає структуру фактів, що містить
|
|
26
|
+
а. Витягує заголовок файлу.
|
|
27
|
+
б. Визначає публічні експорти з їхнім JSDoc.
|
|
28
|
+
в. Класифікує імпорти як стандартні, npm або внутрішні.
|
|
29
|
+
г. Визначає локальні символи (службові функції).
|
|
30
|
+
д. Визначає поведінкові маркери (наприклад, чи є код лише для читання, чи звертається до мережі).
|
|
31
|
+
5. Усі аналізи свідомо ігнорують шляхи: `.github`, `.git`, `node_modules`, `base/`, `ua/`, `.firebase`.
|
|
32
|
+
6. Повертає структуру фактів, що містить інформацію про файл.
|
|
31
33
|
|
|
32
34
|
## Публічний API
|
|
33
35
|
|
|
@@ -3,31 +3,31 @@ type: JS Module
|
|
|
3
3
|
title: docgen-files-batch.mjs
|
|
4
4
|
resource: npm/rules/doc-files/js/docgen-files-batch.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
7
|
-
|
|
6
|
+
crc: 6316eecb
|
|
7
|
+
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
+
score: 100
|
|
8
9
|
---
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
Запускає генерацію документації для застарілих або відсутніх файлів.
|
|
11
|
+
## Огляд
|
|
12
12
|
|
|
13
|
-
runDocFilesStampCli
|
|
14
|
-
Перештампує frontmatter джерело та CRC у наявних документах без виклику LLM.
|
|
13
|
+
Модуль керує життєвим циклом документації. Він вибирає цілі для оновлення за допомогою `selectTargets`, очищає від неіснуючих джерел за допомогою `purgeOrphanedDocs`, запускає генерацію файлів через `runDocFilesGenCli` та `runDocFilesStampCli`, а також виконує пакетну генерацію за допомогою `runGenerationBatch`. Усі операції виконуються з механізмом перехоплення помилок, що запобігає виникненню винятків назовні.
|
|
15
14
|
|
|
16
15
|
## Поведінка
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
selectTargets відфільтровує документи для генерації, вибираючи застарілі або ті, які мають низьку якість і не були спробовані раніше.
|
|
18
|
+
purgeOrphanedDocs видаляє документи, для яких не існує відповідного джерела, і оновлює індекси директорій.
|
|
19
|
+
runDocFilesGenCli запускає генерацію документації для застарілих або низькоякісних файлів, після попереднього очищення сирітських документів.
|
|
20
|
+
runGenerationBatch виконує послідовну генерацію документації для заданого набору цілей, керуючи процесом через механізм виходу з ладу.
|
|
21
|
+
runDocFilesStampCli детерміновано оновлює метадані (frontmatter) існуючих документів, додаючи CRC та зберігаючи дані про якість.
|
|
23
22
|
|
|
24
23
|
## Публічний API
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
selectTargets — Визначає цілі для генерації документації: застарілі або деградовані документи, або всі документи при використанні прапора перезапису.
|
|
26
|
+
purgeOrphanedDocs — Видаляє документи, для яких відсутній відповідний вихідний файл, та оновлює файл індексу.
|
|
27
|
+
runDocFilesGenCli — Генерує документацію для застарілих або відсутніх документів.
|
|
28
|
+
runGenerationBatch — Виконує повний цикл генерації: перевіряє стан локального бекенду, послідовно генерує документи з обробкою збоїв, та створює фінальний звіт.
|
|
29
|
+
runDocFilesStampCli — Додає або оновлює метадані джерела та контрольної суми до існуючих документів без використання великих мовних моделей.
|
|
28
30
|
|
|
29
31
|
## Гарантії поведінки
|
|
30
32
|
|
|
31
33
|
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
32
|
-
- За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
|
|
33
|
-
- Не звертається до мережі.
|