@starci/skills 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INDEX.md +74 -0
- package/INDEX.vi.md +75 -0
- package/README.md +44 -0
- package/README.vi.md +43 -0
- package/SKILL.md +135 -0
- package/SKILL.vi.md +128 -0
- package/alias/INDEX.md +104 -0
- package/alias/INDEX.vi.md +104 -0
- package/alias/alias.json +297 -0
- package/bin/starci-skills.mjs +219 -0
- package/knowledge/INDEX.md +22 -0
- package/knowledge/INDEX.vi.md +22 -0
- package/knowledge/grammars/starci/DNA.md +146 -0
- package/knowledge/grammars/starci/DNA.vi.md +146 -0
- package/knowledge/grammars/starci/INDEX.md +25 -0
- package/knowledge/grammars/starci/INDEX.vi.md +25 -0
- package/knowledge/grammars/starci/family.md +50 -0
- package/knowledge/grammars/starci/family.vi.md +50 -0
- package/knowledge/grammars/starci/idioms.md +120 -0
- package/knowledge/grammars/starci/idioms.vi.md +121 -0
- package/knowledge/grammars/starci/playbook.md +36 -0
- package/knowledge/grammars/starci/playbook.vi.md +35 -0
- package/knowledge/patterns/be/INDEX.md +29 -0
- package/knowledge/patterns/be/INDEX.vi.md +29 -0
- package/knowledge/patterns/be/comment.md +80 -0
- package/knowledge/patterns/be/comment.vi.md +80 -0
- package/knowledge/patterns/be/error.md +86 -0
- package/knowledge/patterns/be/error.vi.md +86 -0
- package/knowledge/patterns/be/folder.md +87 -0
- package/knowledge/patterns/be/folder.vi.md +86 -0
- package/knowledge/patterns/be/function.md +80 -0
- package/knowledge/patterns/be/function.vi.md +80 -0
- package/knowledge/patterns/be/imports.md +79 -0
- package/knowledge/patterns/be/imports.vi.md +79 -0
- package/knowledge/patterns/be/naming.md +87 -0
- package/knowledge/patterns/be/naming.vi.md +87 -0
- package/knowledge/patterns/be/test.md +79 -0
- package/knowledge/patterns/be/test.vi.md +79 -0
- package/knowledge/patterns/be/typing.md +73 -0
- package/knowledge/patterns/be/typing.vi.md +73 -0
- package/knowledge/patterns/fe/INDEX.md +29 -0
- package/knowledge/patterns/fe/INDEX.vi.md +29 -0
- package/knowledge/patterns/fe/comment.md +70 -0
- package/knowledge/patterns/fe/comment.vi.md +70 -0
- package/knowledge/patterns/fe/error.md +61 -0
- package/knowledge/patterns/fe/error.vi.md +61 -0
- package/knowledge/patterns/fe/folder.md +98 -0
- package/knowledge/patterns/fe/folder.vi.md +95 -0
- package/knowledge/patterns/fe/function.md +70 -0
- package/knowledge/patterns/fe/function.vi.md +70 -0
- package/knowledge/patterns/fe/imports.md +87 -0
- package/knowledge/patterns/fe/imports.vi.md +87 -0
- package/knowledge/patterns/fe/naming.md +77 -0
- package/knowledge/patterns/fe/naming.vi.md +77 -0
- package/knowledge/patterns/fe/test.md +73 -0
- package/knowledge/patterns/fe/test.vi.md +73 -0
- package/knowledge/patterns/fe/typing.md +67 -0
- package/knowledge/patterns/fe/typing.vi.md +67 -0
- package/knowledge/ui/INDEX.md +101 -0
- package/knowledge/ui/INDEX.vi.md +101 -0
- package/knowledge/ui/composition/INDEX.md +60 -0
- package/knowledge/ui/composition/INDEX.vi.md +63 -0
- package/knowledge/ui/composition/accent.md +73 -0
- package/knowledge/ui/composition/accent.vi.md +74 -0
- package/knowledge/ui/composition/action.md +55 -0
- package/knowledge/ui/composition/action.vi.md +56 -0
- package/knowledge/ui/composition/coverage.md +37 -0
- package/knowledge/ui/composition/coverage.vi.md +37 -0
- package/knowledge/ui/composition/cta.md +79 -0
- package/knowledge/ui/composition/cta.vi.md +79 -0
- package/knowledge/ui/composition/feedback.md +55 -0
- package/knowledge/ui/composition/feedback.vi.md +56 -0
- package/knowledge/ui/composition/hierarchy.md +83 -0
- package/knowledge/ui/composition/hierarchy.vi.md +82 -0
- package/knowledge/ui/composition/layout.md +91 -0
- package/knowledge/ui/composition/layout.vi.md +93 -0
- package/knowledge/ui/composition/responsive.md +67 -0
- package/knowledge/ui/composition/responsive.vi.md +67 -0
- package/knowledge/ui/composition/state.md +105 -0
- package/knowledge/ui/composition/state.vi.md +106 -0
- package/knowledge/ui/presentation/INDEX.md +94 -0
- package/knowledge/ui/presentation/INDEX.vi.md +69 -0
- package/knowledge/ui/presentation/boundary.md +170 -0
- package/knowledge/ui/presentation/boundary.vi.md +169 -0
- package/knowledge/ui/presentation/font.md +155 -0
- package/knowledge/ui/presentation/font.vi.md +156 -0
- package/knowledge/ui/presentation/gap.md +181 -0
- package/knowledge/ui/presentation/gap.vi.md +181 -0
- package/knowledge/ui/presentation/margin.md +168 -0
- package/knowledge/ui/presentation/margin.vi.md +171 -0
- package/knowledge/ui/presentation/measure.md +174 -0
- package/knowledge/ui/presentation/measure.vi.md +178 -0
- package/knowledge/ui/presentation/overflow.md +142 -0
- package/knowledge/ui/presentation/overflow.vi.md +142 -0
- package/knowledge/ui/presentation/padding.md +293 -0
- package/knowledge/ui/presentation/padding.vi.md +292 -0
- package/knowledge/ui/presentation/surface.md +166 -0
- package/knowledge/ui/presentation/surface.vi.md +166 -0
- package/knowledge/ui/presentation/text-flow.md +123 -0
- package/knowledge/ui/presentation/text-flow.vi.md +123 -0
- package/knowledge/ui/presentation/tone.md +114 -0
- package/knowledge/ui/presentation/tone.vi.md +113 -0
- package/knowledge/ui/proof/INDEX.md +55 -0
- package/knowledge/ui/proof/INDEX.vi.md +55 -0
- package/knowledge/ui/proof/accessibility.md +67 -0
- package/knowledge/ui/proof/accessibility.vi.md +68 -0
- package/knowledge/ui/proof/contrast.md +58 -0
- package/knowledge/ui/proof/contrast.vi.md +57 -0
- package/knowledge/ui/proof/focus.md +76 -0
- package/knowledge/ui/proof/focus.vi.md +76 -0
- package/knowledge/ui/proof/motion.md +63 -0
- package/knowledge/ui/proof/motion.vi.md +64 -0
- package/knowledge/ui/proof/render-truth.md +63 -0
- package/knowledge/ui/proof/render-truth.vi.md +63 -0
- package/operators/INDEX.md +199 -0
- package/operators/INDEX.vi.md +199 -0
- package/operators/architecture-decide/errors.json +115 -0
- package/operators/architecture-decide/operator.json +20 -0
- package/operators/architecture-decide/operator.md +133 -0
- package/operators/architecture-decide/operator.vi.md +130 -0
- package/operators/architecture-decide/self-test.mjs +221 -0
- package/operators/architecture-decide/validate.mjs +112 -0
- package/operators/backend-source-apply/errors.json +66 -0
- package/operators/backend-source-apply/operator.json +20 -0
- package/operators/backend-source-apply/operator.md +189 -0
- package/operators/backend-source-apply/operator.vi.md +185 -0
- package/operators/backend-source-apply/self-test.mjs +257 -0
- package/operators/backend-source-apply/validate.mjs +240 -0
- package/operators/business-decide/errors.json +78 -0
- package/operators/business-decide/operator.json +20 -0
- package/operators/business-decide/operator.md +176 -0
- package/operators/business-decide/operator.vi.md +174 -0
- package/operators/business-decide/self-test.mjs +225 -0
- package/operators/business-decide/validate.mjs +277 -0
- package/operators/content-generate/errors.json +106 -0
- package/operators/content-generate/operator.json +21 -0
- package/operators/content-generate/operator.md +155 -0
- package/operators/content-generate/operator.vi.md +155 -0
- package/operators/content-generate/self-test.mjs +288 -0
- package/operators/content-generate/validate.mjs +196 -0
- package/operators/errors.json +178 -0
- package/operators/frontend-direction-decide/errors.json +135 -0
- package/operators/frontend-direction-decide/operator.json +21 -0
- package/operators/frontend-direction-decide/operator.md +167 -0
- package/operators/frontend-direction-decide/operator.vi.md +167 -0
- package/operators/frontend-direction-decide/self-test.mjs +226 -0
- package/operators/frontend-direction-decide/validate.mjs +146 -0
- package/operators/frontend-presentation-resolve/errors.json +42 -0
- package/operators/frontend-presentation-resolve/operator.json +19 -0
- package/operators/frontend-presentation-resolve/operator.md +142 -0
- package/operators/frontend-presentation-resolve/operator.vi.md +140 -0
- package/operators/frontend-presentation-resolve/self-test.mjs +163 -0
- package/operators/frontend-presentation-resolve/validate.mjs +143 -0
- package/operators/frontend-source-apply/errors.json +30 -0
- package/operators/frontend-source-apply/operator.json +20 -0
- package/operators/frontend-source-apply/operator.md +127 -0
- package/operators/frontend-source-apply/operator.vi.md +126 -0
- package/operators/frontend-source-apply/self-test.mjs +214 -0
- package/operators/frontend-source-apply/validate.mjs +133 -0
- package/operators/frontend-surface-audit/errors.json +5 -0
- package/operators/frontend-surface-audit/operator.json +22 -0
- package/operators/frontend-surface-audit/operator.md +121 -0
- package/operators/frontend-surface-audit/operator.vi.md +121 -0
- package/operators/frontend-surface-audit/self-test.mjs +185 -0
- package/operators/frontend-surface-audit/validate.mjs +127 -0
- package/operators/git-publish/errors.json +54 -0
- package/operators/git-publish/operator.json +20 -0
- package/operators/git-publish/operator.md +180 -0
- package/operators/git-publish/operator.vi.md +178 -0
- package/operators/git-publish/self-test.mjs +177 -0
- package/operators/git-publish/validate.mjs +106 -0
- package/operators/platform-operate/errors.json +90 -0
- package/operators/platform-operate/operator.json +22 -0
- package/operators/platform-operate/operator.md +162 -0
- package/operators/platform-operate/operator.vi.md +160 -0
- package/operators/platform-operate/self-test.mjs +202 -0
- package/operators/platform-operate/validate.mjs +193 -0
- package/operators/quality-verify/errors.json +54 -0
- package/operators/quality-verify/operator.json +20 -0
- package/operators/quality-verify/operator.md +185 -0
- package/operators/quality-verify/operator.vi.md +177 -0
- package/operators/quality-verify/self-test.mjs +210 -0
- package/operators/quality-verify/validate.mjs +197 -0
- package/operators/release-deploy/errors.json +158 -0
- package/operators/release-deploy/operator.json +23 -0
- package/operators/release-deploy/operator.md +183 -0
- package/operators/release-deploy/operator.vi.md +181 -0
- package/operators/release-deploy/self-test.mjs +235 -0
- package/operators/release-deploy/validate.mjs +129 -0
- package/operators/uat-verify/errors.json +78 -0
- package/operators/uat-verify/operator.json +25 -0
- package/operators/uat-verify/operator.md +162 -0
- package/operators/uat-verify/operator.vi.md +161 -0
- package/operators/uat-verify/self-test.mjs +270 -0
- package/operators/uat-verify/validate.mjs +202 -0
- package/operators/workspace-bind/errors.json +90 -0
- package/operators/workspace-bind/operator.json +21 -0
- package/operators/workspace-bind/operator.md +148 -0
- package/operators/workspace-bind/operator.vi.md +148 -0
- package/operators/workspace-bind/self-test.mjs +205 -0
- package/operators/workspace-bind/validate.mjs +152 -0
- package/package.json +50 -0
- package/readiness/initialization/workspaces/commit-policy.json +91 -0
- package/readiness/initialization/workspaces/config.schema.json +35 -0
- package/readiness/initialization/workspaces/device-state.schema.json +54 -0
- package/readiness/initialization/workspaces/local-route.schema.json +206 -0
- package/readiness/initialization/workspaces/portable-route.schema.json +200 -0
- package/resources/INDEX.md +96 -0
- package/resources/INDEX.vi.md +99 -0
- package/resources/agents/profiles/claude.json +131 -0
- package/resources/agents/profiles/openai.json +131 -0
- package/resources/orchestrator.json +71 -0
- package/resources/tools.json +85 -0
- package/routing.json +272 -0
- package/scripts/alias-registry.mjs +31 -0
- package/scripts/device-state.mjs +497 -0
- package/scripts/device-state.spec.mjs +18 -0
- package/scripts/errors-registry.mjs +68 -0
- package/scripts/generate-alias-doc.mjs +66 -0
- package/scripts/generate-grammar-dna.mjs +387 -0
- package/scripts/generate-operators-index.mjs +95 -0
- package/scripts/generate-presentation-owned.mjs +681 -0
- package/scripts/install-cli.spec.mjs +74 -0
- package/scripts/json-schema.mjs +94 -0
- package/scripts/operator-md.mjs +96 -0
- package/scripts/run-operator-self-tests.mjs +36 -0
- package/scripts/validate-alias.mjs +165 -0
- package/scripts/validate-defaults.mjs +72 -0
- package/scripts/validate-knowledge-citations.mjs +90 -0
- package/scripts/validate-operator.mjs +125 -0
- package/scripts/validate-request.mjs +80 -0
- package/scripts/validate-resources.mjs +117 -0
- package/scripts/validate-response.mjs +141 -0
- package/scripts/validate-routing.mjs +91 -0
- package/scripts/validate-step.mjs +50 -0
- package/scripts/validate-templates.mjs +226 -0
- package/scripts/validate-templates.spec.mjs +144 -0
- package/scripts/validate-workflows.mjs +106 -0
- package/scripts/workspace-portable.mjs +389 -0
- package/scripts/workspace-portable.spec.mjs +246 -0
- package/templates/README.md +47 -0
- package/templates/README.vi.md +45 -0
- package/templates/changes.example.md +27 -0
- package/templates/grammars.template.md +34 -0
- package/templates/kinds/architecture-decision.contract.json +14 -0
- package/templates/kinds/architecture-decision.skeleton.md +52 -0
- package/templates/kinds/backend-source-application.contract.json +10 -0
- package/templates/kinds/backend-source-application.skeleton.md +34 -0
- package/templates/kinds/business-promise-authority.contract.json +13 -0
- package/templates/kinds/business-promise-authority.skeleton.md +67 -0
- package/templates/kinds/capture.schema.json +33 -0
- package/templates/kinds/changes.contract.json +10 -0
- package/templates/kinds/changes.skeleton.md +26 -0
- package/templates/kinds/checks.schema.json +44 -0
- package/templates/kinds/claims.schema.json +165 -0
- package/templates/kinds/conformance.schema.json +15 -0
- package/templates/kinds/content-brief.contract.json +12 -0
- package/templates/kinds/content-brief.skeleton.md +45 -0
- package/templates/kinds/content-generation-receipt.contract.json +11 -0
- package/templates/kinds/content-generation-receipt.skeleton.md +40 -0
- package/templates/kinds/content-review.contract.json +11 -0
- package/templates/kinds/content-review.skeleton.md +45 -0
- package/templates/kinds/contract.schema.json +28 -0
- package/templates/kinds/coverage-matrix.schema.json +86 -0
- package/templates/kinds/coverage.schema.json +62 -0
- package/templates/kinds/current-state.schema.json +40 -0
- package/templates/kinds/delta.schema.json +95 -0
- package/templates/kinds/e2e.schema.json +63 -0
- package/templates/kinds/frontend-direction-decision.contract.json +93 -0
- package/templates/kinds/frontend-direction-decision.skeleton.md +68 -0
- package/templates/kinds/frontend-presentation-resolution.contract.json +11 -0
- package/templates/kinds/frontend-presentation-resolution.skeleton.md +32 -0
- package/templates/kinds/frontend-source-application.contract.json +10 -0
- package/templates/kinds/frontend-source-application.skeleton.md +30 -0
- package/templates/kinds/frontend-surface-audit.contract.json +52 -0
- package/templates/kinds/frontend-surface-audit.skeleton.md +32 -0
- package/templates/kinds/gate-result.schema.json +64 -0
- package/templates/kinds/git-publication.contract.json +82 -0
- package/templates/kinds/git-publication.skeleton.md +61 -0
- package/templates/kinds/independent-critique.contract.json +9 -0
- package/templates/kinds/independent-critique.skeleton.md +28 -0
- package/templates/kinds/inventory.schema.json +35 -0
- package/templates/kinds/model.schema.json +99 -0
- package/templates/kinds/mutations.schema.json +65 -0
- package/templates/kinds/platform-operation-receipt.contract.json +76 -0
- package/templates/kinds/platform-operation-receipt.skeleton.md +54 -0
- package/templates/kinds/probes.schema.json +130 -0
- package/templates/kinds/proof.schema.json +17 -0
- package/templates/kinds/quality-verification.contract.json +87 -0
- package/templates/kinds/quality-verification.skeleton.md +58 -0
- package/templates/kinds/release-deployment.contract.json +85 -0
- package/templates/kinds/release-deployment.skeleton.md +67 -0
- package/templates/kinds/route.schema.json +293 -0
- package/templates/kinds/stack-model.schema.json +90 -0
- package/templates/kinds/uat-capture.schema.json +35 -0
- package/templates/kinds/uat-flow-verification.contract.json +11 -0
- package/templates/kinds/uat-flow-verification.skeleton.md +47 -0
- package/templates/kinds/uat-snapshot.schema.json +96 -0
- package/templates/kinds/uat-verdicts.schema.json +41 -0
- package/templates/kinds/ui-coverage.schema.json +77 -0
- package/templates/kinds/verdicts.schema.json +39 -0
- package/templates/kinds/workspace-route-binding.contract.json +12 -0
- package/templates/kinds/workspace-route-binding.skeleton.md +60 -0
- package/templates/kinds/writes.schema.json +37 -0
- package/templates/operator.template.md +73 -0
- package/templates/patterns.template.md +31 -0
- package/templates/step/request.schema.json +42 -0
- package/templates/step/response.schema.json +144 -0
- package/templates/ui-composition.template.md +36 -0
- package/templates/ui-presentation.template.md +57 -0
- package/templates/ui-proof.template.md +34 -0
- package/workflows/README.md +37 -0
- package/workflows/README.vi.md +37 -0
- package/workflows/backend-feature.json +59 -0
- package/workflows/content-unit.json +19 -0
- package/workflows/frontend-new-surface.json +81 -0
- package/workflows/frontend-reconstruct.json +67 -0
- package/workflows/frontend-refine.json +67 -0
- package/workflows/frontend-with-uat.json +78 -0
- package/workflows/full-feature.json +104 -0
- package/workflows/release.json +29 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// frontend.direction.decide's own law over one branch, on top of the shared step check: the intent and the
|
|
2
|
+
// change level agree; the selection policy and the approval agree; the receipt names exactly one
|
|
3
|
+
// selected candidate, falsifies every candidate it formed, and rejects the others by name; a refine
|
|
4
|
+
// forms no structural candidate and consults no external reference; more than one candidate is
|
|
5
|
+
// rendered; and COVERAGE-1 holds, meaning the coverage enumerates every action, region, state and
|
|
6
|
+
// responsive branch the UI contract declares.
|
|
7
|
+
import { existsSync } from 'node:fs';
|
|
8
|
+
import { readFile } from 'node:fs/promises';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import process from 'node:process';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import { validateStep } from '../../scripts/validate-step.mjs';
|
|
13
|
+
import { tableUnder } from '../../scripts/validate-response.mjs';
|
|
14
|
+
|
|
15
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
16
|
+
const empty = (v) => v === undefined || v === null || v === '' || v === '—';
|
|
17
|
+
const list = (v) => (Array.isArray(v) ? v : empty(v) ? [] : [v]);
|
|
18
|
+
|
|
19
|
+
// COVERAGE-1 (knowledge/ui/composition): a decided direction enumerates what a later operator has to
|
|
20
|
+
// exercise. Every element the UI contract declares is covered, every pending path settles, every
|
|
21
|
+
// meaning has its own carrier, and every responsive branch has one owner.
|
|
22
|
+
export function coverageErrors(coverage, declared, at) {
|
|
23
|
+
const errors = [];
|
|
24
|
+
const need = (kind) => declared.filter((d) => d.kind === kind).map((d) => d.element);
|
|
25
|
+
const actions = need('action');
|
|
26
|
+
if (actions.length) {
|
|
27
|
+
if ((coverage.actions ?? []).length === 0) errors.push(`${at}: COVERAGE-1: actions must enumerate every declared action`);
|
|
28
|
+
const covered = (coverage.actions ?? []).map((a) => a.action);
|
|
29
|
+
for (const action of actions) if (!covered.includes(action)) errors.push(`${at}: COVERAGE-1: action is not covered: ${action}`);
|
|
30
|
+
for (const entry of coverage.actions ?? []) for (const p of entry.pendingPaths ?? []) if (!p.settlement) errors.push(`${at}: COVERAGE-1: pending path without a settlement: ${entry.action}`);
|
|
31
|
+
}
|
|
32
|
+
const regions = need('region');
|
|
33
|
+
if (regions.length) {
|
|
34
|
+
if ((coverage.regions ?? []).length === 0) errors.push(`${at}: COVERAGE-1: regions must enumerate every declared region`);
|
|
35
|
+
const covered = (coverage.regions ?? []).map((r) => r.region);
|
|
36
|
+
for (const region of regions) if (!covered.includes(region)) errors.push(`${at}: COVERAGE-1: region is not covered: ${region}`);
|
|
37
|
+
for (const region of covered) if (!regions.includes(region)) errors.push(`${at}: COVERAGE-1: coverage names a region the UI contract does not declare: ${region}`);
|
|
38
|
+
}
|
|
39
|
+
const states = need('state');
|
|
40
|
+
if (states.length) {
|
|
41
|
+
if ((coverage.states ?? []).length === 0) errors.push(`${at}: COVERAGE-1: states must enumerate every named meaning`);
|
|
42
|
+
const covered = (coverage.states ?? []).map((s) => s.meaning);
|
|
43
|
+
for (const state of states) if (!covered.includes(state)) errors.push(`${at}: COVERAGE-1: state is not covered: ${state}`);
|
|
44
|
+
const carriers = (coverage.states ?? []).map((s) => s.carrier);
|
|
45
|
+
if (new Set(carriers).size !== carriers.length) errors.push(`${at}: COVERAGE-1: two meanings share one carrier`);
|
|
46
|
+
}
|
|
47
|
+
const responsive = need('responsive');
|
|
48
|
+
if (responsive.length) {
|
|
49
|
+
if ((coverage.responsive ?? []).length === 0) errors.push(`${at}: COVERAGE-1: responsive must enumerate every responsive branch`);
|
|
50
|
+
const covered = (coverage.responsive ?? []).map((b) => b.branch);
|
|
51
|
+
for (const branch of responsive) if (!covered.includes(branch)) errors.push(`${at}: COVERAGE-1: responsive branch is not covered: ${branch}`);
|
|
52
|
+
if (new Set(covered).size !== covered.length) errors.push(`${at}: COVERAGE-1: a responsive branch is named twice, so it has more than one owner`);
|
|
53
|
+
}
|
|
54
|
+
return errors;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function validateDirectionStep(branchDir, root = ROOT) {
|
|
58
|
+
const base = await validateStep(root, branchDir);
|
|
59
|
+
const errors = [...base.errors];
|
|
60
|
+
const { response, requirements = {}, present = new Set() } = base;
|
|
61
|
+
if (!response || response.operatorId !== 'frontend.direction.decide') return { errors };
|
|
62
|
+
const has = (f) => existsSync(path.join(branchDir, f));
|
|
63
|
+
const read = (f) => readFile(path.join(branchDir, f), 'utf8');
|
|
64
|
+
|
|
65
|
+
const intent = requirements.intent ?? 'modify';
|
|
66
|
+
const changeLevel = requirements.changeLevel;
|
|
67
|
+
const candidates = Number(requirements.candidates ?? 1);
|
|
68
|
+
const preview = requirements.preview ?? 'no';
|
|
69
|
+
const policy = requirements.selectionPolicy ?? 'automatic';
|
|
70
|
+
const approval = empty(requirements.approval) ? null : requirements.approval;
|
|
71
|
+
const references = list(requirements.references);
|
|
72
|
+
|
|
73
|
+
if (intent === 'create' && changeLevel !== 'new') errors.push('request.json: intent create requires changeLevel new');
|
|
74
|
+
if (changeLevel === 'new' && intent !== 'create') errors.push('request.json: changeLevel new requires intent create');
|
|
75
|
+
if (!(candidates >= 1 && candidates <= 3)) errors.push(`request.json: candidates must be 1, 2 or 3, not ${requirements.candidates}`);
|
|
76
|
+
if (policy === 'automatic' && approval !== null) errors.push('request.json: approval is bound under automatic policy; supplying both hides which one decided');
|
|
77
|
+
|
|
78
|
+
const artifacts = new Set(list(response.fields?.candidates));
|
|
79
|
+
if (response.status === 'done') {
|
|
80
|
+
if (candidates > 1 && artifacts.size === 0) errors.push('response/response.json: more than one candidate was formed but none was rendered');
|
|
81
|
+
if (preview === 'yes' && artifacts.size === 0) errors.push('response/response.json: preview was asked for but no candidate page was rendered');
|
|
82
|
+
if (candidates === 1 && preview === 'no' && artifacts.size > 0) errors.push('response/response.json: one candidate under no preview renders no page');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let coverage = null;
|
|
86
|
+
if (present.has('ui-coverage') && has('response/data/coverage.json')) {
|
|
87
|
+
try { coverage = JSON.parse(await read('response/data/coverage.json')); } catch { coverage = null; }
|
|
88
|
+
} else if (response.status === 'done') errors.push('response/data/coverage.json: a done branch needs the coverage enumeration');
|
|
89
|
+
|
|
90
|
+
if (present.has('frontend-direction-decision') && has('response/response.md')) {
|
|
91
|
+
const text = await read('response/response.md');
|
|
92
|
+
const at = 'response/response.md';
|
|
93
|
+
const decision = Object.fromEntries((tableUnder(text, '## Decision') ?? []).map(([k, v]) => [k, v]));
|
|
94
|
+
if (!empty(requirements.target) && decision.Target !== requirements.target) errors.push(`${at}: Target differs from the request`);
|
|
95
|
+
if (decision.Intent !== intent) errors.push(`${at}: Intent ${decision.Intent} differs from the request's ${intent}`);
|
|
96
|
+
if (decision['Change level'] !== changeLevel) errors.push(`${at}: Change level ${decision['Change level']} differs from the request's ${changeLevel}`);
|
|
97
|
+
if (!empty(requirements.ownerCeiling) && decision['Owner ceiling'] !== requirements.ownerCeiling) errors.push(`${at}: Owner ceiling differs from the request`);
|
|
98
|
+
if (decision['Selection policy'] !== policy) errors.push(`${at}: Selection policy ${decision['Selection policy']} differs from the request's ${policy}`);
|
|
99
|
+
if (changeLevel === 'refine' && decision.Classification !== 'locked-refine') errors.push(`${at}: a refine is classified locked-refine, not ${decision.Classification}`);
|
|
100
|
+
if (changeLevel !== 'refine' && decision.Classification === 'locked-refine') errors.push(`${at}: locked-refine requires change level refine`);
|
|
101
|
+
|
|
102
|
+
// Exactly one candidate is selected, every candidate formed is falsified, and every candidate
|
|
103
|
+
// that was not selected is rejected by name.
|
|
104
|
+
const attacks = tableUnder(text, '## Falsification') ?? [];
|
|
105
|
+
const formed = new Set(attacks.map((r) => r[1]));
|
|
106
|
+
const rejected = new Set((tableUnder(text, '## Why not the others') ?? []).map((r) => r[0]));
|
|
107
|
+
const selected = decision['Selected candidate'];
|
|
108
|
+
if (response.status === 'done') {
|
|
109
|
+
if (empty(selected)) errors.push(`${at}: a decided direction names one selected candidate`);
|
|
110
|
+
else if (!formed.has(selected)) errors.push(`${at}: the selected candidate ${selected} carries no falsification row`);
|
|
111
|
+
if (formed.size !== candidates) errors.push(`${at}: Falsification covers ${formed.size} candidates, the request asked for ${candidates}`);
|
|
112
|
+
for (const candidate of formed) {
|
|
113
|
+
if (candidate === selected) continue;
|
|
114
|
+
if (!rejected.has(candidate)) errors.push(`${at}: candidate ${candidate} was not selected and is not rejected by name`);
|
|
115
|
+
}
|
|
116
|
+
if (rejected.has(selected)) errors.push(`${at}: the selected candidate ${selected} is also listed under Why not the others`);
|
|
117
|
+
for (const [, candidate, verdict] of attacks) {
|
|
118
|
+
if (candidate === selected && verdict === 'fails') errors.push(`${at}: the selected candidate ${selected} fails an attack, so the direction is not decided`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (policy === 'approval-required' && response.status === 'done') {
|
|
122
|
+
if (approval === null) errors.push('response/response.json: approval-required with no approval cannot end done; DIRECTION_CHOICE_REQUIRED terminates here');
|
|
123
|
+
else if (approval !== selected) errors.push(`${at}: the receipt selects ${selected} but approval names ${approval}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// A refine moves elements inside the approved structure and consults no external reference.
|
|
127
|
+
const refs = tableUnder(text, '## References') ?? [];
|
|
128
|
+
if (changeLevel === 'refine' && refs.length) errors.push(`${at}: a refine works from the family idioms alone, so References carries no row`);
|
|
129
|
+
if (references.length && refs.length === 0) errors.push(`${at}: the person supplied references and none of them is recorded`);
|
|
130
|
+
const contract = (tableUnder(text, '## UI contract') ?? []).map(([element, kind]) => ({ element, kind }));
|
|
131
|
+
if (coverage) {
|
|
132
|
+
errors.push(...coverageErrors(coverage, contract, 'response/data/coverage.json'));
|
|
133
|
+
if (!empty(decision['Direction id']) && coverage.directionId !== decision['Direction id']) {
|
|
134
|
+
errors.push(`response/data/coverage.json: directionId ${coverage.directionId} differs from the receipt's ${decision['Direction id']}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return { errors };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
142
|
+
const target = process.argv[2];
|
|
143
|
+
if (!target) { process.stderr.write('usage: node validate.mjs <session>/step-N/parallel-M\n'); process.exit(2); }
|
|
144
|
+
const { errors } = await validateDirectionStep(path.resolve(target));
|
|
145
|
+
if (errors.length) { process.stderr.write(`${errors.join('\n')}\n`); process.exitCode = 1; } else process.stdout.write('valid frontend.direction.decide branch\n');
|
|
146
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 9,
|
|
3
|
+
"note": "Stop codes frontend.presentation.resolve emits. Same entry shape as operators/errors.json, scope implicit. Shared codes (INVALID_INPUT, SOURCE_DRIFT, NO_PROGRESS) come from operators/errors.json. OWNER_CONFLICT and UNKNOWN_RULE are defined here and also emitted by frontend.source.apply and frontend.surface.audit; they belong in operators/errors.json with a scope list.",
|
|
4
|
+
"codes": {
|
|
5
|
+
"KNOWLEDGE_UNBOUND": {
|
|
6
|
+
"domain": "knowledge",
|
|
7
|
+
"disposition": "terminate",
|
|
8
|
+
"meaning": {
|
|
9
|
+
"en": "A presentation property is present in the tree and no knowledge topic is bound for it.",
|
|
10
|
+
"vi": "Một thuộc tính trình bày có trong cây mà không topic kiến thức nào được bind cho nó."
|
|
11
|
+
},
|
|
12
|
+
"resume": {
|
|
13
|
+
"en": "Bind the missing topic.",
|
|
14
|
+
"vi": "Bind topic còn thiếu."
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"RULE_MISSING": {
|
|
18
|
+
"domain": "knowledge",
|
|
19
|
+
"disposition": "terminate",
|
|
20
|
+
"meaning": {
|
|
21
|
+
"en": "No published case matches the observed condition on a node.",
|
|
22
|
+
"vi": "Không case nào đã publish khớp điều kiện quan sát được trên một node."
|
|
23
|
+
},
|
|
24
|
+
"resume": {
|
|
25
|
+
"en": "The knowledge owner publishes the case, and the tree is resolved again.",
|
|
26
|
+
"vi": "Chủ knowledge publish case, rồi cây được resolve lại."
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"GRAMMAR_UNPUBLISHED": {
|
|
30
|
+
"domain": "grammar",
|
|
31
|
+
"disposition": "terminate",
|
|
32
|
+
"meaning": {
|
|
33
|
+
"en": "The Grammar package is unpublished or the bound fingerprint is stale.",
|
|
34
|
+
"vi": "Gói Grammar chưa publish hoặc fingerprint đã bind là cũ."
|
|
35
|
+
},
|
|
36
|
+
"resume": {
|
|
37
|
+
"en": "A person publishes the exact Grammar package.",
|
|
38
|
+
"vi": "Người publish đúng gói Grammar."
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 9,
|
|
3
|
+
"id": "frontend.presentation.resolve",
|
|
4
|
+
"domain": "frontend",
|
|
5
|
+
"job": "Resolve every application-owned presentation property on one already-composed tree to exactly one published rule, emit its class and verifiable contract claim, and stop at the smallest owning gap instead of inventing a value.",
|
|
6
|
+
"package": "operator.md",
|
|
7
|
+
"errors": "errors.json",
|
|
8
|
+
"validator": "validate.mjs",
|
|
9
|
+
"selfTest": "self-test.mjs",
|
|
10
|
+
"resources": {
|
|
11
|
+
"profile": "luna",
|
|
12
|
+
"grammarBound": true,
|
|
13
|
+
"tools": {
|
|
14
|
+
"@tools/fileread": "context-aliases",
|
|
15
|
+
"@tools/git": "read",
|
|
16
|
+
"@tools/registry": "read"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# frontend.presentation.resolve
|
|
2
|
+
|
|
3
|
+
## Job
|
|
4
|
+
|
|
5
|
+
Resolve every application-owned presentation property on one already-composed tree to exactly one
|
|
6
|
+
published rule, emit its class and its verifiable contract claim, and stop at the smallest owning gap
|
|
7
|
+
instead of inventing a value.
|
|
8
|
+
|
|
9
|
+
## Structure arrives decided
|
|
10
|
+
|
|
11
|
+
Structure, element order, Grammar component selection, copy, data and behaviour arrive decided, and
|
|
12
|
+
so does the owner ceiling: it is carried by the direction this branch resolves, never re-declared
|
|
13
|
+
here. This operator only answers, for each node the application owns, which value each presentation
|
|
14
|
+
property takes and which rule authorizes it. It changes nothing about what the tree renders.
|
|
15
|
+
|
|
16
|
+
## No fabricated rule
|
|
17
|
+
|
|
18
|
+
A rule exists only if the bound knowledge topic publishes its identifier, and that inventory is
|
|
19
|
+
frozen for the whole run. An emitted identifier absent from the inventory is `UNKNOWN_RULE`. A class
|
|
20
|
+
that contradicts its identifier is rejected: the rule number is an ordinal on the value scale, so
|
|
21
|
+
`GAP-5` renders `gap-6` and `PADDING-5` renders `p-6`, and writing the ordinal as the step is the
|
|
22
|
+
defect this check exists to catch. When no published case matches the observed condition the run
|
|
23
|
+
stops with `RULE_MISSING` naming that node; it does not choose a nearby value, round to the closest
|
|
24
|
+
step, or copy a neighbouring node. The operator never edits knowledge: a missing case goes back to
|
|
25
|
+
the knowledge owner, and the same tree is resolved again once the case is published.
|
|
26
|
+
|
|
27
|
+
## Grammar is read as published, and consulted first
|
|
28
|
+
|
|
29
|
+
The owned relationships come from the published package's own data-contract claims, never from
|
|
30
|
+
Grammar source. A property a component already owns resolves to that component, emits no application
|
|
31
|
+
class, and names the rule the component satisfies; that ordering makes reimplementation impossible
|
|
32
|
+
rather than merely discouraged. An application class that reimplements an owned relationship,
|
|
33
|
+
overrides Grammar anatomy or sits off the closed scale is removed with its own row, per node and
|
|
34
|
+
never silently.
|
|
35
|
+
|
|
36
|
+
## A forbidden class is removed, not ruled
|
|
37
|
+
|
|
38
|
+
When the only case that names an application class states a condition the node does not meet (an
|
|
39
|
+
accent foreground that `SURFACE-4` allows solely inside a raised band, written on an unraised row),
|
|
40
|
+
the property is not missing a rule: the rule has answered, and the answer is no. The class is removed
|
|
41
|
+
in the removal step, the property falls back to what the node inherits, and the removal is recorded
|
|
42
|
+
with the case that refused it. `RULE_MISSING` is reserved for a property no published case addresses
|
|
43
|
+
at all.
|
|
44
|
+
|
|
45
|
+
## A missing public path is a gap, not a stop
|
|
46
|
+
|
|
47
|
+
When Common exposes no public path for a relationship the application legitimately needs, the node
|
|
48
|
+
keeps its application class and the branch records a row under `## Gaps` naming the node, the
|
|
49
|
+
property and the missing path. The branch does not stop: a recorded workaround is visible to the
|
|
50
|
+
family owner and to the next audit, while a stop here would only trade one silent value for a
|
|
51
|
+
blocked chain.
|
|
52
|
+
|
|
53
|
+
## The contract is a claim, not a verdict
|
|
54
|
+
|
|
55
|
+
Every application-owned node publishes the identifiers it claims. `data-contract` records which
|
|
56
|
+
rules a node claims to satisfy and never asserts that the node passes; the claim exists so a later
|
|
57
|
+
audit can contradict it, and one rule stays selectable as `[data-contract~="GAP-4"]`. With emission
|
|
58
|
+
off the tree carries nothing and the receipt alone holds the claims.
|
|
59
|
+
|
|
60
|
+
## The loop is counted
|
|
61
|
+
|
|
62
|
+
An audit that sends its findings back here starts another round, and a round that repeats itself is
|
|
63
|
+
not progress. The number of audit receipts this session has fed back is counted at the gate, and a
|
|
64
|
+
run beyond `maxRounds` stops with `NO_PROGRESS` rather than resolving the same tree a third time.
|
|
65
|
+
|
|
66
|
+
## Boundary
|
|
67
|
+
|
|
68
|
+
Context is read-only. The operator writes only `response/` of its own branch: the resolution receipt,
|
|
69
|
+
the inventory and the resolved tree. It does not change DOM structure, element order, Grammar
|
|
70
|
+
component selection, copy or behaviour, write a class for a property a Grammar component already
|
|
71
|
+
owns, reach into Grammar anatomy with a selector or a passed class, edit knowledge, publish Grammar,
|
|
72
|
+
write product source, or record a verdict, score or pass claim on any node.
|
|
73
|
+
|
|
74
|
+
## Context
|
|
75
|
+
|
|
76
|
+
| Alias | Bind | Required |
|
|
77
|
+
| --- | --- | --- |
|
|
78
|
+
| `@knowledge/ui/presentation` | the closed rule inventory read at its fingerprint; the only source of valid identifiers | yes |
|
|
79
|
+
| `@grammar/core` | the published package's owned relationships, read as published and never from Grammar source | yes |
|
|
80
|
+
| `@workspaces/fe` | the routed checkout the composed tree belongs to, read at the frozen head | yes |
|
|
81
|
+
|
|
82
|
+
## Inputs
|
|
83
|
+
|
|
84
|
+
| Kind | From | Required |
|
|
85
|
+
| --- | --- | --- |
|
|
86
|
+
| `frontend-direction-decision` | `frontend.direction.decide`, the intent and the owner ceiling this resolution works inside; never a source of presentation values | yes |
|
|
87
|
+
| `frontend-surface-audit` | `frontend.surface.audit`, the findings that opened this round; present only when this is a loop | no |
|
|
88
|
+
|
|
89
|
+
## Requirements
|
|
90
|
+
|
|
91
|
+
| Field | Type | Default | Ask |
|
|
92
|
+
| --- | --- | --- | --- |
|
|
93
|
+
| `maxRounds` | number | 2 | How many audit-to-resolve rounds this surface may take before the loop is called off |
|
|
94
|
+
| `contractEmission` | choice | on | `on` writes the claim token list onto the tree, `off` leaves the receipt as the record |
|
|
95
|
+
| `resume` | token | null | The blocked branch's token when re-entering after a stop |
|
|
96
|
+
|
|
97
|
+
## Steps
|
|
98
|
+
|
|
99
|
+
| # | Step | Params | Reads | Writes | Stops with |
|
|
100
|
+
| --- | --- | --- | --- | --- | --- |
|
|
101
|
+
| 1 | Validate the gate and resume, and count the audit rounds | `resume`, `maxRounds` | `request/request.json`, input `frontend-surface-audit` when this is a loop, @workspaces/fe at the frozen head | — | `INVALID_INPUT`, `SOURCE_DRIFT`, `NO_PROGRESS` |
|
|
102
|
+
| 2 | Bind the authority | — | @knowledge/ui/presentation (every topic with its fingerprint and rule inventory), @grammar/core (the published package's owned relationships), @workspaces/fe (the routed head and the frozen tree), input `frontend-direction-decision`, @tools/git, @tools/registry | — | `KNOWLEDGE_UNBOUND`, `GRAMMAR_UNPUBLISHED` |
|
|
103
|
+
| 3 | Walk the tree once under the owner ceiling the direction carries | — | @workspaces/fe (the frozen tree, in document order), input `frontend-direction-decision` | — | `OWNER_CONFLICT` |
|
|
104
|
+
| 4 | Determine the owner of every present property | — | @grammar/core (the owned relationships), @workspaces/fe (the properties the node presently carries) | `response/data/inventory.json` | — |
|
|
105
|
+
| 5 | Select one presentation rule per remaining application-owned property | — | @knowledge/ui/presentation (the cases the bound topic publishes) | — | `RULE_MISSING` |
|
|
106
|
+
| 6 | Classify a missing public path as a Grammar gap | — | @grammar/core (the relationship under question), @knowledge/ui/presentation (the capability-gap marking) | — | — |
|
|
107
|
+
| 7 | Remove what the tree should not carry | — | @workspaces/fe (the application classes on the node), @grammar/core (Grammar anatomy and the closed scale) | — | — |
|
|
108
|
+
| 8 | Emit the contract claims onto the application-owned nodes | `contractEmission` | @knowledge/ui/presentation (the frozen rule inventory) | — | `UNKNOWN_RULE` |
|
|
109
|
+
| 9 | Emit | — | everything above | `response/artifacts/<target>.resolved.tsx`, `response/data/inventory.json`, `response/response.md`, `response/response.json` | — |
|
|
110
|
+
|
|
111
|
+
The walk visits every node in document order and records a stable node path; a node outside the
|
|
112
|
+
ceiling the direction carries is observed and never mutated. Steps 4 to 8 run per node, so a single
|
|
113
|
+
tree yields one decision per node and property. The receipt authorizes a later audit to measure the
|
|
114
|
+
rendered result against the claims; it proves nothing about how the tree renders.
|
|
115
|
+
|
|
116
|
+
## Outputs
|
|
117
|
+
|
|
118
|
+
| Kind | File | Type | Required |
|
|
119
|
+
| --- | --- | --- | --- |
|
|
120
|
+
| `frontend-presentation-resolution` | `response/response.md` | md | yes |
|
|
121
|
+
| `inventory` | `response/data/inventory.json` | data | yes |
|
|
122
|
+
| `resolved-tree` | `response/artifacts/<target>.resolved.tsx` | artifact | yes |
|
|
123
|
+
|
|
124
|
+
## Stops
|
|
125
|
+
|
|
126
|
+
| Code | Disposition |
|
|
127
|
+
| --- | --- |
|
|
128
|
+
| `INVALID_INPUT` | terminate |
|
|
129
|
+
| `SOURCE_DRIFT` | terminate |
|
|
130
|
+
| `OWNER_CONFLICT` | terminate |
|
|
131
|
+
| `KNOWLEDGE_UNBOUND` | terminate |
|
|
132
|
+
| `UNKNOWN_RULE` | terminate |
|
|
133
|
+
| `RULE_MISSING` | terminate |
|
|
134
|
+
| `GRAMMAR_UNPUBLISHED` | terminate |
|
|
135
|
+
| `NO_PROGRESS` | terminate |
|
|
136
|
+
|
|
137
|
+
## Next
|
|
138
|
+
|
|
139
|
+
| When | Operator |
|
|
140
|
+
| --- | --- |
|
|
141
|
+
| the tree is resolved and its values must be written into product source | `frontend.source.apply` |
|
|
142
|
+
| a gap needs a family component before the next round, so a person publishes it and the same tree is resolved again | `frontend.presentation.resolve` |
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frontend.presentation.resolve
|
|
2
|
+
|
|
3
|
+
## Việc
|
|
4
|
+
|
|
5
|
+
Resolve mọi thuộc tính trình bày do ứng dụng sở hữu trên một cây đã compose sẵn về đúng một luật đã
|
|
6
|
+
publish, phát ra class và lời khai contract kiểm chứng được của nó, và dừng ở khoảng trống có chủ nhỏ
|
|
7
|
+
nhất thay vì bịa ra một giá trị.
|
|
8
|
+
|
|
9
|
+
## Cấu trúc đến nơi là đã quyết xong
|
|
10
|
+
|
|
11
|
+
Cấu trúc, thứ tự phần tử, việc chọn component Grammar, chữ, dữ liệu và hành vi đến nơi là đã quyết
|
|
12
|
+
xong, và trần owner cũng vậy: nó do chính cái hướng mà nhánh này resolve mang theo, không bao giờ
|
|
13
|
+
được khai lại ở đây. Operator này chỉ trả lời, cho từng node ứng dụng sở hữu, mỗi thuộc tính trình
|
|
14
|
+
bày nhận giá trị nào và luật nào uỷ quyền cho giá trị ấy. Nó không đổi gì về thứ cây render ra.
|
|
15
|
+
|
|
16
|
+
## Không có luật bịa
|
|
17
|
+
|
|
18
|
+
Một luật chỉ tồn tại khi topic kiến thức được bind publish đúng identifier của nó, và kho luật ấy
|
|
19
|
+
đóng băng suốt lần chạy. Một identifier phát ra mà không có trong kho là `UNKNOWN_RULE`. Một class
|
|
20
|
+
chỏi với identifier của nó bị từ chối: số hiệu luật là số thứ tự trên thang giá trị, nên `GAP-5`
|
|
21
|
+
render ra `gap-6` và `PADDING-5` render ra `p-6`, và viết số thứ tự thành bước thang chính là lỗi mà
|
|
22
|
+
phép kiểm này sinh ra để bắt. Khi không case nào đã publish khớp điều kiện quan sát được, lần chạy
|
|
23
|
+
dừng với `RULE_MISSING` gọi tên đúng node đó; nó không chọn giá trị gần, không làm tròn về bước gần
|
|
24
|
+
nhất, không chép của node bên cạnh. Operator không bao giờ sửa knowledge: case còn thiếu được trả về
|
|
25
|
+
cho chủ knowledge, và chính cây ấy được resolve lại sau khi case được publish.
|
|
26
|
+
|
|
27
|
+
## Grammar đọc ở bản đã publish, và được hỏi trước
|
|
28
|
+
|
|
29
|
+
Các quan hệ đã sở hữu lấy từ chính lời khai data-contract của gói đã publish, không bao giờ lấy từ
|
|
30
|
+
source của Grammar. Một thuộc tính mà component đã sở hữu sẽ resolve về component ấy, không phát class
|
|
31
|
+
ứng dụng nào, và gọi tên luật mà component thoả; thứ tự đó làm việc hiện thực lại thành bất khả thi
|
|
32
|
+
chứ không chỉ là điều bị khuyên can. Một class ứng dụng hiện thực lại quan hệ đã có chủ, đè lên giải
|
|
33
|
+
phẫu Grammar hay nằm ngoài thang đóng sẽ bị bỏ kèm một dòng ghi của chính nó, theo từng node và không
|
|
34
|
+
bao giờ im lặng.
|
|
35
|
+
|
|
36
|
+
## Class bị cấm thì gỡ, không phải thiếu rule
|
|
37
|
+
|
|
38
|
+
Khi case duy nhất gọi tên một class của ứng dụng nêu điều kiện mà node không thoả (foreground accent
|
|
39
|
+
mà `SURFACE-4` chỉ cho phép trong một dải raised, lại viết lên một hàng không raised), thuộc tính đó
|
|
40
|
+
không thiếu rule: rule đã trả lời, và câu trả lời là không. Class bị gỡ ở bước gỡ bỏ, thuộc tính rơi
|
|
41
|
+
về giá trị node kế thừa, và việc gỡ được ghi kèm case đã từ chối nó. `RULE_MISSING` chỉ dành cho thuộc
|
|
42
|
+
tính không case nào đã publish nhắc tới.
|
|
43
|
+
|
|
44
|
+
## Thiếu đường công khai là một khoảng trống, không phải một lần dừng
|
|
45
|
+
|
|
46
|
+
Khi Common không mở đường công khai nào cho một quan hệ mà ứng dụng cần một cách chính đáng, node giữ
|
|
47
|
+
lại class ứng dụng của nó và nhánh ghi một dòng vào `## Gaps` gọi tên node, thuộc tính và đường còn
|
|
48
|
+
thiếu. Nhánh không dừng: một cách chữa cháy có ghi sổ thì chủ họ và lượt audit sau đều thấy, còn dừng
|
|
49
|
+
ở đây chỉ đổi một giá trị im lặng lấy một chuỗi bị chặn.
|
|
50
|
+
|
|
51
|
+
## Contract là lời khai, không phải phán quyết
|
|
52
|
+
|
|
53
|
+
Mọi node do ứng dụng sở hữu đều công bố các identifier nó khai. `data-contract` ghi lại node khai
|
|
54
|
+
thoả những luật nào và không bao giờ khẳng định node đó pass; lời khai tồn tại để một lượt audit sau
|
|
55
|
+
có thể phản bác, và một luật vẫn chọn được trực tiếp bằng `[data-contract~="GAP-4"]`. Khi tắt chế độ
|
|
56
|
+
phát, cây không mang gì và một mình biên nhận giữ lời khai.
|
|
57
|
+
|
|
58
|
+
## Vòng lặp được đếm
|
|
59
|
+
|
|
60
|
+
Một lượt audit gửi phát hiện ngược về đây là mở thêm một vòng, và một vòng lặp lại chính nó thì không
|
|
61
|
+
phải tiến triển. Số biên nhận audit mà phiên này đã đẩy ngược về được đếm ngay ở gate, và một lần
|
|
62
|
+
chạy vượt `maxRounds` sẽ dừng với `NO_PROGRESS` thay vì resolve cùng một cây tới lần thứ ba.
|
|
63
|
+
|
|
64
|
+
## Ranh giới
|
|
65
|
+
|
|
66
|
+
Context chỉ đọc. Operator chỉ ghi `response/` của nhánh mình: biên nhận resolution, bản kiểm kê và
|
|
67
|
+
cây đã resolve. Nó không đổi cấu trúc DOM, thứ tự phần tử, việc chọn component Grammar, chữ hay hành
|
|
68
|
+
vi, không viết class cho thuộc tính mà một component Grammar đã sở hữu, không thò tay vào giải phẫu
|
|
69
|
+
Grammar bằng selector hay class truyền vào, không sửa knowledge, không publish Grammar, không ghi
|
|
70
|
+
source sản phẩm, và không ghi phán quyết, điểm số hay tuyên bố pass lên bất kỳ node nào.
|
|
71
|
+
|
|
72
|
+
## Context
|
|
73
|
+
|
|
74
|
+
| Alias | Bind | Bắt buộc |
|
|
75
|
+
| --- | --- | --- |
|
|
76
|
+
| `@knowledge/ui/presentation` | kho luật đóng, đọc ở fingerprint của nó; nguồn duy nhất của identifier hợp lệ | có |
|
|
77
|
+
| `@grammar/core` | các quan hệ đã sở hữu của gói đã publish, đọc ở bản publish chứ không bao giờ từ source Grammar | có |
|
|
78
|
+
| `@workspaces/fe` | checkout được route mà cây đã compose thuộc về, đọc ở head đóng băng | có |
|
|
79
|
+
|
|
80
|
+
## Đầu vào
|
|
81
|
+
|
|
82
|
+
| Kind | Từ đâu | Bắt buộc |
|
|
83
|
+
| --- | --- | --- |
|
|
84
|
+
| `frontend-direction-decision` | `frontend.direction.decide`, ý đồ và trần owner mà lượt resolve này làm việc bên trong; không bao giờ là nguồn giá trị trình bày | có |
|
|
85
|
+
| `frontend-surface-audit` | `frontend.surface.audit`, các phát hiện mở ra vòng này; chỉ có mặt khi đây là một vòng lặp | không |
|
|
86
|
+
|
|
87
|
+
## Yêu cầu
|
|
88
|
+
|
|
89
|
+
| Field | Kiểu | Mặc định | Hỏi |
|
|
90
|
+
| --- | --- | --- | --- |
|
|
91
|
+
| `maxRounds` | number | 2 | Bề mặt này được đi bao nhiêu vòng audit rồi resolve trước khi gọi dừng vòng lặp |
|
|
92
|
+
| `contractEmission` | choice | on | `on` ghi danh sách token lời khai lên cây, `off` để một mình biên nhận làm bằng |
|
|
93
|
+
| `resume` | token | null | Token của nhánh bị chặn khi vào lại sau một mã dừng |
|
|
94
|
+
|
|
95
|
+
## Các bước
|
|
96
|
+
|
|
97
|
+
| # | Bước | Tham số | Đọc | Ghi | Dừng với |
|
|
98
|
+
| --- | --- | --- | --- | --- | --- |
|
|
99
|
+
| 1 | Kiểm gate, chạy lại, và đếm số vòng audit | `resume`, `maxRounds` | `request/request.json`, đầu vào `frontend-surface-audit` khi đây là vòng lặp, @workspaces/fe ở head đóng băng | — | `INVALID_INPUT`, `SOURCE_DRIFT`, `NO_PROGRESS` |
|
|
100
|
+
| 2 | Bind thẩm quyền | — | @knowledge/ui/presentation (mọi topic kèm fingerprint và kho luật), @grammar/core (các quan hệ đã sở hữu của gói đã publish), @workspaces/fe (head được route và cây đã đóng băng), đầu vào `frontend-direction-decision`, @tools/git, @tools/registry | — | `KNOWLEDGE_UNBOUND`, `GRAMMAR_UNPUBLISHED` |
|
|
101
|
+
| 3 | Đi hết cây một lượt dưới trần owner mà hướng mang theo | — | @workspaces/fe (cây đóng băng, theo thứ tự tài liệu), đầu vào `frontend-direction-decision` | — | `OWNER_CONFLICT` |
|
|
102
|
+
| 4 | Xác định chủ của từng thuộc tính đang có | — | @grammar/core (các quan hệ đã sở hữu), @workspaces/fe (thuộc tính node đang mang) | `response/data/inventory.json` | — |
|
|
103
|
+
| 5 | Chọn một luật trình bày cho mỗi thuộc tính ứng dụng còn sở hữu | — | @knowledge/ui/presentation (các case topic được bind publish) | — | `RULE_MISSING` |
|
|
104
|
+
| 6 | Xếp một đường công khai còn thiếu thành khoảng trống Grammar | — | @grammar/core (quan hệ đang xét), @knowledge/ui/presentation (dấu khoảng trống năng lực) | — | — |
|
|
105
|
+
| 7 | Bỏ những gì cây không nên mang | — | @workspaces/fe (class ứng dụng trên node), @grammar/core (giải phẫu Grammar và thang đóng) | — | — |
|
|
106
|
+
| 8 | Phát lời khai contract lên các node do ứng dụng sở hữu | `contractEmission` | @knowledge/ui/presentation (kho luật đã đóng băng) | — | `UNKNOWN_RULE` |
|
|
107
|
+
| 9 | Phát | — | mọi thứ ở trên | `response/artifacts/<target>.resolved.tsx`, `response/data/inventory.json`, `response/response.md`, `response/response.json` | — |
|
|
108
|
+
|
|
109
|
+
Lượt đi thăm mọi node theo thứ tự tài liệu và ghi một node path ổn định; node nằm ngoài trần mà hướng
|
|
110
|
+
mang theo thì chỉ quan sát chứ không bao giờ bị sửa. Bước 4 đến 8 chạy theo từng node, nên một cây cho
|
|
111
|
+
đúng một quyết định cho mỗi cặp node và thuộc tính. Biên nhận uỷ quyền cho một lượt audit sau đo kết
|
|
112
|
+
quả render đối chiếu với lời khai; nó không chứng minh gì về việc cây render ra sao.
|
|
113
|
+
|
|
114
|
+
## Đầu ra
|
|
115
|
+
|
|
116
|
+
| Kind | File | Kiểu | Bắt buộc |
|
|
117
|
+
| --- | --- | --- | --- |
|
|
118
|
+
| `frontend-presentation-resolution` | `response/response.md` | md | có |
|
|
119
|
+
| `inventory` | `response/data/inventory.json` | data | có |
|
|
120
|
+
| `resolved-tree` | `response/artifacts/<target>.resolved.tsx` | artifact | có |
|
|
121
|
+
|
|
122
|
+
## Dừng
|
|
123
|
+
|
|
124
|
+
| Code | Xử lý |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| `INVALID_INPUT` | terminate |
|
|
127
|
+
| `SOURCE_DRIFT` | terminate |
|
|
128
|
+
| `OWNER_CONFLICT` | terminate |
|
|
129
|
+
| `KNOWLEDGE_UNBOUND` | terminate |
|
|
130
|
+
| `UNKNOWN_RULE` | terminate |
|
|
131
|
+
| `RULE_MISSING` | terminate |
|
|
132
|
+
| `GRAMMAR_UNPUBLISHED` | terminate |
|
|
133
|
+
| `NO_PROGRESS` | terminate |
|
|
134
|
+
|
|
135
|
+
## Kế tiếp
|
|
136
|
+
|
|
137
|
+
| Khi | Operator |
|
|
138
|
+
| --- | --- |
|
|
139
|
+
| cây đã resolve và các giá trị của nó phải được ghi vào source sản phẩm | `frontend.source.apply` |
|
|
140
|
+
| một khoảng trống cần component của họ trước vòng sau, nên một người publish nó rồi chính cây ấy được resolve lại | `frontend.presentation.resolve` |
|