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.
Files changed (63) hide show
  1. package/README.md +54 -10
  2. package/commands/gcf.js +452 -30
  3. package/extension.json +22 -5
  4. package/hooks/pre-commit.js +69 -41
  5. package/injections/commit-status.md +7 -4
  6. package/injections/plan-context.md +8 -4
  7. package/injections/review-pillars.md +4 -3
  8. package/lib/anchors.js +60 -35
  9. package/lib/audit-core.js +172 -55
  10. package/lib/bundle.js +278 -0
  11. package/lib/context.js +25 -23
  12. package/lib/design-check.js +631 -0
  13. package/lib/design.js +179 -0
  14. package/lib/gcf-paths.js +13 -2
  15. package/lib/git.js +63 -0
  16. package/lib/id.js +7 -15
  17. package/lib/inbox.js +54 -0
  18. package/lib/index-gen.js +62 -13
  19. package/lib/ledger.js +94 -0
  20. package/lib/linter.js +17 -5
  21. package/lib/live.js +179 -0
  22. package/lib/migrate.js +345 -0
  23. package/lib/plan-check.js +31 -0
  24. package/lib/playtest-list.js +9 -5
  25. package/lib/systems-doc.js +85 -0
  26. package/lib/transitions.js +36 -21
  27. package/lib/unit-ops.js +297 -0
  28. package/lib/validate-item.js +244 -0
  29. package/lib/verdict-fs.js +112 -165
  30. package/lib/work-ops.js +727 -0
  31. package/package.json +1 -1
  32. package/profiles/game.md +68 -0
  33. package/profiles/glossary.md +37 -0
  34. package/profiles/pillars.md +3 -2
  35. package/profiles/system.md +1 -1
  36. package/profiles/unit-constraint.md +52 -0
  37. package/profiles/unit-entity.md +48 -0
  38. package/profiles/unit-mechanic.md +111 -0
  39. package/profiles/unit-resource.md +91 -0
  40. package/profiles/unit-rule.md +52 -0
  41. package/schemas/item.schema.json +105 -0
  42. package/skills/gcf-adopt/SKILL.md +3 -3
  43. package/skills/gcf-audit/SKILL.md +7 -6
  44. package/skills/gcf-card/SKILL.md +31 -17
  45. package/skills/gcf-debate/SKILL.md +17 -14
  46. package/skills/gcf-ingest/SKILL.md +39 -23
  47. package/skills/gcf-init/SKILL.md +5 -5
  48. package/skills/gcf-triage/SKILL.md +35 -0
  49. package/skills/gcf-verdict/SKILL.md +19 -15
  50. package/skills/gcf-vision/SKILL.md +17 -11
  51. package/templates/PILLARS.md +2 -0
  52. package/templates/backlog.md +2 -5
  53. package/templates/cnlp.config.json +0 -1
  54. package/templates/config.yml +7 -0
  55. package/templates/design.md +59 -0
  56. package/templates/game.md +24 -0
  57. package/templates/glossary.md +11 -0
  58. package/templates/item.md +58 -0
  59. package/templates/system.md +1 -1
  60. package/lib/validate-card.js +0 -82
  61. package/profiles/card.md +0 -65
  62. package/schemas/card.schema.json +0 -30
  63. package/templates/card.md +0 -34
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  system: example-system
3
- updated_by: card-000
3
+ updated_by: example
4
4
  ---
5
5
 
6
6
  purpose:
@@ -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
@@ -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