@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,196 @@
|
|
|
1
|
+
// content.generate's own law over one branch, on top of the shared step check: the brief is the measure
|
|
2
|
+
// of everything after it, and the receipt restates it; every declared edition exists once per language
|
|
3
|
+
// and covers the whole published outcome set; the image stage produces something only when stageModes
|
|
4
|
+
// turns it on, and a stage that stayed off is recorded rather than merely absent; every declared track
|
|
5
|
+
// builds and is exercised by the executable check inside the iteration bound, whose contract
|
|
6
|
+
// fingerprint did not move; and the review is a fresh execution that produced none of the artifacts,
|
|
7
|
+
// received all of them, received no producer rationale, approves only at or above the published
|
|
8
|
+
// minimum with no open error finding, and spends no more rounds than maxReviewRounds.
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
10
|
+
import { readFile } from 'node:fs/promises';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import process from 'node:process';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { validateStep } from '../../scripts/validate-step.mjs';
|
|
15
|
+
import { tableUnder } from '../../scripts/validate-response.mjs';
|
|
16
|
+
|
|
17
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
18
|
+
const MINIMUM_SCORE = 85;
|
|
19
|
+
const empty = (v) => v === undefined || v === null || v === '' || v === '—';
|
|
20
|
+
const fields = (rows) => Object.fromEntries((rows ?? []).map(([k, v]) => [k, v]));
|
|
21
|
+
const sameSet = (left, right) => { const a = new Set(left); const b = new Set(right); return a.size === b.size && [...a].every((item) => b.has(item)); };
|
|
22
|
+
const list = (v) => (Array.isArray(v) ? v : String(v ?? '').split(',').map((s) => s.trim()).filter(Boolean));
|
|
23
|
+
const listed = (value) => (value === undefined ? [] : Array.isArray(value) ? value : [value]);
|
|
24
|
+
// An edition is filed as article.<language>.md and a track as track.<language>.<extension>, so the
|
|
25
|
+
// language is everything between the prefix and the extension.
|
|
26
|
+
const languageOf = (file, prefix) => {
|
|
27
|
+
const parts = String(file).split('/').pop().split('.');
|
|
28
|
+
if (parts.length < 3 || parts[0] !== prefix) return null;
|
|
29
|
+
return parts.slice(1, -1).join('.');
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export async function validateContentStep(branchDir, root = ROOT) {
|
|
33
|
+
const base = await validateStep(root, branchDir);
|
|
34
|
+
const errors = [...base.errors];
|
|
35
|
+
const { response, requirements = {}, present = new Set() } = base;
|
|
36
|
+
if (!response || response.operatorId !== 'content.generate') return { errors };
|
|
37
|
+
const has = (f) => existsSync(path.join(branchDir, f));
|
|
38
|
+
const read = (f) => readFile(path.join(branchDir, f), 'utf8');
|
|
39
|
+
|
|
40
|
+
const naturalLanguages = list(requirements.naturalLanguages);
|
|
41
|
+
const implementationLanguages = list(requirements.implementationLanguages);
|
|
42
|
+
const imageOn = (requirements.stageModes ?? {}).image === 'on';
|
|
43
|
+
const maxE2eIterations = Number(requirements.maxE2eIterations ?? 2);
|
|
44
|
+
const maxReviewRounds = Number(requirements.maxReviewRounds ?? 2);
|
|
45
|
+
if (naturalLanguages.length === 0) errors.push('request.json: a unit is written in at least one natural language');
|
|
46
|
+
if (new Set(naturalLanguages).size !== naturalLanguages.length) errors.push('request.json: naturalLanguages must not repeat a language');
|
|
47
|
+
if (new Set(implementationLanguages).size !== implementationLanguages.length) errors.push('request.json: implementationLanguages must not repeat a language');
|
|
48
|
+
const commandLanguages = (Array.isArray(requirements.commands) ? requirements.commands : []).map((c) => c.language);
|
|
49
|
+
if (new Set(commandLanguages).size !== commandLanguages.length) errors.push('request.json: commands must not name a language twice');
|
|
50
|
+
if (!sameSet(commandLanguages, implementationLanguages)) errors.push('request.json: commands must cover exactly the declared implementationLanguages, and nothing else');
|
|
51
|
+
|
|
52
|
+
// A blocked branch carries no unit at all.
|
|
53
|
+
if (response.status === 'blocked' && (present.has('content-generation-receipt') || present.has('content-brief') || present.has('e2e'))) {
|
|
54
|
+
errors.push('response/response.json: a blocked branch carries no unit');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const articleFiles = listed(response.fields?.article);
|
|
58
|
+
const trackFiles = listed(response.fields?.track);
|
|
59
|
+
const imageFiles = listed(response.fields?.image);
|
|
60
|
+
const promptFiles = listed(response.fields?.['image-prompt']);
|
|
61
|
+
const articleLanguages = articleFiles.map((f) => languageOf(f, 'article'));
|
|
62
|
+
const trackLanguages = trackFiles.map((f) => languageOf(f, 'track'));
|
|
63
|
+
if (response.status !== 'blocked') {
|
|
64
|
+
if (new Set(articleLanguages).size !== articleLanguages.length) errors.push('response/response.json: a language cannot have two article editions');
|
|
65
|
+
if (articleFiles.length && !sameSet(articleLanguages, naturalLanguages)) errors.push('response/response.json: the article editions must cover exactly the declared natural languages');
|
|
66
|
+
if (!sameSet(trackLanguages, implementationLanguages)) errors.push('response/response.json: the implementation tracks must cover exactly the declared implementation languages');
|
|
67
|
+
// The image stage is a decision, and a stage that is off produces nothing at all.
|
|
68
|
+
if (!imageOn && (imageFiles.length || promptFiles.length)) errors.push('response/response.json: stageModes turns the image off, so no image and no prompt may be produced');
|
|
69
|
+
if (imageOn && response.status === 'done' && (imageFiles.length === 0 || promptFiles.length === 0)) errors.push('response/response.json: stageModes turns the image on, so the unit carries an image and the prompt that states its intent');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let publishedOutcomes = [];
|
|
73
|
+
let publishedClaims = [];
|
|
74
|
+
let briefFingerprint = null;
|
|
75
|
+
if (present.has('content-brief') && has('response/brief.md')) {
|
|
76
|
+
const text = await read('response/brief.md');
|
|
77
|
+
const binding = fields(tableUnder(text, '## Binding'));
|
|
78
|
+
briefFingerprint = binding.Fingerprint;
|
|
79
|
+
if (!empty(requirements.unit) && binding.Unit !== requirements.unit) errors.push('response/brief.md: Unit differs from the request');
|
|
80
|
+
publishedOutcomes = (tableUnder(text, '## Outcomes') ?? []).map(([id]) => id);
|
|
81
|
+
publishedClaims = (tableUnder(text, '## Claims') ?? []).map(([id]) => id);
|
|
82
|
+
if (new Set(publishedOutcomes).size !== publishedOutcomes.length) errors.push('response/brief.md: an outcome is published twice');
|
|
83
|
+
if (new Set(publishedClaims).size !== publishedClaims.length) errors.push('response/brief.md: a claim is published twice');
|
|
84
|
+
for (const [kind, target] of tableUnder(text, '## Dispositions') ?? []) if (kind !== 'add' && empty(target)) errors.push(`response/brief.md: a ${kind} disposition must name what it acts on`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let e2e = null;
|
|
88
|
+
if (present.has('e2e') && has('response/data/e2e.json')) { try { e2e = JSON.parse(await read('response/data/e2e.json')); } catch { e2e = null; } }
|
|
89
|
+
if (implementationLanguages.length === 0 && e2e !== null) errors.push('response/data/e2e.json: no implementation language is declared, so nothing was built and nothing ran');
|
|
90
|
+
if (implementationLanguages.length > 0 && e2e === null && response.status === 'done') errors.push('response/data/e2e.json: a unit that ships code ships the record of building and running it');
|
|
91
|
+
if (e2e) {
|
|
92
|
+
if (!empty(requirements.unit) && e2e.unitId !== requirements.unit) errors.push(`response/data/e2e.json: unitId ${e2e.unitId} differs from the request's ${requirements.unit}`);
|
|
93
|
+
if (e2e.maxIterations !== maxE2eIterations) errors.push(`response/data/e2e.json: maxIterations ${e2e.maxIterations} differs from the request's ${maxE2eIterations}`);
|
|
94
|
+
if (e2e.iterations > maxE2eIterations) errors.push(`response/data/e2e.json: the executable check spent ${e2e.iterations} iterations, past the bound of ${maxE2eIterations}`);
|
|
95
|
+
// The repair loop may fix the implementation. It may never move the contract it is measured by.
|
|
96
|
+
if (e2e.contractFingerprintBefore !== e2e.contractFingerprintAfter) errors.push('response/data/e2e.json: the executable contract changed during the repair loop, so the proof measures nothing');
|
|
97
|
+
const builtLanguages = e2e.tracks.map((t) => t.language);
|
|
98
|
+
if (new Set(builtLanguages).size !== builtLanguages.length) errors.push('response/data/e2e.json: a language cannot have two implementation tracks');
|
|
99
|
+
if (!sameSet(builtLanguages, implementationLanguages)) errors.push('response/data/e2e.json: the build records must cover exactly the declared implementation languages');
|
|
100
|
+
const runLanguages = e2e.runs.map((r) => r.language);
|
|
101
|
+
if (new Set(runLanguages).size !== runLanguages.length) errors.push('response/data/e2e.json: a language cannot have two executable-check runs');
|
|
102
|
+
if (!sameSet(runLanguages, builtLanguages)) errors.push('response/data/e2e.json: every implementation track must be exercised by the executable check');
|
|
103
|
+
const declaredCommands = new Map((Array.isArray(requirements.commands) ? requirements.commands : []).map((c) => [c.language, c]));
|
|
104
|
+
for (const track of e2e.tracks) {
|
|
105
|
+
const command = declaredCommands.get(track.language);
|
|
106
|
+
if (command && track.buildCommand !== command.buildCommand) errors.push(`response/data/e2e.json: the ${track.language} track was built with ${track.buildCommand}, the request declared ${command.buildCommand}`);
|
|
107
|
+
if (response.status === 'done' && track.exitCode !== 0) errors.push(`response/data/e2e.json: the ${track.language} track exits ${track.exitCode} and cannot be shipped as working code`);
|
|
108
|
+
}
|
|
109
|
+
for (const run of e2e.runs) {
|
|
110
|
+
const command = declaredCommands.get(run.language);
|
|
111
|
+
if (command && run.command !== command.checkCommand) errors.push(`response/data/e2e.json: the ${run.language} check ran ${run.command}, the request declared ${command.checkCommand}`);
|
|
112
|
+
if (response.status === 'done' && run.exitCode !== 0) errors.push(`response/data/e2e.json: the ${run.language} executable check exits ${run.exitCode} and proves nothing`);
|
|
113
|
+
if (response.status === 'done') for (const assertion of run.assertions) if (!assertion.held) errors.push(`response/data/e2e.json: the ${run.language} assertion ${assertion.name} did not hold, so the check proves nothing`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const produced = [...articleFiles, ...trackFiles, ...imageFiles, ...promptFiles];
|
|
118
|
+
let verdict = null;
|
|
119
|
+
let round = null;
|
|
120
|
+
if (present.has('content-review') && has('review/response/review.md')) {
|
|
121
|
+
const text = await read('review/response/review.md');
|
|
122
|
+
const execution = fields(tableUnder(text, '## Execution'));
|
|
123
|
+
verdict = fields(tableUnder(text, '## Verdict')).Verdict;
|
|
124
|
+
round = Number(execution.Round);
|
|
125
|
+
// A unit that passes its own author's review has not been reviewed.
|
|
126
|
+
if (execution['Inherited turns'] !== 'none') errors.push('review/response/review.md: the review must be a fresh execution with no inherited turns');
|
|
127
|
+
if (execution['Producer rationale'] !== 'withheld') errors.push("review/response/review.md: the review may not receive the producer's rationale");
|
|
128
|
+
if (!Number.isInteger(round) || round < 1) errors.push('review/response/review.md: Round must be the number of this review round');
|
|
129
|
+
else if (round > maxReviewRounds) errors.push(`review/response/review.md: this is review round ${round}, past the approved maxReviewRounds of ${maxReviewRounds}`);
|
|
130
|
+
|
|
131
|
+
const received = (tableUnder(text, '## Received') ?? []).map(([artifact]) => artifact);
|
|
132
|
+
for (const ref of produced) if (!received.includes(ref)) errors.push(`review/response/review.md: the review never received ${ref}, so nothing reviewed it`);
|
|
133
|
+
|
|
134
|
+
const scores = (tableUnder(text, '## Scores') ?? []).filter(([, score]) => !empty(score)).map(([, score]) => Number(score));
|
|
135
|
+
const findings = tableUnder(text, '## Findings') ?? [];
|
|
136
|
+
const errorFindings = findings.filter(([, severity]) => severity === 'error');
|
|
137
|
+
if (verdict === 'approved') {
|
|
138
|
+
const lowest = scores.length ? Math.min(...scores) : 0;
|
|
139
|
+
if (lowest < MINIMUM_SCORE) errors.push(`review/response/review.md: the review approved the unit while a score sits at ${lowest}, below ${MINIMUM_SCORE}`);
|
|
140
|
+
if (errorFindings.length > 0) errors.push('review/response/review.md: the review approved the unit while an error finding remains open');
|
|
141
|
+
} else if (errorFindings.length === 0) errors.push('review/response/review.md: a revision verdict must name at least one error finding and its owning stage');
|
|
142
|
+
for (const [stage] of findings) {
|
|
143
|
+
if (stage === 'image' && !imageOn) errors.push('review/response/review.md: a finding cannot be assigned to the image stage, which stageModes turned off');
|
|
144
|
+
if ((stage === 'code' || stage === 'e2e') && implementationLanguages.length === 0) errors.push(`review/response/review.md: a finding cannot be assigned to the ${stage} stage, which never ran`);
|
|
145
|
+
}
|
|
146
|
+
if (response.status === 'done' && verdict !== 'approved') errors.push('review/response/review.md: a unit cannot be generated while the independent review demands a revision');
|
|
147
|
+
} else if (response.status === 'done') errors.push('review/response/review.md: a generated unit needs the review exchange');
|
|
148
|
+
|
|
149
|
+
// The revision fallback is bounded: every round past the first is one taken fallback, and the round
|
|
150
|
+
// after the last approved one is REVIEW_ROUNDS_EXHAUSTED rather than another quiet rewrite.
|
|
151
|
+
const revised = (response.fallbacks ?? []).includes('REVIEW_REVISION_REQUIRED');
|
|
152
|
+
if (revised && round !== null && round < 2) errors.push('response/response.json: REVIEW_REVISION_REQUIRED was taken, so the review that answered it is at least the second round');
|
|
153
|
+
if (!revised && round !== null && round > 1) errors.push(`response/response.json: this is review round ${round}, so the REVIEW_REVISION_REQUIRED fallback that reopened the exchange must be recorded`);
|
|
154
|
+
if (response.status === 'blocked' && response.stop === 'REVIEW_ROUNDS_EXHAUSTED' && round !== null && round !== maxReviewRounds) {
|
|
155
|
+
errors.push(`response/response.json: the rounds are exhausted only at round ${maxReviewRounds}, and the review is at round ${round}`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (present.has('content-generation-receipt') && has('response/response.md')) {
|
|
159
|
+
const text = await read('response/response.md');
|
|
160
|
+
const binding = fields(tableUnder(text, '## Binding'));
|
|
161
|
+
if (!empty(requirements.unit) && binding.Unit !== requirements.unit) errors.push('response/response.md: Unit differs from the request');
|
|
162
|
+
if (briefFingerprint !== null && binding['Brief fingerprint'] !== briefFingerprint) errors.push('response/response.md: Brief fingerprint differs from the frozen brief');
|
|
163
|
+
if (verdict !== null && binding.Verdict !== verdict) errors.push(`response/response.md: Verdict ${binding.Verdict} differs from the review's ${verdict}`);
|
|
164
|
+
if (round !== null && Number(binding.Round) !== round) errors.push(`response/response.md: Round ${binding.Round} differs from the review's ${round}`);
|
|
165
|
+
|
|
166
|
+
const editions = tableUnder(text, '## Editions') ?? [];
|
|
167
|
+
if (!sameSet(editions.map(([language]) => language), articleLanguages.filter(Boolean))) errors.push('response/response.md: the editions differ from the article files the response registers');
|
|
168
|
+
for (const [language, article, covered] of editions) {
|
|
169
|
+
const expected = `response/artifacts/article.${language}.md`;
|
|
170
|
+
if (article !== expected) errors.push(`response/response.md: the ${language} edition names ${article}, and an edition of ${language} is filed as ${expected}`);
|
|
171
|
+
const claimed = list(covered);
|
|
172
|
+
for (const ref of claimed) if (publishedOutcomes.length && !publishedOutcomes.includes(ref)) errors.push(`response/response.md: the ${language} edition claims outcome ${ref}, which the brief never published`);
|
|
173
|
+
if (response.status === 'done') for (const ref of publishedOutcomes) if (!claimed.includes(ref)) errors.push(`response/response.md: the ${language} edition leaves published outcome ${ref} uncovered`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const approved = (tableUnder(text, '## Approved artifacts') ?? []).map(([artifact]) => artifact);
|
|
177
|
+
if (response.status === 'done') {
|
|
178
|
+
if (approved.length === 0) errors.push('response/response.md: a generated unit must name the artifacts the review approved');
|
|
179
|
+
for (const ref of approved) if (produced.length && !produced.includes(ref)) errors.push(`response/response.md: approved artifact ${ref} was never produced by this unit`);
|
|
180
|
+
}
|
|
181
|
+
// A stage that stayed off is a decision, and a decision that leaves no record reads later as an omission.
|
|
182
|
+
const recorded = new Set((tableUnder(text, '## Findings') ?? []).filter(([code]) => code === 'STAGE_DISABLED').map(([, stage]) => stage));
|
|
183
|
+
if (!imageOn && !recorded.has('image')) errors.push('response/response.md: the image stage stayed off and must be recorded as a STAGE_DISABLED finding');
|
|
184
|
+
if (implementationLanguages.length === 0) {
|
|
185
|
+
for (const stage of ['code', 'e2e']) if (!recorded.has(stage)) errors.push(`response/response.md: the ${stage} stage never ran and must be recorded as a STAGE_DISABLED finding`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return { errors };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
192
|
+
const target = process.argv[2];
|
|
193
|
+
if (!target) { process.stderr.write('usage: node validate.mjs <session>/step-N/parallel-M\n'); process.exit(2); }
|
|
194
|
+
const { errors } = await validateContentStep(path.resolve(target));
|
|
195
|
+
if (errors.length) { process.stderr.write(`${errors.join('\n')}\n`); process.exitCode = 1; } else process.stdout.write('valid content.generate branch\n');
|
|
196
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 9,
|
|
3
|
+
"note": "Stop codes shared by more than one operator. `scope` is the list of operator ids that may emit the code, or [\"*\"] for every operator. A code only one operator emits lives in that operator's own operators/<id>/errors.json with the same entry shape and no scope; scripts/errors-registry.mjs merges both into one registry and refuses a code defined twice. A code has exactly one disposition: `terminate` ends the step with response.json status blocked and stop = code; `fallback` performs the named action, records it under `## Fallbacks taken` in response.md, and continues. `unless` is the only way a disposition changes: it names one Requirements param and the value that flips the code to `then`. `domain` is the routing.json domain the code hands to; `self` means the emitting operator's own domain (a resume). A runtime that meets a code the merged registry does not list terminates with UNKNOWN_STOP.",
|
|
4
|
+
"codes": {
|
|
5
|
+
"INVALID_INPUT": {
|
|
6
|
+
"scope": [
|
|
7
|
+
"*"
|
|
8
|
+
],
|
|
9
|
+
"domain": "caller",
|
|
10
|
+
"disposition": "terminate",
|
|
11
|
+
"meaning": {
|
|
12
|
+
"en": "request.json fails the gate or the operator's Requirements.",
|
|
13
|
+
"vi": "request.json không qua gate hoặc bảng Yêu cầu của operator."
|
|
14
|
+
},
|
|
15
|
+
"resume": {
|
|
16
|
+
"en": "Correct request.json.",
|
|
17
|
+
"vi": "Sửa request.json."
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"SOURCE_DRIFT": {
|
|
21
|
+
"scope": [
|
|
22
|
+
"*"
|
|
23
|
+
],
|
|
24
|
+
"domain": "workspace",
|
|
25
|
+
"disposition": "terminate",
|
|
26
|
+
"meaning": {
|
|
27
|
+
"en": "The observed checkout head differs from the head request.json froze.",
|
|
28
|
+
"vi": "Head quan sát được của checkout khác head mà request.json đã đóng băng."
|
|
29
|
+
},
|
|
30
|
+
"resume": {
|
|
31
|
+
"en": "The orchestrator freezes the head again.",
|
|
32
|
+
"vi": "Orchestrator đóng băng head lại."
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"NO_PROGRESS": {
|
|
36
|
+
"scope": [
|
|
37
|
+
"*"
|
|
38
|
+
],
|
|
39
|
+
"domain": "caller",
|
|
40
|
+
"disposition": "terminate",
|
|
41
|
+
"meaning": {
|
|
42
|
+
"en": "A resume adds no evidence, constraint, inventory, or approval delta.",
|
|
43
|
+
"vi": "Lần chạy lại không thêm bằng chứng, ràng buộc, inventory hay phê duyệt nào."
|
|
44
|
+
},
|
|
45
|
+
"resume": {
|
|
46
|
+
"en": "Bring a real delta.",
|
|
47
|
+
"vi": "Mang một delta thật."
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"EVIDENCE_MISSING": {
|
|
51
|
+
"scope": [
|
|
52
|
+
"*"
|
|
53
|
+
],
|
|
54
|
+
"domain": "self",
|
|
55
|
+
"disposition": "terminate",
|
|
56
|
+
"meaning": {
|
|
57
|
+
"en": "A claim about the system has no file, line, or head behind it.",
|
|
58
|
+
"vi": "Một khẳng định về hệ thống không có file, dòng hay head nào đứng sau."
|
|
59
|
+
},
|
|
60
|
+
"resume": {
|
|
61
|
+
"en": "Add the evidence.",
|
|
62
|
+
"vi": "Bổ sung bằng chứng."
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"UNKNOWN_STOP": {
|
|
66
|
+
"scope": [
|
|
67
|
+
"*"
|
|
68
|
+
],
|
|
69
|
+
"domain": "caller",
|
|
70
|
+
"disposition": "terminate",
|
|
71
|
+
"meaning": {
|
|
72
|
+
"en": "The runtime met a code the merged registry does not list.",
|
|
73
|
+
"vi": "Runtime gặp một mã mà sổ gộp không có."
|
|
74
|
+
},
|
|
75
|
+
"resume": {
|
|
76
|
+
"en": "Register the code or fix the operator.",
|
|
77
|
+
"vi": "Đăng ký mã hoặc sửa operator."
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"OWNER_CONFLICT": {
|
|
81
|
+
"scope": [
|
|
82
|
+
"backend.source.apply",
|
|
83
|
+
"frontend.presentation.resolve",
|
|
84
|
+
"frontend.source.apply"
|
|
85
|
+
],
|
|
86
|
+
"domain": "caller",
|
|
87
|
+
"disposition": "terminate",
|
|
88
|
+
"meaning": {
|
|
89
|
+
"en": "A node that must be mutated lies outside the mutable owner ceiling, or the owner sets overlap.",
|
|
90
|
+
"vi": "Một node cần sửa nằm ngoài trần owner được sửa, hoặc hai tập owner chồng nhau."
|
|
91
|
+
},
|
|
92
|
+
"resume": {
|
|
93
|
+
"en": "Correct the owner authority.",
|
|
94
|
+
"vi": "Sửa thẩm quyền owner."
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"ROUTE_UNVERIFIED": {
|
|
98
|
+
"scope": [
|
|
99
|
+
"frontend.direction.decide",
|
|
100
|
+
"git.publish"
|
|
101
|
+
],
|
|
102
|
+
"domain": "workspace",
|
|
103
|
+
"disposition": "terminate",
|
|
104
|
+
"meaning": {
|
|
105
|
+
"en": "The project or the routed frontend checkout identity is not verified.",
|
|
106
|
+
"vi": "Danh tính project hoặc checkout frontend được route chưa được xác minh."
|
|
107
|
+
},
|
|
108
|
+
"resume": {
|
|
109
|
+
"en": "Bind the route again.",
|
|
110
|
+
"vi": "Bind lại route."
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"UNKNOWN_RULE": {
|
|
114
|
+
"scope": [
|
|
115
|
+
"frontend.presentation.resolve",
|
|
116
|
+
"frontend.surface.audit"
|
|
117
|
+
],
|
|
118
|
+
"domain": "self",
|
|
119
|
+
"disposition": "terminate",
|
|
120
|
+
"meaning": {
|
|
121
|
+
"en": "An identifier outside the bound rule inventory was reached for.",
|
|
122
|
+
"vi": "Một identifier ngoài kho luật đã bind bị với tới."
|
|
123
|
+
},
|
|
124
|
+
"resume": {
|
|
125
|
+
"en": "Bind the topic that publishes it, or correct the identifier.",
|
|
126
|
+
"vi": "Bind topic publish nó, hoặc sửa lại identifier."
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"RUNTIME_UNAVAILABLE": {
|
|
130
|
+
"scope": [
|
|
131
|
+
"frontend.surface.audit",
|
|
132
|
+
"uat.verify"
|
|
133
|
+
],
|
|
134
|
+
"domain": "platform",
|
|
135
|
+
"disposition": "terminate",
|
|
136
|
+
"meaning": {
|
|
137
|
+
"en": "The endpoint does not serve the bound route, or the surface never reaches readiness.",
|
|
138
|
+
"vi": "Endpoint không phục vụ route đã bind, hoặc bề mặt không bao giờ sẵn sàng."
|
|
139
|
+
},
|
|
140
|
+
"resume": {
|
|
141
|
+
"en": "Whoever runs the service serves the bound route; this operator never starts one.",
|
|
142
|
+
"vi": "Người vận hành dịch vụ cho route đã bind chạy; operator này không bao giờ tự khởi động."
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"APPROVAL_REQUIRED": {
|
|
146
|
+
"scope": [
|
|
147
|
+
"business.decide",
|
|
148
|
+
"release.deploy"
|
|
149
|
+
],
|
|
150
|
+
"domain": "caller",
|
|
151
|
+
"disposition": "terminate",
|
|
152
|
+
"meaning": {
|
|
153
|
+
"en": "The transition or the release needs an approval that no request bound.",
|
|
154
|
+
"vi": "Chuyển trạng thái hoặc release cần một phê duyệt mà request chưa ràng."
|
|
155
|
+
},
|
|
156
|
+
"resume": {
|
|
157
|
+
"en": "A person supplies the approval.",
|
|
158
|
+
"vi": "Người cấp phê duyệt."
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"BRANCH_POLICY_VIOLATION": {
|
|
162
|
+
"scope": [
|
|
163
|
+
"git.publish",
|
|
164
|
+
"workspace.bind"
|
|
165
|
+
],
|
|
166
|
+
"domain": "workspace",
|
|
167
|
+
"disposition": "terminate",
|
|
168
|
+
"meaning": {
|
|
169
|
+
"en": "The checkout is on a branch the routed Git policy forbids for this operation.",
|
|
170
|
+
"vi": "Checkout đang ở nhánh mà chính sách Git của route cấm với thao tác này."
|
|
171
|
+
},
|
|
172
|
+
"resume": {
|
|
173
|
+
"en": "Move to a permitted branch or change the routed policy.",
|
|
174
|
+
"vi": "Chuyển sang nhánh được phép hoặc đổi chính sách của route."
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 9,
|
|
3
|
+
"note": "Stop codes frontend.direction.decide emits. Same entry shape as operators/errors.json, scope implicit. Shared codes (INVALID_INPUT, SOURCE_DRIFT, NO_PROGRESS, EVIDENCE_MISSING) come from operators/errors.json.",
|
|
4
|
+
"codes": {
|
|
5
|
+
"SCOPE_UNFROZEN": {
|
|
6
|
+
"domain": "caller",
|
|
7
|
+
"disposition": "terminate",
|
|
8
|
+
"meaning": {
|
|
9
|
+
"en": "The target or the boundary of the surface is incomplete, so the UI contract cannot be closed.",
|
|
10
|
+
"vi": "Target hay ranh giới của bề mặt còn thiếu, nên không đóng được UI contract."
|
|
11
|
+
},
|
|
12
|
+
"resume": {
|
|
13
|
+
"en": "Freeze the scope.",
|
|
14
|
+
"vi": "Đóng băng scope."
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"CHANGE_LEVEL_AMBIGUOUS": {
|
|
18
|
+
"domain": "caller",
|
|
19
|
+
"disposition": "terminate",
|
|
20
|
+
"meaning": {
|
|
21
|
+
"en": "The authority for new, reconstruct or refine is unresolved or contradicts the intent.",
|
|
22
|
+
"vi": "Thẩm quyền cho new, reconstruct hay refine chưa rõ hoặc chỏi với intent."
|
|
23
|
+
},
|
|
24
|
+
"resume": {
|
|
25
|
+
"en": "State the exact change level.",
|
|
26
|
+
"vi": "Nêu đúng change level."
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"OWNER_CEILING_INVALID": {
|
|
30
|
+
"domain": "caller",
|
|
31
|
+
"disposition": "terminate",
|
|
32
|
+
"meaning": {
|
|
33
|
+
"en": "The direction needs an owner the declared ceiling does not authorize.",
|
|
34
|
+
"vi": "Hướng cần một owner mà trần đã khai không uỷ quyền."
|
|
35
|
+
},
|
|
36
|
+
"resume": {
|
|
37
|
+
"en": "Correct the owner ceiling.",
|
|
38
|
+
"vi": "Sửa trần owner."
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"BUSINESS_REQUIRED": {
|
|
42
|
+
"domain": "business",
|
|
43
|
+
"disposition": "terminate",
|
|
44
|
+
"meaning": {
|
|
45
|
+
"en": "An actor, promise, permission, adverse outcome or recovery truth the change level requires is unresolved.",
|
|
46
|
+
"vi": "Một actor, lời hứa, quyền, kết cục bất lợi hay đường phục hồi mà change level đòi vẫn chưa được giải quyết."
|
|
47
|
+
},
|
|
48
|
+
"resume": {
|
|
49
|
+
"en": "Run business.decide first.",
|
|
50
|
+
"vi": "Chạy business.decide trước."
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"BACKEND_REQUIRED": {
|
|
54
|
+
"domain": "backend",
|
|
55
|
+
"disposition": "terminate",
|
|
56
|
+
"meaning": {
|
|
57
|
+
"en": "The direction changes a data contract nobody delivered.",
|
|
58
|
+
"vi": "Hướng làm đổi một contract dữ liệu chưa ai giao."
|
|
59
|
+
},
|
|
60
|
+
"resume": {
|
|
61
|
+
"en": "Run backend.source.apply first.",
|
|
62
|
+
"vi": "Chạy backend.source.apply trước."
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"ARCHITECTURE_REQUIRED": {
|
|
66
|
+
"domain": "architecture",
|
|
67
|
+
"disposition": "terminate",
|
|
68
|
+
"meaning": {
|
|
69
|
+
"en": "The direction changes a system or data boundary nobody decided.",
|
|
70
|
+
"vi": "Hướng làm đổi một ranh giới hệ thống hay dữ liệu chưa ai quyết."
|
|
71
|
+
},
|
|
72
|
+
"resume": {
|
|
73
|
+
"en": "Run architecture.decide first.",
|
|
74
|
+
"vi": "Chạy architecture.decide trước."
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"GRAMMAR_REQUIRED": {
|
|
78
|
+
"domain": "grammar",
|
|
79
|
+
"disposition": "terminate",
|
|
80
|
+
"meaning": {
|
|
81
|
+
"en": "A family component the direction needs is unpublished; a composite is never assembled in its place.",
|
|
82
|
+
"vi": "Một component của họ mà hướng cần chưa được publish; không bao giờ được ghép tạm một cái thay thế."
|
|
83
|
+
},
|
|
84
|
+
"resume": {
|
|
85
|
+
"en": "A person publishes the component, and the same direction runs again.",
|
|
86
|
+
"vi": "Người publish component đó, rồi chính hướng ấy chạy lại."
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"REFERENCE_EVIDENCE_EXHAUSTED": {
|
|
90
|
+
"domain": "caller",
|
|
91
|
+
"disposition": "terminate",
|
|
92
|
+
"meaning": {
|
|
93
|
+
"en": "Bounded research cannot close the business or interaction question the decision rests on.",
|
|
94
|
+
"vi": "Nghiên cứu có giới hạn không lấp được câu hỏi nghiệp vụ hay tương tác mà quyết định dựa vào."
|
|
95
|
+
},
|
|
96
|
+
"resume": {
|
|
97
|
+
"en": "Supply the owning authority or a materially new reference.",
|
|
98
|
+
"vi": "Cấp thẩm quyền có chủ hoặc một tham chiếu mới về bản chất."
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"NO_VIABLE_DIRECTION": {
|
|
102
|
+
"domain": "caller",
|
|
103
|
+
"disposition": "terminate",
|
|
104
|
+
"meaning": {
|
|
105
|
+
"en": "Every candidate contradicts authority or fails a mandatory attack.",
|
|
106
|
+
"vi": "Mọi phương án đều chỏi thẩm quyền hoặc chết dưới một đòn tấn công bắt buộc."
|
|
107
|
+
},
|
|
108
|
+
"resume": {
|
|
109
|
+
"en": "Change the authority or the constraints; cosmetic variants are not a delta.",
|
|
110
|
+
"vi": "Đổi thẩm quyền hoặc ràng buộc; biến thể bề ngoài không phải delta."
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"DIRECTION_CHOICE_REQUIRED": {
|
|
114
|
+
"domain": "caller",
|
|
115
|
+
"disposition": "fallback",
|
|
116
|
+
"meaning": {
|
|
117
|
+
"en": "Several candidates survive falsification and none dominates.",
|
|
118
|
+
"vi": "Nhiều phương án cùng sống sót qua phản chứng và không cái nào trội."
|
|
119
|
+
},
|
|
120
|
+
"fallback": {
|
|
121
|
+
"en": "Select the candidate that survived the most falsification attacks; on a tie, the one that introduces the fewest new nodes; record the table under ## Decision.",
|
|
122
|
+
"vi": "Chọn phương án sống sót qua nhiều đòn phản chứng nhất; hòa thì chọn phương án thêm ít node mới nhất; ghi bảng vào mục ## Decision."
|
|
123
|
+
},
|
|
124
|
+
"unless": {
|
|
125
|
+
"param": "selectionPolicy",
|
|
126
|
+
"equals": "approval-required",
|
|
127
|
+
"then": "terminate"
|
|
128
|
+
},
|
|
129
|
+
"resume": {
|
|
130
|
+
"en": "The person supplies approval naming one candidate.",
|
|
131
|
+
"vi": "Người nhập approval gọi tên một phương án."
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 9,
|
|
3
|
+
"id": "frontend.direction.decide",
|
|
4
|
+
"domain": "frontend",
|
|
5
|
+
"job": "Decide one evidence-backed, implementation-ready frontend direction for one authorized target, and prove it against the business promise, the published Grammar, the observed implementation and a falsification pass that no candidate survives by taste.",
|
|
6
|
+
"package": "operator.md",
|
|
7
|
+
"errors": "errors.json",
|
|
8
|
+
"validator": "validate.mjs",
|
|
9
|
+
"selfTest": "self-test.mjs",
|
|
10
|
+
"resources": {
|
|
11
|
+
"profile": "sol-fresh",
|
|
12
|
+
"grammarBound": true,
|
|
13
|
+
"tools": {
|
|
14
|
+
"@tools/fileread": "context-aliases",
|
|
15
|
+
"@tools/git": "read",
|
|
16
|
+
"@tools/websearch": "bounded",
|
|
17
|
+
"@tools/imagegen": "judged",
|
|
18
|
+
"@tools/visualize": "html"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|