@nimiplatform/nimi-coding 0.4.0 → 0.6.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/CONTRIBUTING.md +1 -1
- package/README.md +92 -55
- package/README.zh-CN.md +93 -56
- package/cli/commands/authority.mjs +80 -125
- package/cli/commands/clear.mjs +3 -2
- package/cli/commands/code.mjs +225 -0
- package/cli/commands/start.mjs +3 -2
- package/cli/constants.mjs +2 -1
- package/cli/dev/check-authority-surface.mjs +17 -8
- package/cli/dev/check-product-conformance.mjs +4 -32
- package/cli/dev/run-cli-smoke.mjs +6 -0
- package/cli/help.mjs +8 -3
- package/cli/index.mjs +3 -2
- package/cli/lib/authority/audit.mjs +262 -185
- package/cli/lib/authority/change-candidates.mjs +807 -0
- package/cli/lib/authority/closed-sets.mjs +7 -8
- package/cli/lib/authority/compile.mjs +6 -24
- package/cli/lib/authority/compiled-snapshot.mjs +143 -0
- package/cli/lib/authority/consumers.mjs +69 -19
- package/cli/lib/authority/diagnostics.mjs +10 -2
- package/cli/lib/authority/diff.mjs +77 -54
- package/cli/lib/authority/format.mjs +4 -32
- package/cli/lib/authority/git-snapshot.mjs +34 -379
- package/cli/lib/authority/graph.mjs +10 -10
- package/cli/lib/authority/impact.mjs +17 -144
- package/cli/lib/authority/review.mjs +33 -43
- package/cli/lib/authority/sarif.mjs +1 -8
- package/cli/lib/authority/source-yaml.mjs +0 -4
- package/cli/lib/authority/surface.mjs +19 -1
- package/cli/lib/authority/terms.mjs +10 -9
- package/cli/lib/authority/validate.mjs +6 -14
- package/cli/lib/code/authority-annotation-response.mjs +43 -0
- package/cli/lib/code/authority-annotation-scan.mjs +162 -0
- package/cli/lib/code/authority-annotations.mjs +293 -0
- package/cli/lib/code/context.mjs +710 -0
- package/cli/lib/code/response.mjs +165 -0
- package/cli/lib/doctor.mjs +3 -2
- package/cli/lib/entrypoints.mjs +13 -5
- package/cli/seeds/seed-policy.yaml +2 -2
- package/contracts/authority-source.schema.yaml +0 -6
- package/contracts/authority-verifier-bindings.schema.yaml +21 -10
- package/methodology/authority-authoring.yaml +68 -70
- package/methodology/core.yaml +10 -6
- package/package.json +5 -3
- package/spec/authority-audit.yaml +56 -52
- package/spec/authority-authoring.yaml +3 -16
- package/spec/authority-change-candidates.yaml +146 -0
- package/spec/authority-consumers.yaml +7 -0
- package/spec/authority-discovery.yaml +2 -2
- package/spec/authority-graph.yaml +1 -1
- package/spec/authority-impact.yaml +16 -39
- package/spec/authority-review.yaml +29 -47
- package/spec/authority-terms.yaml +5 -1
- package/spec/code-authority-annotations.yaml +42 -0
- package/spec/code-context.yaml +38 -0
- package/spec/product-scope.yaml +15 -9
- package/cli/commands/validate-ai-governance.mjs +0 -335
- package/cli/lib/authority/evidence-snapshot.mjs +0 -1
- package/cli/lib/authority/evidence.mjs +0 -1432
- package/cli/lib/internal/governance/ai/ai-context-budget-core.mjs +0 -377
- package/cli/lib/internal/governance/ai/ai-structure-budget-core.mjs +0 -376
- package/cli/lib/internal/governance/ai/check-agents-freshness.mjs +0 -155
- package/cli/lib/internal/governance/ai/check-high-risk-doc-metadata-core.mjs +0 -173
- package/cli/lib/internal/governance/config.mjs +0 -114
- package/cli/lib/internal/governance/shared/read-yaml-with-fragments.mjs +0 -49
- package/contracts/authority-evidence-bindings.schema.yaml +0 -53
- package/contracts/authority-evidence-probe-results.schema.yaml +0 -38
- package/contracts/authority-impact-dispositions.schema.yaml +0 -13
- package/spec/authority-evidence.yaml +0 -200
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
|
|
3
|
+
export const CODE_CONTEXT_FORMAT = "nimicoding.code-context-response/v1";
|
|
4
|
+
export const MIN_CODE_CONTEXT_BYTES = 512;
|
|
5
|
+
|
|
6
|
+
const MAX_ERROR_MESSAGE_BYTES = 160;
|
|
7
|
+
|
|
8
|
+
function serialized(value) {
|
|
9
|
+
return JSON.stringify(value);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function serializedBytes(value) {
|
|
13
|
+
return Buffer.byteLength(value, "utf8");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function prefixByteLengths(fragments) {
|
|
17
|
+
const totals = [0];
|
|
18
|
+
for (const fragment of fragments) {
|
|
19
|
+
totals.push(totals.at(-1) + serializedBytes(fragment));
|
|
20
|
+
}
|
|
21
|
+
return totals;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function arrayBytes(prefixTotals, count) {
|
|
25
|
+
return 2 + prefixTotals[count] + Math.max(0, count - 1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function arrayText(fragments, count) {
|
|
29
|
+
return `[${fragments.slice(0, count).join(",")}]`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function refusedCodeResponse(code, message) {
|
|
33
|
+
if (Buffer.byteLength(message, "utf8") > MAX_ERROR_MESSAGE_BYTES) {
|
|
34
|
+
throw new Error("code response error message exceeds its fixed protocol bound");
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
format: CODE_CONTEXT_FORMAT,
|
|
38
|
+
status: "refused",
|
|
39
|
+
scope: null,
|
|
40
|
+
coverage: null,
|
|
41
|
+
missing_frontier: null,
|
|
42
|
+
result: null,
|
|
43
|
+
error: { code, message },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function serializeCodeResponse(response) {
|
|
48
|
+
return `${serialized(response)}\n`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function targetCountsBySemanticPrefix(targets, semanticItems) {
|
|
52
|
+
const known = new Set();
|
|
53
|
+
const counts = [0];
|
|
54
|
+
for (const item of semanticItems) {
|
|
55
|
+
if (item.target_id !== undefined && item.target_id !== null) known.add(item.target_id);
|
|
56
|
+
counts.push(known.size);
|
|
57
|
+
}
|
|
58
|
+
if (known.size !== targets.length) throw new Error("semantic projection contains an unused target descriptor");
|
|
59
|
+
return counts;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function responseParts({ scopeText, rootText, targetFragments, semanticFragments, sourceFragments }, state) {
|
|
63
|
+
const coverage = {
|
|
64
|
+
semantic_items: state.semanticCount === semanticFragments.length ? "complete" : "truncated",
|
|
65
|
+
source_units: state.sourceCount === sourceFragments.length ? "complete" : "truncated",
|
|
66
|
+
};
|
|
67
|
+
const complete = state.semanticCount === semanticFragments.length && state.sourceCount === sourceFragments.length;
|
|
68
|
+
const frontier = complete ? null : {
|
|
69
|
+
next_semantic_site: state.nextSemanticSite,
|
|
70
|
+
next_source_target: state.nextSourceTarget,
|
|
71
|
+
};
|
|
72
|
+
if (!complete && frontier.next_semantic_site === null && frontier.next_source_target === null) {
|
|
73
|
+
throw new Error("partial code response has no missing frontier");
|
|
74
|
+
}
|
|
75
|
+
const head = [
|
|
76
|
+
`{"format":${serialized(CODE_CONTEXT_FORMAT)}`,
|
|
77
|
+
`,"status":${serialized(complete ? "completed" : "partial")}`,
|
|
78
|
+
`,"scope":${scopeText}`,
|
|
79
|
+
`,"coverage":${serialized(coverage)}`,
|
|
80
|
+
`,"missing_frontier":${serialized(frontier)}`,
|
|
81
|
+
`,"result":{"root":${rootText},"targets":`,
|
|
82
|
+
].join("");
|
|
83
|
+
return {
|
|
84
|
+
head,
|
|
85
|
+
betweenTargetsAndSemantic: ",\"semantic_items\":",
|
|
86
|
+
betweenSemanticAndSources: ",\"source_units\":",
|
|
87
|
+
tail: "},\"error\":null}\n",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function codeResponseBytes(parts, targetBytes, semanticBytes, sourceBytes, state) {
|
|
92
|
+
return serializedBytes(parts.head)
|
|
93
|
+
+ arrayBytes(targetBytes, state.targetCount)
|
|
94
|
+
+ serializedBytes(parts.betweenTargetsAndSemantic)
|
|
95
|
+
+ arrayBytes(semanticBytes, state.semanticCount)
|
|
96
|
+
+ serializedBytes(parts.betweenSemanticAndSources)
|
|
97
|
+
+ arrayBytes(sourceBytes, state.sourceCount)
|
|
98
|
+
+ serializedBytes(parts.tail);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function stateForPrefix({ targets, semanticItems, sourceUnits, targetCounts }, prefix) {
|
|
102
|
+
const semanticCount = Math.min(prefix, semanticItems.length);
|
|
103
|
+
const sourceCount = prefix <= semanticItems.length ? 0 : prefix - semanticItems.length;
|
|
104
|
+
const targetCount = targetCounts[semanticCount];
|
|
105
|
+
const nextSemantic = semanticItems[semanticCount];
|
|
106
|
+
let nextSourceTarget = null;
|
|
107
|
+
if (semanticCount === semanticItems.length) {
|
|
108
|
+
nextSourceTarget = sourceUnits[sourceCount]?.target_id ?? null;
|
|
109
|
+
} else if (sourceUnits.length > 0) {
|
|
110
|
+
const targetIndex = targets.findIndex((target) => target.id === sourceUnits[0].target_id);
|
|
111
|
+
if (targetIndex >= 0 && targetIndex < targetCount) nextSourceTarget = sourceUnits[0].target_id;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
semanticCount,
|
|
115
|
+
sourceCount,
|
|
116
|
+
targetCount,
|
|
117
|
+
nextSemanticSite: nextSemantic === undefined ? null : {
|
|
118
|
+
line: nextSemantic.site.range.start_line,
|
|
119
|
+
column: nextSemantic.site.range.start_column,
|
|
120
|
+
},
|
|
121
|
+
nextSourceTarget,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function renderContextResponse({ scope, projection, maxBytes }) {
|
|
126
|
+
const scopeText = serialized(scope);
|
|
127
|
+
const rootText = serialized(projection.root);
|
|
128
|
+
const targetFragments = projection.targets.map(serialized);
|
|
129
|
+
const semanticFragments = projection.semanticItems.map(serialized);
|
|
130
|
+
const sourceFragments = projection.sourceUnits.map(serialized);
|
|
131
|
+
const targetBytes = prefixByteLengths(targetFragments);
|
|
132
|
+
const semanticBytes = prefixByteLengths(semanticFragments);
|
|
133
|
+
const sourceBytes = prefixByteLengths(sourceFragments);
|
|
134
|
+
const targetCounts = targetCountsBySemanticPrefix(projection.targets, projection.semanticItems);
|
|
135
|
+
const totalItems = semanticFragments.length + sourceFragments.length;
|
|
136
|
+
let selected = null;
|
|
137
|
+
|
|
138
|
+
for (let prefix = 0; prefix <= totalItems; prefix += 1) {
|
|
139
|
+
const state = stateForPrefix({
|
|
140
|
+
targets: projection.targets,
|
|
141
|
+
semanticItems: projection.semanticItems,
|
|
142
|
+
sourceUnits: projection.sourceUnits,
|
|
143
|
+
targetCounts,
|
|
144
|
+
}, prefix);
|
|
145
|
+
const parts = responseParts({ scopeText, rootText, targetFragments, semanticFragments, sourceFragments }, state);
|
|
146
|
+
const bytes = codeResponseBytes(parts, targetBytes, semanticBytes, sourceBytes, state);
|
|
147
|
+
if (bytes <= maxBytes) selected = { state, parts, bytes };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (selected === null) return null;
|
|
151
|
+
const { state, parts, bytes } = selected;
|
|
152
|
+
const text = [
|
|
153
|
+
parts.head,
|
|
154
|
+
arrayText(targetFragments, state.targetCount),
|
|
155
|
+
parts.betweenTargetsAndSemantic,
|
|
156
|
+
arrayText(semanticFragments, state.semanticCount),
|
|
157
|
+
parts.betweenSemanticAndSources,
|
|
158
|
+
arrayText(sourceFragments, state.sourceCount),
|
|
159
|
+
parts.tail,
|
|
160
|
+
].join("");
|
|
161
|
+
if (serializedBytes(text) !== bytes || bytes > maxBytes) {
|
|
162
|
+
throw new Error("code response renderer byte accounting is inconsistent");
|
|
163
|
+
}
|
|
164
|
+
return { text, bytes, status: state.semanticCount === semanticFragments.length && state.sourceCount === sourceFragments.length ? "completed" : "partial" };
|
|
165
|
+
}
|
package/cli/lib/doctor.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readdir } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
|
+
import { PROJECT_LOCAL_CLI_INVOCATION } from "../constants.mjs";
|
|
4
5
|
import { getBootstrapSeedEntries } from "../seeds/bootstrap.mjs";
|
|
5
6
|
import { pathExists, preflightManagedProjectPaths } from "./fs-helpers.mjs";
|
|
6
7
|
import { runSeedSync, SYNC_MODE } from "./sync.mjs";
|
|
@@ -34,7 +35,7 @@ export async function inspectDoctorState(projectRoot) {
|
|
|
34
35
|
true,
|
|
35
36
|
"info",
|
|
36
37
|
specPresent
|
|
37
|
-
?
|
|
38
|
+
? `canonical authority is present; run ${PROJECT_LOCAL_CLI_INVOCATION} authority check .nimi/spec for admission`
|
|
38
39
|
: "canonical authority has not been authored; the project owns all product semantics under .nimi/spec",
|
|
39
40
|
),
|
|
40
41
|
];
|
|
@@ -74,7 +75,7 @@ export function formatDoctorResult(result, options = {}) {
|
|
|
74
75
|
if (visible.length === 0) lines.push(` - ${localize("No blocking integration issues found.", "没有发现阻塞性的集成问题。")}`);
|
|
75
76
|
else for (const entry of visible) lines.push(` - [${entry.ok ? "info" : entry.severity}] ${entry.detail}`);
|
|
76
77
|
if (!result.spec.present) {
|
|
77
|
-
lines.push("", styleLabel(localize("Next:", "下一步:")),
|
|
78
|
+
lines.push("", styleLabel(localize("Next:", "下一步:")), ` - Author canonical authority under .nimi/spec, format changed files, then run ${PROJECT_LOCAL_CLI_INVOCATION} authority check .nimi/spec.`);
|
|
78
79
|
}
|
|
79
80
|
return `${lines.join("\n")}\n`;
|
|
80
81
|
}
|
package/cli/lib/entrypoints.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
AGENTS_END,
|
|
7
7
|
CLAUDE_BEGIN,
|
|
8
8
|
CLAUDE_END,
|
|
9
|
+
PROJECT_LOCAL_CLI_INVOCATION,
|
|
9
10
|
} from "../constants.mjs";
|
|
10
11
|
import { pathExists, preflightManagedProjectPaths, readUtf8FileFatal } from "./fs-helpers.mjs";
|
|
11
12
|
|
|
@@ -18,14 +19,21 @@ export class ManagedBlockError extends Error {
|
|
|
18
19
|
|
|
19
20
|
function authorityAuthoringLines() {
|
|
20
21
|
return [
|
|
22
|
+
`- From the repository root, invoke the pinned project-local CLI as \`${PROJECT_LOCAL_CLI_INVOCATION}\`; do not probe or rely on a global \`nimicoding\` binary in \`PATH\`.`,
|
|
21
23
|
"- Product authority lives under `.nimi/spec/**`.",
|
|
22
24
|
"- For canonical authority authoring, read only `.nimi/methodology/authority-authoring.yaml`, the affected authority files or bounded task context, and CLI diagnostics.",
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
`- Use \`${PROJECT_LOCAL_CLI_INVOCATION} authority context <path> <id> --max-units <n> --max-bytes <n> --json\` only for the complete declared outgoing interpretation closure; it is not complete task context, and failure never permits guessed or partial context.`,
|
|
26
|
+
`- Use \`${PROJECT_LOCAL_CLI_INVOCATION} authority diff\` and \`${PROJECT_LOCAL_CLI_INVOCATION} authority impact\` with explicit \`--max-bytes\`; impact reports declared review obligations and does not prove implementation, consumers, or tests are synchronized.`,
|
|
27
|
+
`- Use \`${PROJECT_LOCAL_CLI_INVOCATION} authority change-candidates\` only with explicit channels and budgets; its complete union is recall input, never conflict, retirement, absence, authority, or conformance judgment.`,
|
|
28
|
+
`- For implementation audits with an exact authority ID, use \`${PROJECT_LOCAL_CLI_INVOCATION} code authority --repo <root> --authority <id> --max-files <n> --max-bytes <n>\` to locate annotated code, and use \`--source <path>\` for code-to-authority lookup. Results cover only explicit markers and authority lifecycle; they do not prove implementation conformance or evaluate unannotated code.`,
|
|
29
|
+
`- For a new or changed authority-governed feature, add \`// nimi-authority: <exact-id>\` only at the small number of key semantic owner files or declarations. Multiple markers are allowed; do not blanket-annotate mechanical helpers or tests.`,
|
|
30
|
+
`- Use \`// nimi-deprecated: <exact-id>\` only after direct authority evidence or a real product failure confirms obsolete semantics; find it with \`${PROJECT_LOCAL_CLI_INVOCATION} code authority --repo <root> --audit --max-files <n> --max-bytes <n>\` and remove the marker with the hard cut.`,
|
|
31
|
+
`- After selecting an explicit TypeScript or TSX consumer, use \`${PROJECT_LOCAL_CLI_INVOCATION} code context <path> --repo <root> --symbol <identifier> --tsconfig <path> --max-bytes <n>\` for bounded root-direct static dependencies; it is not inbound impact, runtime dispatch, or complete task context.`,
|
|
32
|
+
`- Use \`${PROJECT_LOCAL_CLI_INVOCATION} sync --check\` to diagnose drift in package-owned managed projections, \`${PROJECT_LOCAL_CLI_INVOCATION} sync --apply\` to restore them, and \`${PROJECT_LOCAL_CLI_INVOCATION} doctor\` to diagnose package/managed compatibility. These commands do not validate product authority, implementation conformance, or task readiness.`,
|
|
25
33
|
"- Under `.nimi/spec/**`, author only closed multi-unit `*.authority.yaml` containers or single-unit `*.authority.md`; historical document formats are unsupported and never inferred.",
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"- Keep derived and verification
|
|
34
|
+
`- Run \`${PROJECT_LOCAL_CLI_INVOCATION} authority fmt\` on each changed file, then \`${PROJECT_LOCAL_CLI_INVOCATION} authority check\` on the complete authority input set.`,
|
|
35
|
+
`- A failed project-local \`${PROJECT_LOCAL_CLI_INVOCATION} ...\` invocation blocks only the requested CLI product and never permits guessed, partial, corpus-wide, or fallback context; choose repair values only from product/task authority.`,
|
|
36
|
+
"- Keep derived and local verification output under `.nimi/local/**`; it is never product authority.",
|
|
29
37
|
];
|
|
30
38
|
}
|
|
31
39
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
policy_id: nimicoding.seed-projection.v3
|
|
2
|
-
description: Exact downstream projection registry for
|
|
2
|
+
description: Exact downstream projection registry for authority authoring and bounded implementation navigation.
|
|
3
3
|
projections:
|
|
4
4
|
- source: methodology/authority-authoring.yaml
|
|
5
5
|
output: .nimi/methodology/authority-authoring.yaml
|
|
6
6
|
ownership: package_canonical
|
|
7
|
-
downstream_consumer: project AI reads the compact
|
|
7
|
+
downstream_consumer: project AI reads the compact authority and implementation-navigation guide
|
|
8
8
|
deprecated_projections:
|
|
9
9
|
- .nimi/config/spec-generation-inputs.yaml
|
|
10
10
|
- .nimi/contracts/domain-admission.schema.yaml
|
|
@@ -4,11 +4,6 @@ contract:
|
|
|
4
4
|
owner: nimi-coding
|
|
5
5
|
visibility: package_internal
|
|
6
6
|
format: nimicoding.authority/v2
|
|
7
|
-
migration_inputs:
|
|
8
|
-
format: nimicoding.authority/v1
|
|
9
|
-
admitted_by: [fmt --upgrade, diff, compile, check, impact]
|
|
10
|
-
rationale: history_snapshots_and_migration_inputs_are_read_not_authored
|
|
11
|
-
compatibility_product_surface: none_v1_is_not_a_current_authoring_format
|
|
12
7
|
file_suffixes: [.authority.yaml, .authority.md]
|
|
13
8
|
yaml_document:
|
|
14
9
|
allowed_fields: [format, owner, scope, units]
|
|
@@ -40,7 +35,6 @@ text_values:
|
|
|
40
35
|
line_break_code_points: [U+000A, U+000B, U+000C, U+000D, U+0085, U+2028, U+2029]
|
|
41
36
|
fields:
|
|
42
37
|
yaml_document: [format, owner, scope, units]
|
|
43
|
-
yaml_document_migration_input: [format, units]
|
|
44
38
|
unit_common: [id, kind, owner, lifecycle, title, relations]
|
|
45
39
|
active_definition_required: [meaning]
|
|
46
40
|
active_rule_required: [modality, scope, statement, condition, failure]
|
|
@@ -1,20 +1,31 @@
|
|
|
1
|
-
version:
|
|
1
|
+
version: 2
|
|
2
2
|
contract:
|
|
3
|
-
id: nimicoding.authority-verifier-bindings.
|
|
3
|
+
id: nimicoding.authority-verifier-bindings.v2
|
|
4
4
|
owner: nimi-coding
|
|
5
5
|
visibility: package_internal
|
|
6
|
-
format: nimicoding.authority-verifier-bindings/
|
|
7
|
-
|
|
6
|
+
format: nimicoding.authority-verifier-bindings/v2
|
|
7
|
+
detectors:
|
|
8
|
+
- minimum-independent-incoming-reference/v1
|
|
9
|
+
- exact-lexical-invariant/v1
|
|
8
10
|
identifier_pattern: '^[a-z](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z](?:[a-z0-9-]*[a-z0-9])?)+$'
|
|
11
|
+
token_pattern: '^[\p{L}\p{N}](?:[\p{L}\p{N}_.-]*[\p{L}\p{N}])?$'
|
|
9
12
|
policies: [advisory, blocking]
|
|
13
|
+
lexical_matches: [token, phrase]
|
|
14
|
+
lexical_expectations: [present, absent]
|
|
10
15
|
fields:
|
|
11
|
-
top: [format,
|
|
12
|
-
|
|
16
|
+
top: [format, bindings]
|
|
17
|
+
graph_binding: [id, detector, premise, targets, minimum, policy]
|
|
18
|
+
lexical_binding: [id, detector, term, match, expectation, policy]
|
|
13
19
|
constraints:
|
|
14
|
-
|
|
20
|
+
bindings: non_empty_closed_detector_binding_list
|
|
15
21
|
binding_ID: unique_exact_dotted_lowercase_identifier
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
graph_premise: exact_active_rule_ID
|
|
23
|
+
graph_targets: non_empty_unique_exact_active_definition_IDs
|
|
24
|
+
graph_minimum: positive_safe_integer
|
|
25
|
+
lexical_term: non_empty_trimmed_single_line_exact_text
|
|
26
|
+
lexical_token: token_pattern_when_match_is_token
|
|
27
|
+
lexical_phrase: exact_case_sensitive_code_point_substring
|
|
28
|
+
lexical_corpus: active_authority_only
|
|
29
|
+
lexical_fields: [meaning, statement, condition, failure]
|
|
19
30
|
policy: advisory_or_blocking
|
|
20
31
|
extra_fields: forbidden
|
|
@@ -1,45 +1,62 @@
|
|
|
1
|
-
version:
|
|
1
|
+
version: 6
|
|
2
2
|
id: nimicoding.authority-authoring
|
|
3
|
-
purpose: Author explicit
|
|
3
|
+
purpose: Author explicit authority and navigate current implementation without inference.
|
|
4
4
|
authority_boundary:
|
|
5
5
|
canonical_root: .nimi/spec
|
|
6
6
|
sources: ["*.authority.yaml", "*.authority.md"]
|
|
7
|
-
rule: The project owns
|
|
8
|
-
AI_inputs: [this_guide, task_authority,
|
|
7
|
+
rule: The project owns meaning; nimicoding formats, validates, and derives read-only results.
|
|
8
|
+
AI_inputs: [this_guide, task_authority, bounded_authority_or_code_query, diagnostics]
|
|
9
9
|
do_not_read: [complete_authority_corpus, contracts, package_internal_specs]
|
|
10
10
|
|
|
11
|
+
cli_execution:
|
|
12
|
+
cwd: repository_root
|
|
13
|
+
command_prefix: pnpm exec nimicoding
|
|
14
|
+
rule: Resolve the pinned local package; never probe global PATH. Failure blocks only the requested CLI product.
|
|
15
|
+
|
|
11
16
|
daily_workflow:
|
|
12
|
-
-
|
|
13
|
-
- Select
|
|
14
|
-
- Modify only project
|
|
15
|
-
- Run nimicoding authority fmt <changed-file> for each changed file.
|
|
16
|
-
- Run nimicoding authority check <complete-path> [--scope-bindings <file>] --json
|
|
17
|
-
- For semantic changes, run diff and impact with
|
|
18
|
-
- Never continue from
|
|
17
|
+
- Without an exact ID, run pnpm exec nimicoding authority discover <path> <query> --max-candidates 10 --max-snippet-terms 24 --max-bytes 131072 --json. It returns candidates, never selection or absence proof.
|
|
18
|
+
- Select IDs only from task/product authority. pnpm exec nimicoding authority query <path> <id> --max-bytes <n> --json returns one unit; pnpm exec nimicoding authority context <path> <id> --max-units <n> --max-bytes <n> --json returns its outgoing applies_to/supersedes closure, not task context.
|
|
19
|
+
- Modify only project authority; never infer product values or relations.
|
|
20
|
+
- Run pnpm exec nimicoding authority fmt <changed-file> for each changed file.
|
|
21
|
+
- Run pnpm exec nimicoding authority check <complete-path> [--scope-bindings <file>] --json, then pnpm exec nimicoding authority compile <complete-path> --json. For anchors run pnpm exec nimicoding authority anchors <repo> --spec <corpus> [--scope-bindings <file>] --max-units <n> --max-anchors <n> --max-bytes <n> --json.
|
|
22
|
+
- For semantic changes, run complete-input diff and impact with budgets; obligations are host follow-up targets, not results.
|
|
23
|
+
- Never continue from diagnostics, unknown IDs, budget failures, or guessed/partial results.
|
|
24
|
+
|
|
25
|
+
implementation_navigation:
|
|
26
|
+
authority_to_code: pnpm exec nimicoding code authority --repo <root> --authority <exact-id> --max-files <n> --max-bytes <n>
|
|
27
|
+
code_to_authority: pnpm exec nimicoding code authority --repo <root> --source <tracked-path> --max-files <n> --max-bytes <n>
|
|
28
|
+
context: pnpm exec nimicoding code context <ts-or-tsx-path> --repo <root> --symbol <top-level-identifier> --tsconfig <path> --max-bytes <n>
|
|
29
|
+
markers:
|
|
30
|
+
authority: "// nimi-authority: <exact-id>"
|
|
31
|
+
deprecated: "// nimi-deprecated: <same-exact-id>"
|
|
32
|
+
rule: Put optional markers near key semantic owners; add deprecated only from direct authority/product failure, then remove with the hard cut.
|
|
33
|
+
boundary: Markers return authored locations/lifecycle; TypeScript context is root-direct static outbound only. Neither evaluates unannotated code, conformance, inbound impact, runtime dispatch, or completion.
|
|
34
|
+
|
|
35
|
+
managed_surfaces:
|
|
36
|
+
check: pnpm exec nimicoding sync --check
|
|
37
|
+
restore: pnpm exec nimicoding sync --apply
|
|
38
|
+
doctor: pnpm exec nimicoding doctor
|
|
39
|
+
boundary: Sync diagnoses exact package-owned projection/block drift and apply restores it; doctor diagnoses package/managed compatibility. Neither validates authority, code, or task readiness.
|
|
19
40
|
|
|
20
41
|
source_profiles:
|
|
21
42
|
yaml:
|
|
22
|
-
shape: "Closed
|
|
23
|
-
defaults: owner/rule scope inherit; unit
|
|
24
|
-
omissions: lifecycle
|
|
25
|
-
|
|
43
|
+
shape: "Closed nimicoding.authority/v2 mapping with optional owner/scope defaults and units."
|
|
44
|
+
defaults: owner/rule scope inherit; unit values override; definitions have no scope.
|
|
45
|
+
omissions: active lifecycle and empty relations may be omitted; removed reason stays explicit.
|
|
46
|
+
format: nimicoding.authority/v2_only_without_legacy_migration_or_history_input
|
|
26
47
|
markdown:
|
|
27
|
-
shape: One unit per file
|
|
48
|
+
shape: One unit per file; front matter carries fields and relations.
|
|
28
49
|
title: One plain H1.
|
|
29
50
|
sections:
|
|
30
51
|
active_definition: [Meaning]
|
|
31
52
|
active_rule: [Statement, Condition, Failure]
|
|
32
53
|
removed_unit: [Removal reason]
|
|
33
|
-
boundary:
|
|
34
|
-
shared_text_rule: Text
|
|
54
|
+
boundary: One plain-text line per section; no free prose or unknown structures.
|
|
55
|
+
shared_text_rule: Text is non-empty trimmed single-line Unicode.
|
|
35
56
|
|
|
36
57
|
common_fields:
|
|
37
|
-
id: Stable
|
|
38
|
-
|
|
39
|
-
owner: Accountable dotted lower-case unit or container value.
|
|
40
|
-
lifecycle: active or explicit removed.
|
|
41
|
-
title: Required display label.
|
|
42
|
-
relations: Type/target pairs; omitted means [].
|
|
58
|
+
id: Stable lower-case dot identity; never reuse a removed ID.
|
|
59
|
+
owner: Accountable lower-case dotted identity.
|
|
43
60
|
|
|
44
61
|
unit_shapes:
|
|
45
62
|
active_definition:
|
|
@@ -50,55 +67,37 @@ unit_shapes:
|
|
|
50
67
|
required: [id, kind, title, modality, statement, condition, failure]
|
|
51
68
|
fixed: {kind: rule, lifecycle: active}
|
|
52
69
|
modality: must or must_not.
|
|
53
|
-
scope:
|
|
54
|
-
condition:
|
|
55
|
-
failure:
|
|
70
|
+
scope: Unique non-empty unit list or inherited container value.
|
|
71
|
+
condition: Actual condition; use Always. only when unconditional.
|
|
72
|
+
failure: Observable failure, never pseudo-success or fallback.
|
|
56
73
|
forbidden: [meaning, reason]
|
|
57
74
|
removed_tombstone:
|
|
58
75
|
required: [id, kind, lifecycle, title, reason]
|
|
59
76
|
fixed: {lifecycle: removed}
|
|
60
|
-
boundary: Preserve
|
|
77
|
+
boundary: Preserve identity/kind; reason is rationale, not replacement content.
|
|
61
78
|
forbidden: [meaning, modality, scope, statement, condition, failure]
|
|
62
79
|
|
|
63
80
|
relation_rules:
|
|
64
|
-
applies_to:
|
|
65
|
-
supersedes: Optional
|
|
66
|
-
resolution:
|
|
81
|
+
applies_to: Each active rule targets one or more active definitions only.
|
|
82
|
+
supersedes: Optional edge to one removed unit of the same kind; one incoming/outgoing maximum, acyclic.
|
|
83
|
+
resolution: Exact IDs in complete input; invalid, dangling, mismatched, cyclic, duplicate, or inferred edges fail.
|
|
67
84
|
|
|
68
85
|
formatter_and_diagnostics:
|
|
69
|
-
- fmt canonicalizes
|
|
70
|
-
-
|
|
71
|
-
- check/compile use
|
|
72
|
-
- Diagnostics give locations
|
|
73
|
-
- Fix values only from task or product authority. Do not invent container defaults, fallback data, historical inference, internal contracts, or wildcard corpus reading.
|
|
86
|
+
- fmt canonicalizes v2 and strips redundant unit defaults.
|
|
87
|
+
- Non-v2 input fails fmt/check/compile/diff/impact/review.
|
|
88
|
+
- check/compile use complete paths and emit no public/partial AuthorityIR.
|
|
89
|
+
- Diagnostics give locations and repair categories, never product values.
|
|
74
90
|
|
|
75
91
|
change_workflow:
|
|
76
|
-
diff: nimicoding authority diff <before-path> <after-path> --max-bytes <positive-integer> --json
|
|
77
|
-
|
|
92
|
+
diff: pnpm exec nimicoding authority diff <before-path> <after-path> --max-bytes <positive-integer> --json
|
|
93
|
+
candidates: pnpm exec nimicoding authority change-candidates <before-path> <after-path> --channels <comma-separated-closed-set> --max-candidates <positive-safe-integer> --max-reasons <positive-safe-integer> --max-bytes <positive-safe-integer> --json
|
|
94
|
+
impact: pnpm exec nimicoding authority impact <before-path> <after-path> --max-bytes <positive-integer> --json
|
|
78
95
|
boundaries:
|
|
79
96
|
- Diff compares complete canonical inputs; formatting, profile, file, and order-only changes are semantic zero.
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
|
|
84
|
-
disposition_authoring:
|
|
85
|
-
workflow:
|
|
86
|
-
- Write the empty skeleton and run impact to obtain exact obligations from the failed result.
|
|
87
|
-
- Add exactly one entry per impacted active rule using real project evidence, then rerun impact with the same budget. Missing or extra dispositions fail.
|
|
88
|
-
empty_skeleton: |
|
|
89
|
-
format: nimicoding.authority-impact-dispositions/v1
|
|
90
|
-
rules: []
|
|
91
|
-
complete_example: |
|
|
92
|
-
format: nimicoding.authority-impact-dispositions/v1
|
|
93
|
-
rules:
|
|
94
|
-
- id: rule.checkout-session
|
|
95
|
-
consumers:
|
|
96
|
-
- scope: api.checkout
|
|
97
|
-
status: addressed
|
|
98
|
-
evidence: src/checkout/session-handler.ts
|
|
99
|
-
test:
|
|
100
|
-
status: addressed
|
|
101
|
-
evidence: tests/checkout-session.test.ts
|
|
97
|
+
- Candidates cover only requested exact channels, never semantic judgment.
|
|
98
|
+
- Impact reports declared reverse-relation consumers and one test target per impacted active rule.
|
|
99
|
+
- Diff/impact budget failure returns no partial result.
|
|
100
|
+
- Impact accepts no disposition, receipt, external result, test outcome, or completion state; workflow stays host-owned.
|
|
102
101
|
|
|
103
102
|
canonical_examples:
|
|
104
103
|
complete_yaml_lifecycle: |
|
|
@@ -109,13 +108,13 @@ canonical_examples:
|
|
|
109
108
|
kind: definition
|
|
110
109
|
owner: team.identity
|
|
111
110
|
lifecycle: removed
|
|
112
|
-
title:
|
|
113
|
-
reason: Replaced by
|
|
111
|
+
title: Old session
|
|
112
|
+
reason: Replaced by definition.session.
|
|
114
113
|
- id: definition.session
|
|
115
114
|
kind: definition
|
|
116
115
|
owner: team.identity
|
|
117
116
|
title: Session
|
|
118
|
-
meaning: A server-issued identity
|
|
117
|
+
meaning: A server-issued request identity.
|
|
119
118
|
relations:
|
|
120
119
|
- type: supersedes
|
|
121
120
|
target: definition.session-v0
|
|
@@ -123,16 +122,16 @@ canonical_examples:
|
|
|
123
122
|
kind: rule
|
|
124
123
|
owner: team.checkout
|
|
125
124
|
lifecycle: removed
|
|
126
|
-
title:
|
|
127
|
-
reason: Replaced by
|
|
125
|
+
title: Old checkout rule
|
|
126
|
+
reason: Replaced by rule.checkout-no-anonymous.
|
|
128
127
|
- id: rule.checkout-no-anonymous
|
|
129
128
|
kind: rule
|
|
130
129
|
owner: team.checkout
|
|
131
|
-
title:
|
|
130
|
+
title: Require checkout session
|
|
132
131
|
modality: must_not
|
|
133
|
-
statement: Checkout creates an order without a
|
|
132
|
+
statement: Checkout creates an order without a session.
|
|
134
133
|
condition: Always.
|
|
135
|
-
failure: Reject
|
|
134
|
+
failure: Reject before creating the order.
|
|
136
135
|
relations:
|
|
137
136
|
- type: applies_to
|
|
138
137
|
target: definition.session
|
|
@@ -140,5 +139,4 @@ canonical_examples:
|
|
|
140
139
|
target: rule.checkout-no-anonymous-v0
|
|
141
140
|
|
|
142
141
|
final_boundaries:
|
|
143
|
-
-
|
|
144
|
-
- Derived reads are bounded and read-only; none selects authority, supplies complete task context, or proves completion.
|
|
142
|
+
- Only project-authored sources under .nimi/spec are authority; derived/local output is not.
|
package/methodology/core.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
version:
|
|
1
|
+
version: 7
|
|
2
2
|
methodology:
|
|
3
3
|
id: nimi-coding
|
|
4
|
-
mission: Preserve explicit project-authored canonical authority
|
|
4
|
+
mission: Preserve explicit project-authored canonical authority and derive bounded read-only code context or explicit authored code links from current implementation inputs.
|
|
5
5
|
package_boundary:
|
|
6
6
|
owns:
|
|
7
7
|
- compact_canonical_authority_authoring_methodology
|
|
@@ -9,11 +9,13 @@ methodology:
|
|
|
9
9
|
- canonical_authority_formatter_and_conformance_gate
|
|
10
10
|
- bounded_deterministic_exact_filtered_lexical_candidate_discovery_with_SourceMapped_field_snippets_and_optional_direct_authored_relation_preview
|
|
11
11
|
- private_compiler_filtered_lexical_discovery_and_exact_query
|
|
12
|
+
- immutable_per_invocation_compiler_snapshots_transient_exact_indexes_and_change_derived_candidate_recall
|
|
12
13
|
- complete_declared_outgoing_interpretation_closure
|
|
13
14
|
- bounded_explicit_relation_graph_navigation
|
|
14
15
|
- project_bound_deterministic_authority_audit_and_SARIF_projection
|
|
15
16
|
- semantic_diff_and_declared_review_obligations
|
|
16
|
-
-
|
|
17
|
+
- explicit_TypeScript_5_9_3_root_direct_bounded_code_context
|
|
18
|
+
- transient_exact_code_authority_marker_lookup_and_lifecycle_audit
|
|
17
19
|
does_not_own:
|
|
18
20
|
- project_product_semantics
|
|
19
21
|
- historical_document_reconstruction_or_inference
|
|
@@ -23,16 +25,18 @@ methodology:
|
|
|
23
25
|
- implementation_or_review_completion
|
|
24
26
|
- host_workflow_commands
|
|
25
27
|
- storage_semantic_search_visualization_or_Atlas
|
|
28
|
+
- code_location_inbound_impact_structural_advice_other_languages_or_task_completion
|
|
26
29
|
authority_order:
|
|
27
30
|
- host_canonical_authority_under_.nimi/spec
|
|
28
31
|
- projected_compact_authoring_methodology
|
|
29
32
|
- package_internal_compiler_contracts
|
|
30
|
-
-
|
|
33
|
+
- local_derived_output
|
|
31
34
|
boundaries:
|
|
32
35
|
discovery: bounded_exact_filtered_lexical_candidates_with_SourceMapped_field_snippets_and_optional_M1_direct_authored_relation_preview_not_semantic_search_selection_context_complete_recall_or_absence_proof
|
|
36
|
+
change_candidates: complete_union_for_explicit_requested_exact_channels_not_conflict_retirement_authority_or_conformance_judgment
|
|
33
37
|
context: complete_declared_outgoing_interpretation_closure_not_complete_task_context
|
|
34
38
|
graph: bounded_explicit_relation_navigation_not_semantic_inference_or_raw_IR
|
|
35
39
|
audit: explicit_project_verifier_bindings_not_prose_inference_plugin_execution_or_product_authority
|
|
36
|
-
impact:
|
|
40
|
+
impact: declared_relation_impact_and_host_follow_up_targets_not_implementation_consumer_or_test_sync_proof
|
|
41
|
+
code_context: current_filesystem_complete_selected_TypeScript_Program_root_direct_static_outbound_projection_not_location_impact_runtime_dispatch_or_task_context
|
|
37
42
|
authority_admission: nimicoding_authority_check_on_complete_canonical_root
|
|
38
|
-
optional_repository_governance: separate_L3_not_authority_admission
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nimiplatform/nimi-coding",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "Canonical authority
|
|
5
|
+
"description": "Canonical authority products and bounded read-only code context for AI coding systems.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://docs.nimi.ai/nimicoding",
|
|
8
8
|
"repository": {
|
|
@@ -33,12 +33,14 @@
|
|
|
33
33
|
"keywords": [
|
|
34
34
|
"ai",
|
|
35
35
|
"coding",
|
|
36
|
-
"
|
|
36
|
+
"authority",
|
|
37
|
+
"code-intelligence",
|
|
37
38
|
"methodology",
|
|
38
39
|
"spec",
|
|
39
40
|
"nimicoding"
|
|
40
41
|
],
|
|
41
42
|
"dependencies": {
|
|
43
|
+
"typescript": "5.9.3",
|
|
42
44
|
"yaml": "^2.8.1"
|
|
43
45
|
},
|
|
44
46
|
"files": [
|