gcf-aif-ext 0.2.7 → 0.4.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/README.md +54 -10
- package/commands/gcf.js +452 -30
- package/extension.json +22 -5
- package/hooks/pre-commit.js +69 -41
- package/injections/commit-status.md +7 -4
- package/injections/plan-context.md +8 -4
- package/injections/review-pillars.md +4 -3
- package/lib/anchors.js +60 -35
- package/lib/audit-core.js +172 -55
- package/lib/bundle.js +278 -0
- package/lib/context.js +25 -23
- package/lib/design-check.js +631 -0
- package/lib/design.js +179 -0
- package/lib/gcf-paths.js +13 -2
- package/lib/git.js +63 -0
- package/lib/id.js +7 -15
- package/lib/inbox.js +54 -0
- package/lib/index-gen.js +62 -13
- package/lib/ledger.js +94 -0
- package/lib/linter.js +17 -5
- package/lib/live.js +179 -0
- package/lib/migrate.js +345 -0
- package/lib/plan-check.js +31 -0
- package/lib/playtest-list.js +9 -5
- package/lib/systems-doc.js +85 -0
- package/lib/transitions.js +36 -21
- package/lib/unit-ops.js +297 -0
- package/lib/validate-item.js +244 -0
- package/lib/verdict-fs.js +112 -165
- package/lib/work-ops.js +727 -0
- package/package.json +1 -1
- package/profiles/game.md +68 -0
- package/profiles/glossary.md +37 -0
- package/profiles/pillars.md +3 -2
- package/profiles/system.md +1 -1
- package/profiles/unit-constraint.md +52 -0
- package/profiles/unit-entity.md +48 -0
- package/profiles/unit-mechanic.md +111 -0
- package/profiles/unit-resource.md +91 -0
- package/profiles/unit-rule.md +52 -0
- package/schemas/item.schema.json +105 -0
- package/skills/gcf-adopt/SKILL.md +3 -3
- package/skills/gcf-audit/SKILL.md +7 -6
- package/skills/gcf-card/SKILL.md +31 -17
- package/skills/gcf-debate/SKILL.md +17 -14
- package/skills/gcf-ingest/SKILL.md +39 -23
- package/skills/gcf-init/SKILL.md +5 -5
- package/skills/gcf-triage/SKILL.md +35 -0
- package/skills/gcf-verdict/SKILL.md +19 -15
- package/skills/gcf-vision/SKILL.md +17 -11
- package/templates/PILLARS.md +2 -0
- package/templates/backlog.md +2 -5
- package/templates/cnlp.config.json +0 -1
- package/templates/config.yml +7 -0
- package/templates/design.md +59 -0
- package/templates/game.md +24 -0
- package/templates/glossary.md +11 -0
- package/templates/item.md +58 -0
- package/templates/system.md +1 -1
- package/lib/validate-card.js +0 -82
- package/profiles/card.md +0 -65
- package/schemas/card.schema.json +0 -30
- package/templates/card.md +0 -34
package/templates/system.md
CHANGED
package/lib/validate-card.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
// Runtime mirror of schemas/card.schema.json for the pre-commit hook (no ajv in
|
|
2
|
-
// production deps). The parity test keeps the two in agreement.
|
|
3
|
-
const FIELDS = [
|
|
4
|
-
'schema',
|
|
5
|
-
'id',
|
|
6
|
-
'slug',
|
|
7
|
-
'status',
|
|
8
|
-
'route',
|
|
9
|
-
'system',
|
|
10
|
-
'depends',
|
|
11
|
-
'source',
|
|
12
|
-
'tune_count',
|
|
13
|
-
'built_at',
|
|
14
|
-
'created',
|
|
15
|
-
];
|
|
16
|
-
const REQUIRED = FIELDS.filter((f) => f !== 'built_at');
|
|
17
|
-
|
|
18
|
-
const RULES = {
|
|
19
|
-
schema: (v) => v === 1 || 'schema must be 1',
|
|
20
|
-
id: (v) => /^card-\d{3}$/.test(v) || 'id must match card-NNN',
|
|
21
|
-
slug: (v) => /^[a-z0-9]+(-[a-z0-9]+)*$/.test(v) || 'slug must be a lowercase hyphen slug',
|
|
22
|
-
status: (v) =>
|
|
23
|
-
['proposed', 'built', 'tuning'].includes(v) ||
|
|
24
|
-
`status "${v}" is not storable (П1: terminal statuses never live in a file)`,
|
|
25
|
-
route: (v) => ['soft', 'hard'].includes(v) || 'route must be soft or hard',
|
|
26
|
-
system: (v) =>
|
|
27
|
-
(Array.isArray(v) && v.length >= 1 && v.every((s) => /^[a-z0-9]+(-[a-z0-9]+)*$/.test(s))) ||
|
|
28
|
-
'system must list >=1 subsystem slugs',
|
|
29
|
-
depends: (v) =>
|
|
30
|
-
(Array.isArray(v) && v.every((d) => /^card-\d{3}$/.test(d))) ||
|
|
31
|
-
'depends must list card-NNN ids',
|
|
32
|
-
source: (v) =>
|
|
33
|
-
/^(GDD#[A-Za-z0-9_-]+|manual|inferred)$/.test(v) ||
|
|
34
|
-
'source must be GDD#<id>, manual or inferred',
|
|
35
|
-
tune_count: (v) => (Number.isInteger(v) && v >= 0) || 'tune_count must be an integer >= 0',
|
|
36
|
-
built_at: (v) =>
|
|
37
|
-
v === null ||
|
|
38
|
-
v === undefined ||
|
|
39
|
-
/^[0-9a-f]{7,40}$/.test(v) ||
|
|
40
|
-
'built_at must be null or a commit hash',
|
|
41
|
-
created: (v) => /^\d{4}-\d{2}-\d{2}$/.test(dateStr(v)) || 'created must be YYYY-MM-DD',
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const dateStr = (v) => (v instanceof Date ? v.toISOString().slice(0, 10) : String(v));
|
|
45
|
-
|
|
46
|
-
const UNTIL_OK = /^\[until:\s*(verdict\(card-\d{3}\)|retune\([a-z0-9-]+\)|manual\([^)]*\))\]$/;
|
|
47
|
-
|
|
48
|
-
/** Validate card frontmatter. Returns a list of one-line errors (empty = valid). */
|
|
49
|
-
export function validateCard(data) {
|
|
50
|
-
const errors = [];
|
|
51
|
-
for (const key of REQUIRED) if (!(key in data)) errors.push(`missing field: ${key}`);
|
|
52
|
-
for (const key of Object.keys(data)) {
|
|
53
|
-
if (!FIELDS.includes(key))
|
|
54
|
-
errors.push(
|
|
55
|
-
`unknown field: ${key}` +
|
|
56
|
-
(key === 'until' ? ' (until: is a line annotation, not frontmatter)' : ''),
|
|
57
|
-
);
|
|
58
|
-
else if (key in RULES) {
|
|
59
|
-
const res = RULES[key](data[key]);
|
|
60
|
-
if (res !== true) errors.push(res);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return errors;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** Validate every `[until: ...]` annotation in a body against the trigger grammar (§7.3). */
|
|
68
|
-
export function validateUntil(body) {
|
|
69
|
-
const errors = [];
|
|
70
|
-
const lines = String(body).split('\n');
|
|
71
|
-
lines.forEach((line, i) => {
|
|
72
|
-
for (const m of line.matchAll(/\[until:[^\]]*\]/g)) {
|
|
73
|
-
if (!UNTIL_OK.test(m[0]))
|
|
74
|
-
errors.push(
|
|
75
|
-
`line ${i + 1}: bad until annotation ${m[0]} ` +
|
|
76
|
-
'(use verdict(card-NNN), retune(system) or manual(text))',
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
return errors;
|
|
82
|
-
}
|
package/profiles/card.md
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: card
|
|
3
|
-
description: The CNL-P profile of a GCF feature card — the six slots a card body carries, in order.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
format: cnlp-format.md
|
|
7
|
-
|
|
8
|
-
mood: declarative
|
|
9
|
-
|
|
10
|
-
headings:
|
|
11
|
-
- none: the body is flat and the document is named by its frontmatter or its fixed path
|
|
12
|
-
|
|
13
|
-
frontmatter_fields:
|
|
14
|
-
- schema
|
|
15
|
-
- id
|
|
16
|
-
- slug
|
|
17
|
-
- status
|
|
18
|
-
- route
|
|
19
|
-
- system
|
|
20
|
-
- depends
|
|
21
|
-
- source
|
|
22
|
-
- tune_count
|
|
23
|
-
- built_at
|
|
24
|
-
- created
|
|
25
|
-
|
|
26
|
-
lexicon_exempt:
|
|
27
|
-
- none: every field of a card body is read at planning time and must stay unambiguous
|
|
28
|
-
|
|
29
|
-
sections:
|
|
30
|
-
- key: behavior
|
|
31
|
-
form: bullet-list
|
|
32
|
-
required: yes
|
|
33
|
-
note: player input -> state change -> feedback, one observable statement per line
|
|
34
|
-
|
|
35
|
-
- key: contract
|
|
36
|
-
form: bullet-list
|
|
37
|
-
required: yes
|
|
38
|
-
note: entities, components and data flows the feature adds; paths and entry points, never member lists or values
|
|
39
|
-
|
|
40
|
-
- key: feel
|
|
41
|
-
form: bullet-list
|
|
42
|
-
required: yes
|
|
43
|
-
note: a comparison line (like X, not like Y) plus envelope lines; envelopes are the only legal numbers in gcf documents
|
|
44
|
-
|
|
45
|
-
- key: interactions
|
|
46
|
-
form: bullet-list
|
|
47
|
-
required: yes
|
|
48
|
-
note: existing mechanics this feature crosses; a soft line may end with an "[until: ...]" annotation
|
|
49
|
-
|
|
50
|
-
- key: constraints
|
|
51
|
-
form: bullet-list
|
|
52
|
-
required: yes
|
|
53
|
-
note: negative constraints, one prohibition per line, checkable by an analyzer or a reviewer
|
|
54
|
-
|
|
55
|
-
- key: miss_criterion
|
|
56
|
-
form: scalar
|
|
57
|
-
required: yes
|
|
58
|
-
note: the one question the game in hand answers; the human answers it at the verdict
|
|
59
|
-
|
|
60
|
-
custom_sections:
|
|
61
|
-
- none: a card block that is not listed above is prose looking for a home
|
|
62
|
-
|
|
63
|
-
enforcement:
|
|
64
|
-
- `npx cnlp check`, over the files a `cnlp.config.json` corpus entry maps to this profile
|
|
65
|
-
- frontmatter is validated separately by `schemas/card.schema.json` in the gcf pre-commit hook
|
package/schemas/card.schema.json
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"$id": "https://github.com/VirtualMaestro/GCF/schemas/card.schema.json",
|
|
4
|
-
"title": "GCF card frontmatter",
|
|
5
|
-
"type": "object",
|
|
6
|
-
"additionalProperties": false,
|
|
7
|
-
"required": ["schema", "id", "slug", "status", "route", "system", "depends", "source", "tune_count", "created"],
|
|
8
|
-
"properties": {
|
|
9
|
-
"schema": { "const": 1 },
|
|
10
|
-
"id": { "type": "string", "pattern": "^card-\\d{3}$" },
|
|
11
|
-
"slug": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
|
|
12
|
-
"status": { "enum": ["proposed", "built", "tuning"] },
|
|
13
|
-
"route": { "enum": ["soft", "hard"] },
|
|
14
|
-
"system": {
|
|
15
|
-
"type": "array",
|
|
16
|
-
"minItems": 1,
|
|
17
|
-
"items": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" }
|
|
18
|
-
},
|
|
19
|
-
"depends": {
|
|
20
|
-
"type": "array",
|
|
21
|
-
"items": { "type": "string", "pattern": "^card-\\d{3}$" }
|
|
22
|
-
},
|
|
23
|
-
"source": { "type": "string", "pattern": "^(GDD#[A-Za-z0-9_-]+|manual|inferred)$" },
|
|
24
|
-
"tune_count": { "type": "integer", "minimum": 0 },
|
|
25
|
-
"built_at": {
|
|
26
|
-
"anyOf": [{ "type": "null" }, { "type": "string", "pattern": "^[0-9a-f]{7,40}$" }]
|
|
27
|
-
},
|
|
28
|
-
"created": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" }
|
|
29
|
-
}
|
|
30
|
-
}
|
package/templates/card.md
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
schema: 1
|
|
3
|
-
id: card-000
|
|
4
|
-
slug: example
|
|
5
|
-
status: proposed
|
|
6
|
-
route: soft
|
|
7
|
-
system: [example-system]
|
|
8
|
-
depends: []
|
|
9
|
-
source: manual
|
|
10
|
-
tune_count: 0
|
|
11
|
-
built_at: null
|
|
12
|
-
created: "2026-01-01"
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
behavior:
|
|
16
|
-
- player presses X -> the character does Y -> the screen shows Z
|
|
17
|
-
|
|
18
|
-
contract:
|
|
19
|
-
- new components and systems live under Assets/Scripts/Example/
|
|
20
|
-
- data flows from input to simulation, never backwards
|
|
21
|
-
|
|
22
|
-
feel:
|
|
23
|
-
- like Hades, not like Celeste
|
|
24
|
-
- duration 0.15..0.25 s
|
|
25
|
-
- cooldown 0.4..0.8 s
|
|
26
|
-
|
|
27
|
-
interactions:
|
|
28
|
-
- none: this example crosses no existing mechanic
|
|
29
|
-
|
|
30
|
-
constraints:
|
|
31
|
-
- do not add a new input binding
|
|
32
|
-
- no per-frame allocations
|
|
33
|
-
|
|
34
|
-
miss_criterion: does the move feel responsive on the first try
|