sinapse-ai 1.6.1 → 1.8.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 (131) hide show
  1. package/.claude/CLAUDE.md +5 -11
  2. package/.claude/hooks/README.md +14 -1
  3. package/.claude/hooks/code-intel-pretool.cjs +115 -0
  4. package/.claude/hooks/enforce-delegation.cjs +31 -3
  5. package/.claude/hooks/enforce-framework-boundary.cjs +324 -0
  6. package/.claude/hooks/enforce-permission-mode.cjs +249 -0
  7. package/.claude/hooks/secret-scanning.cjs +34 -43
  8. package/.claude/hooks/synapse-engine.cjs +23 -23
  9. package/.claude/hooks/telemetry-post-tool.cjs +128 -0
  10. package/.claude/hooks/telemetry-stop.cjs +132 -0
  11. package/.claude/hooks/verify-packages.cjs +9 -2
  12. package/.claude/rules/documentation-first.md +1 -1
  13. package/.claude/rules/hook-governance.md +2 -0
  14. package/.sinapse-ai/cli/commands/health/index.js +24 -0
  15. package/.sinapse-ai/core/README.md +11 -0
  16. package/.sinapse-ai/core/config/config-loader.js +19 -0
  17. package/.sinapse-ai/core/config/merge-utils.js +8 -0
  18. package/.sinapse-ai/core/errors/constants.js +147 -0
  19. package/.sinapse-ai/core/errors/error-registry.js +176 -0
  20. package/.sinapse-ai/core/errors/index.js +50 -0
  21. package/.sinapse-ai/core/errors/serializer.js +147 -0
  22. package/.sinapse-ai/core/errors/sinapse-error.js +144 -0
  23. package/.sinapse-ai/core/errors/utils.js +187 -0
  24. package/.sinapse-ai/core/execution/build-orchestrator.js +47 -49
  25. package/.sinapse-ai/core/execution/build-state-manager.js +183 -31
  26. package/.sinapse-ai/core/execution/parallel-executor.js +7 -1
  27. package/.sinapse-ai/core/execution/semantic-merge-engine.js +26 -14
  28. package/.sinapse-ai/core/execution/subagent-dispatcher.js +201 -60
  29. package/.sinapse-ai/core/execution/wave-executor.js +4 -1
  30. package/.sinapse-ai/core/grounding/README.md +71 -11
  31. package/.sinapse-ai/core/health-check/checks/project/framework-config.js +38 -2
  32. package/.sinapse-ai/core/health-check/checks/project/package-json.js +47 -3
  33. package/.sinapse-ai/core/health-check/checks/services/gemini-cli.js +117 -0
  34. package/.sinapse-ai/core/health-check/checks/services/index.js +2 -0
  35. package/.sinapse-ai/core/health-check/healers/index.js +40 -3
  36. package/.sinapse-ai/core/ideation/ideation-engine.js +212 -107
  37. package/.sinapse-ai/core/ids/gate-evaluator.js +318 -0
  38. package/.sinapse-ai/core/ids/gates/g5-semantic-handshake.js +190 -0
  39. package/.sinapse-ai/core/ids/gates/g6-ci-integrity.js +162 -0
  40. package/.sinapse-ai/core/ids/index.js +30 -0
  41. package/.sinapse-ai/core/memory/__tests__/active-modules.verify.js +11 -0
  42. package/.sinapse-ai/core/memory/gotchas-memory.js +37 -2
  43. package/.sinapse-ai/core/orchestration/agent-invoker.js +29 -6
  44. package/.sinapse-ai/core/orchestration/brownfield-handler.js +36 -3
  45. package/.sinapse-ai/core/orchestration/condition-evaluator.js +57 -0
  46. package/.sinapse-ai/core/orchestration/executors/epic-3-executor.js +76 -5
  47. package/.sinapse-ai/core/orchestration/executors/epic-4-executor.js +63 -17
  48. package/.sinapse-ai/core/orchestration/executors/epic-6-executor.js +153 -41
  49. package/.sinapse-ai/core/orchestration/executors/epic-executor.js +40 -0
  50. package/.sinapse-ai/core/orchestration/greenfield-handler.js +87 -3
  51. package/.sinapse-ai/core/orchestration/master-orchestrator.js +150 -10
  52. package/.sinapse-ai/core/orchestration/parallel-executor.js +6 -1
  53. package/.sinapse-ai/core/orchestration/recovery-handler.js +81 -8
  54. package/.sinapse-ai/core/orchestration/workflow-executor.js +41 -0
  55. package/.sinapse-ai/core/registry/registry-loader.js +71 -5
  56. package/.sinapse-ai/core/registry/squad-agent-resolver.js +253 -0
  57. package/.sinapse-ai/core/synapse/context/context-tracker.js +104 -9
  58. package/.sinapse-ai/core/synapse/context/index.js +19 -0
  59. package/.sinapse-ai/core/synapse/context/semantic-handshake-engine.js +555 -0
  60. package/.sinapse-ai/core/synapse/diagnostics/collectors/pipeline-collector.js +4 -2
  61. package/.sinapse-ai/core/synapse/engine.js +43 -3
  62. package/.sinapse-ai/core/telemetry/ids-sink.js +188 -0
  63. package/.sinapse-ai/core/utils/output-formatter.js +8 -290
  64. package/.sinapse-ai/core/utils/spawn-safe.js +186 -0
  65. package/.sinapse-ai/core-config.yaml +68 -1
  66. package/.sinapse-ai/data/entity-registry.yaml +15082 -13618
  67. package/.sinapse-ai/data/registry-update-log.jsonl +143 -0
  68. package/.sinapse-ai/development/agents/developer.md +2 -0
  69. package/.sinapse-ai/development/agents/devops.md +9 -0
  70. package/.sinapse-ai/development/external-executors/README.md +18 -0
  71. package/.sinapse-ai/development/external-executors/codex.md +56 -0
  72. package/.sinapse-ai/development/scripts/populate-entity-registry.js +65 -9
  73. package/.sinapse-ai/development/scripts/squad/squad-downloader.js +169 -14
  74. package/.sinapse-ai/development/tasks/delegate-to-external-executor.md +152 -0
  75. package/.sinapse-ai/development/tasks/github-devops-pre-push-quality-gate.md +46 -29
  76. package/.sinapse-ai/development/tasks/update-sinapse.md +3 -3
  77. package/.sinapse-ai/hooks/sinapse-brand-grounding.cjs +4 -7
  78. package/.sinapse-ai/hooks/sinapse-ds-grounding.cjs +5 -8
  79. package/.sinapse-ai/hooks/sinapse-vault-grounding.cjs +6 -9
  80. package/.sinapse-ai/infrastructure/integrations/ai-providers/ai-provider-factory.js +4 -1
  81. package/.sinapse-ai/infrastructure/integrations/ai-providers/claude-provider.js +57 -55
  82. package/.sinapse-ai/infrastructure/integrations/pm-adapters/github-adapter.js +9 -7
  83. package/.sinapse-ai/infrastructure/scripts/ide-sync/gemini-commands.js +298 -0
  84. package/.sinapse-ai/infrastructure/scripts/ide-sync/index.js +127 -6
  85. package/.sinapse-ai/infrastructure/scripts/ide-sync/persona-renderer.js +97 -0
  86. package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/antigravity.js +121 -0
  87. package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/cursor.js +119 -0
  88. package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/github-copilot.js +191 -0
  89. package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/kimi.js +448 -0
  90. package/.sinapse-ai/install-manifest.yaml +218 -114
  91. package/.sinapse-ai/product/templates/engine/renderer.js +20 -1
  92. package/.sinapse-ai/scripts/pm.sh +18 -6
  93. package/bin/cli.js +17 -0
  94. package/bin/commands/agents.js +96 -0
  95. package/bin/commands/doctor.js +15 -0
  96. package/bin/commands/ideate.js +129 -0
  97. package/bin/commands/uninstall.js +40 -0
  98. package/bin/postinstall.js +50 -4
  99. package/bin/sinapse.js +146 -2
  100. package/bin/utils/secret-scanner-core.js +253 -0
  101. package/bin/utils/staged-secret-scan.js +106 -40
  102. package/docs/framework/collaboration-autonomy-plan.md +18 -18
  103. package/docs/guides/parallel-workflow.md +6 -6
  104. package/package.json +22 -5
  105. package/packages/installer/src/installer/git-hooks-installer.js +384 -0
  106. package/packages/installer/src/installer/sinapse-ai-installer.js +16 -0
  107. package/packages/installer/src/wizard/ide-config-generator.js +23 -0
  108. package/packages/installer/src/wizard/validators.js +38 -1
  109. package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +5 -1
  110. package/packages/installer/tests/unit/doctor/doctor-checks.test.js +44 -22
  111. package/packages/installer/tests/unit/git-hooks-installer.test.js +262 -0
  112. package/scripts/eval-runner.js +422 -0
  113. package/scripts/generate-install-manifest.js +13 -9
  114. package/scripts/generate-synapse-runtime.js +51 -0
  115. package/scripts/regenerate-orqx-stubs.ps1 +6 -5
  116. package/scripts/validate-all.js +1 -0
  117. package/scripts/validate-evals.js +466 -0
  118. package/scripts/validate-schemas.js +539 -0
  119. package/scripts/validate-squad-orqx.js +9 -2
  120. package/squads/claude-code-mastery/knowledge-base/memory-systems-reference.md +1 -1
  121. package/squads/squad-brand/templates/client-delivery-template.md +1 -1
  122. package/squads/squad-content/knowledge-base/social-compression-framework.md +1 -1
  123. package/squads/squad-council/knowledge-base/brand-strategy-models.md +1 -1
  124. package/.sinapse-ai/development/scripts/elicitation-engine.js +0 -385
  125. package/.sinapse-ai/development/scripts/elicitation-session-manager.js +0 -300
  126. package/.sinapse-ai/development/tasks/test-validation-task.md +0 -172
  127. package/docs/chrome-brain-upgrade-plan.md +0 -624
  128. package/docs/constitution-compliance.md +0 -87
  129. package/docs/mega-upgrade-orchestration-plan.md +0 -71
  130. package/docs/research-synthesis-for-upgrade.md +0 -511
  131. package/docs/security-audit-report.md +0 -306
@@ -0,0 +1,539 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Schema Validation GATE — Meta-validation + Kind coverage + Artifact validation
6
+ *
7
+ * Deterministic CI gate. fail-CLOSED. Three layers, all driven by the SAME
8
+ * TemplateValidator (.sinapse-ai/product/templates/engine/validator.js, v2.0.0)
9
+ * that the engine already uses at render time — this gate does NOT reimplement
10
+ * Ajv kind-aware validation, it reuses the validator's Ajv instance, custom
11
+ * formats, schema resolution, data extraction and error formatting.
12
+ *
13
+ * LAYERS:
14
+ * 1. META-VALIDATION (always runs — the value in a public CI with no artifacts):
15
+ * Discover EVERY *.schema.json in the repo (git ls-files, node_modules
16
+ * excluded) and compile each one with a fresh Ajv draft-07 instance
17
+ * (strict:false + ajv-formats + the validator's custom formats). A schema
18
+ * that does NOT compile (invalid JSON, broken $ref, invalid meta-schema)
19
+ * -> violation -> exit 1.
20
+ *
21
+ * 2. KIND COVERAGE: for the engine's known templateTypes (adr, dbdr, epic,
22
+ * pmdr, prd-v2, prd, story, task), reuse TemplateValidator.checkSchemas()
23
+ * and report found/missing. A known kind with no schema -> violation.
24
+ *
25
+ * 3. ARTIFACT VALIDATION (no-op clean when absent): kind -> glob by CONVENTION
26
+ * (story -> docs/stories/ ** / *.story.md, epic -> docs/epics/ ** / *.md,
27
+ * prd -> docs/prd/ ** / *.md). docs/stories and docs/epics are gitignored,
28
+ * so in public CI there are 0 artifacts -> reported as skipped, NOT a
29
+ * failure. When artifacts ARE present, extract data via
30
+ * TemplateValidator.extractDataFromMarkdown (or frontmatter parse) and
31
+ * validate via TemplateValidator.validate(data, kind); each error is
32
+ * reported with the instancePath that formatErrors() already produces.
33
+ * An invalid artifact -> exit 1.
34
+ *
35
+ * Why a SEPARATE Ajv for meta-validation (layer 1): the shared
36
+ * TemplateValidator.ajv has allErrors/verbose on and caches by $id; compiling
37
+ * arbitrary repo schemas (which may share or collide on $id, or be config /
38
+ * infra schemas unrelated to templates) into it would pollute that cache and
39
+ * mask the real "does this schema compile on its own?" question. Layer 1 asks
40
+ * exactly that question, in isolation, per schema.
41
+ *
42
+ * EXIT CODES:
43
+ * 0 -> everything valid (and artifacts, if any, all valid).
44
+ * 1 -> any schema fails to compile, OR a known kind has no schema, OR an
45
+ * artifact is invalid.
46
+ * 2 -> gate/internal error (cannot load the validator, git discovery fails
47
+ * with no fallback, etc).
48
+ *
49
+ * FLAGS:
50
+ * --artifacts <dir> Use <dir> as the artifact root instead of the repo root
51
+ * (used by the jest wrapper / for testing). Globs are
52
+ * resolved relative to this root.
53
+ * --quiet Suppress the per-schema OK lines; still prints the
54
+ * summary and every violation.
55
+ *
56
+ * Will be wired into package.json (NOT touched here) as:
57
+ * "validate:schemas": "node scripts/validate-schemas.js"
58
+ *
59
+ * Node puro, Windows-nativo, ZERO new dependency (ajv + ajv-formats already deps).
60
+ *
61
+ * @module scripts/validate-schemas
62
+ */
63
+
64
+ const fs = require('fs');
65
+ const path = require('path');
66
+ const { execFileSync } = require('child_process');
67
+
68
+ // ---------------------------------------------------------------------------
69
+ // Paths
70
+ // ---------------------------------------------------------------------------
71
+
72
+ const REPO_ROOT = path.resolve(__dirname, '..');
73
+ const ENGINE_DIR = path.join(REPO_ROOT, '.sinapse-ai', 'product', 'templates', 'engine');
74
+ const SCHEMAS_DIR = path.join(ENGINE_DIR, 'schemas');
75
+ const VALIDATOR_PATH = path.join(ENGINE_DIR, 'validator.js');
76
+
77
+ // Engine's known template types (mirrors the schemas the engine ships).
78
+ const KNOWN_KINDS = ['adr', 'dbdr', 'epic', 'pmdr', 'prd-v2', 'prd', 'story', 'task'];
79
+
80
+ // Artifact resolution by CONVENTION (path/filename). Frontmatter has no
81
+ // apiVersion/kind, so the kind comes from where the file lives + its suffix.
82
+ // `dir` is relative to the artifact root; `suffix` matches filename endings.
83
+ const ARTIFACT_CONVENTIONS = [
84
+ { kind: 'story', dir: path.join('docs', 'stories'), suffix: '.story.md' },
85
+ // Epic artifacts are machine docs validated against the Epic *template
86
+ // variables* schema (id ^EPIC-…$, owner, objective, stories). Use an explicit
87
+ // `.epic.md` suffix — mirroring `.story.md` — so prose planning docs
88
+ // (README.md, SESSION-HANDOFF.md, story files) under docs/epics/ are NOT
89
+ // misclassified as epic artifacts. Before this, every .md under docs/epics/
90
+ // (tracked since the epics/stories split) failed the gate.
91
+ { kind: 'epic', dir: path.join('docs', 'epics'), suffix: '.epic.md' },
92
+ { kind: 'prd', dir: path.join('docs', 'prd'), suffix: '.md' },
93
+ ];
94
+
95
+ // ---------------------------------------------------------------------------
96
+ // CLI args
97
+ // ---------------------------------------------------------------------------
98
+
99
+ function parseArgs(argv) {
100
+ const opts = { artifactsRoot: REPO_ROOT, quiet: false };
101
+ for (let i = 0; i < argv.length; i += 1) {
102
+ const a = argv[i];
103
+ if (a === '--quiet') {
104
+ opts.quiet = true;
105
+ } else if (a === '--artifacts') {
106
+ const next = argv[i + 1];
107
+ if (!next) {
108
+ process.stderr.write('[validate-schemas] --artifacts requires a directory argument.\n');
109
+ process.exit(2);
110
+ }
111
+ opts.artifactsRoot = path.resolve(next);
112
+ i += 1;
113
+ } else if (a.startsWith('--artifacts=')) {
114
+ opts.artifactsRoot = path.resolve(a.slice('--artifacts='.length));
115
+ }
116
+ }
117
+ return opts;
118
+ }
119
+
120
+ // ---------------------------------------------------------------------------
121
+ // Violation collection
122
+ // ---------------------------------------------------------------------------
123
+
124
+ /** @type {Array<{file:string, message:string}>} */
125
+ const violations = [];
126
+ function addViolation(file, message) {
127
+ violations.push({ file, message });
128
+ }
129
+
130
+ function rel(p, root = REPO_ROOT) {
131
+ return path.relative(root, p).split(path.sep).join('/') || path.basename(p);
132
+ }
133
+
134
+ // ---------------------------------------------------------------------------
135
+ // Load the engine's TemplateValidator (REUSE — do not reimplement Ajv).
136
+ // ---------------------------------------------------------------------------
137
+
138
+ let TemplateValidator;
139
+ try {
140
+ ({ TemplateValidator } = require(VALIDATOR_PATH));
141
+ if (typeof TemplateValidator !== 'function') {
142
+ throw new Error('validator.js did not export a TemplateValidator class');
143
+ }
144
+ } catch (err) {
145
+ process.stderr.write(
146
+ '[validate-schemas] FATAL: could not load TemplateValidator from\n' +
147
+ ` ${VALIDATOR_PATH}\n` +
148
+ ` reason: ${err.message}\n`,
149
+ );
150
+ process.exit(2);
151
+ }
152
+
153
+ // One shared validator instance for kind-coverage + artifact validation. It
154
+ // resolves schemas from the engine schemas dir and carries the custom formats
155
+ // (semver, slug, story-id, epic-id) the engine schemas may rely on.
156
+ const validator = new TemplateValidator({ schemasDir: SCHEMAS_DIR });
157
+
158
+ // ---------------------------------------------------------------------------
159
+ // Ajv factory for LAYER 1 meta-validation (fresh, isolated, per schema).
160
+ // Mirrors the validator's own config (strict:false, ajv-formats, custom
161
+ // formats) so "compiles in the gate" == "compiles in the engine".
162
+ // ---------------------------------------------------------------------------
163
+
164
+ // Draft-07 is the default (matches the engine's TemplateValidator and the bulk
165
+ // of the repo). But the repo is heterogeneous: a schema may legitimately declare
166
+ // a NEWER meta-schema (e.g. draft 2020-12 in .codex/*.parity.schema.json).
167
+ // Forcing such a schema through the draft-07 compiler is a FALSE failure — it is
168
+ // valid, just newer. So the meta-validator is draft-AWARE: it picks the Ajv
169
+ // build by the schema's declared `$schema`. All builds ship INSIDE the `ajv`
170
+ // package (ajv, ajv/dist/2020, ajv/dist/2019) -> ZERO new dependency.
171
+ let AjvDraft07;
172
+ let Ajv2020;
173
+ let Ajv2019;
174
+ let addFormats;
175
+ try {
176
+
177
+ AjvDraft07 = require('ajv'); // draft-07 (also draft-06/04 via addMetaSchema, default here)
178
+
179
+ addFormats = require('ajv-formats');
180
+ } catch (err) {
181
+ process.stderr.write(
182
+ `[validate-schemas] FATAL: ajv / ajv-formats not available (expected as deps): ${err.message}\n`,
183
+ );
184
+ process.exit(2);
185
+ }
186
+ try {
187
+
188
+ Ajv2020 = require('ajv/dist/2020');
189
+ } catch {
190
+ Ajv2020 = null; // graceful: a 2020-12 schema then fails with an actionable message
191
+ }
192
+ try {
193
+
194
+ Ajv2019 = require('ajv/dist/2019');
195
+ } catch {
196
+ Ajv2019 = null;
197
+ }
198
+
199
+ function registerCustomFormats(ajv) {
200
+ // Same custom formats the TemplateValidator registers — so a schema that
201
+ // uses "format": "semver" | "slug" | "story-id" | "epic-id" still compiles
202
+ // here (with strict:false an unknown format would not throw, but mirroring
203
+ // keeps the gate semantically identical to the engine).
204
+ ajv.addFormat('semver', { validate: (s) => /^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?(\+[a-zA-Z0-9.]+)?$/.test(s) });
205
+ ajv.addFormat('slug', { validate: (s) => /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(s) });
206
+ ajv.addFormat('story-id', { validate: (s) => /^\d+\.\d+$/.test(s) });
207
+ ajv.addFormat('epic-id', { validate: (s) => /^EPIC-[A-Z0-9]+$/.test(s) });
208
+ }
209
+
210
+ /** Resolve which Ajv constructor compiles a schema, from its `$schema` URI. */
211
+ function ajvCtorFor(schema) {
212
+ const meta = typeof schema.$schema === 'string' ? schema.$schema : '';
213
+ if (/2020-12/.test(meta)) return { ctor: Ajv2020, draft: 'draft 2020-12' };
214
+ if (/2019-09/.test(meta)) return { ctor: Ajv2019, draft: 'draft 2019-09' };
215
+ // draft-07 / draft-06 / draft-04 / unspecified -> default Ajv (draft-07).
216
+ return { ctor: AjvDraft07, draft: 'draft-07' };
217
+ }
218
+
219
+ function newAjvFor(schema) {
220
+ const { ctor, draft } = ajvCtorFor(schema);
221
+ if (!ctor) {
222
+ const err = new Error(
223
+ `meta-schema ${draft} requested but the matching Ajv build is unavailable in this environment`,
224
+ );
225
+ err.unsupportedDraft = true;
226
+ throw err;
227
+ }
228
+ const ajv = new ctor({ allErrors: true, strict: false, validateFormats: true });
229
+ addFormats(ajv);
230
+ registerCustomFormats(ajv);
231
+ return { ajv, draft };
232
+ }
233
+
234
+ // ---------------------------------------------------------------------------
235
+ // Schema discovery — git ls-files (preferred), recursive readdir (fallback).
236
+ // The dot-prefixed dirs (.sinapse-ai, .codex) break a naive Glob, so we either
237
+ // ask git or walk the tree ourselves. node_modules is always excluded.
238
+ // ---------------------------------------------------------------------------
239
+
240
+ function discoverViaGit() {
241
+ try {
242
+ const out = execFileSync('git', ['ls-files', '*.schema.json'], {
243
+ cwd: REPO_ROOT,
244
+ encoding: 'utf8',
245
+ stdio: ['ignore', 'pipe', 'ignore'],
246
+ });
247
+ const files = out
248
+ .split('\n')
249
+ .map((l) => l.trim())
250
+ .filter(Boolean)
251
+ .filter((l) => !l.split('/').includes('node_modules'))
252
+ .map((l) => path.join(REPO_ROOT, l));
253
+ return files.length ? files : null;
254
+ } catch {
255
+ return null;
256
+ }
257
+ }
258
+
259
+ function discoverViaWalk(dir, acc) {
260
+ let entries;
261
+ try {
262
+ entries = fs.readdirSync(dir, { withFileTypes: true });
263
+ } catch {
264
+ return acc;
265
+ }
266
+ for (const e of entries) {
267
+ if (e.name === 'node_modules' || e.name === '.git') continue;
268
+ const full = path.join(dir, e.name);
269
+ if (e.isDirectory()) {
270
+ discoverViaWalk(full, acc);
271
+ } else if (e.isFile() && e.name.endsWith('.schema.json')) {
272
+ acc.push(full);
273
+ }
274
+ }
275
+ return acc;
276
+ }
277
+
278
+ function discoverSchemas() {
279
+ const viaGit = discoverViaGit();
280
+ if (viaGit) return { files: viaGit.sort(), method: 'git ls-files' };
281
+ const walked = discoverViaWalk(REPO_ROOT, []);
282
+ return { files: walked.sort(), method: 'recursive readdir' };
283
+ }
284
+
285
+ // ---------------------------------------------------------------------------
286
+ // LAYER 1 — meta-validation: each schema compiles in isolation.
287
+ // ---------------------------------------------------------------------------
288
+
289
+ function metaValidate(schemaFiles, opts) {
290
+ let okCount = 0;
291
+ for (const file of schemaFiles) {
292
+ const relPath = rel(file);
293
+ let raw;
294
+ try {
295
+ raw = fs.readFileSync(file, 'utf8');
296
+ } catch (err) {
297
+ addViolation(relPath, `cannot read schema file: ${err.message}`);
298
+ continue;
299
+ }
300
+ let schema;
301
+ try {
302
+ schema = JSON.parse(raw);
303
+ } catch (err) {
304
+ addViolation(relPath, `invalid JSON: ${err.message}`);
305
+ continue;
306
+ }
307
+ // Fresh Ajv per schema -> no $id cache collisions across the repo's
308
+ // template / config / infra / quality / codex schemas. Draft-aware so a
309
+ // schema that declares a newer meta-schema is not a false failure.
310
+ try {
311
+ const { ajv, draft } = newAjvFor(schema);
312
+ ajv.compile(schema); // throws on broken $ref, invalid meta-schema, bad keywords
313
+ okCount += 1;
314
+ if (!opts.quiet) process.stdout.write(` ok ${relPath} (${draft})\n`);
315
+ } catch (err) {
316
+ addViolation(relPath, `does not compile: ${err.message}`);
317
+ }
318
+ }
319
+ return okCount;
320
+ }
321
+
322
+ // ---------------------------------------------------------------------------
323
+ // LAYER 2 — kind coverage via the validator's own checkSchemas().
324
+ // ---------------------------------------------------------------------------
325
+
326
+ async function kindCoverage() {
327
+ const result = await validator.checkSchemas(KNOWN_KINDS);
328
+ for (const missing of result.missing) {
329
+ addViolation(
330
+ rel(SCHEMAS_DIR),
331
+ `known template kind '${missing}' has no schema (expected ${missing}.schema.json in ${rel(SCHEMAS_DIR)}/).`,
332
+ );
333
+ }
334
+ return result; // { complete, found, missing }
335
+ }
336
+
337
+ // ---------------------------------------------------------------------------
338
+ // LAYER 3 — artifact validation by convention (no-op clean when absent).
339
+ // ---------------------------------------------------------------------------
340
+
341
+ /** Recursively collect files under `dir` ending with `suffix`. */
342
+ function collectArtifacts(dir, suffix, acc) {
343
+ let entries;
344
+ try {
345
+ entries = fs.readdirSync(dir, { withFileTypes: true });
346
+ } catch {
347
+ return acc; // dir absent -> no-op
348
+ }
349
+ for (const e of entries) {
350
+ if (e.name === 'node_modules' || e.name === '.git') continue;
351
+ const full = path.join(dir, e.name);
352
+ if (e.isDirectory()) {
353
+ collectArtifacts(full, suffix, acc);
354
+ } else if (e.isFile() && e.name.endsWith(suffix)) {
355
+ acc.push(full);
356
+ }
357
+ }
358
+ return acc;
359
+ }
360
+
361
+ /**
362
+ * Minimal YAML frontmatter parser (--- ... ---). Engine artifacts have no
363
+ * apiVersion/kind, but a story/epic/prd may carry scalar + simple list/nested
364
+ * frontmatter. We parse what we safely can; deep structures fall back to the
365
+ * markdown-body extraction the validator already provides.
366
+ */
367
+ function parseFrontmatter(content) {
368
+ const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
369
+ if (!m) return null;
370
+ const body = m[1];
371
+ const data = {};
372
+ const lines = body.split(/\r?\n/);
373
+ let pendingKey = null;
374
+ let pendingList = null;
375
+ for (const line of lines) {
376
+ if (line.trim() === '') continue;
377
+ const listItem = line.match(/^\s*-\s+(.*)$/);
378
+ if (listItem && pendingKey) {
379
+ if (!pendingList) {
380
+ pendingList = [];
381
+ data[pendingKey] = pendingList;
382
+ }
383
+ pendingList.push(coerce(listItem[1].trim()));
384
+ continue;
385
+ }
386
+ const kv = line.match(/^([A-Za-z0-9_-]+)\s*:\s*(.*)$/);
387
+ if (kv) {
388
+ pendingKey = kv[1];
389
+ pendingList = null;
390
+ const val = kv[2].trim();
391
+ if (val === '') {
392
+ // could be a list/object on following lines
393
+ data[pendingKey] = '';
394
+ } else {
395
+ data[pendingKey] = coerce(val);
396
+ }
397
+ }
398
+ }
399
+ return data;
400
+ }
401
+
402
+ function coerce(v) {
403
+ if (/^-?\d+$/.test(v)) return parseInt(v, 10);
404
+ if (/^-?\d+\.\d+$/.test(v) && !/^\d+\.\d+$/.test(v)) return parseFloat(v); // avoid eating story ids like 3.6
405
+ if (v === 'true') return true;
406
+ if (v === 'false') return false;
407
+ // strip surrounding quotes
408
+ const q = v.match(/^["'](.*)["']$/);
409
+ return q ? q[1] : v;
410
+ }
411
+
412
+ /**
413
+ * Build the data object for an artifact. Prefer the validator's own extractor
414
+ * (markdown body `**Key:** value`), merged with frontmatter (frontmatter wins
415
+ * on key collision since it is the structured source).
416
+ */
417
+ function extractArtifactData(content) {
418
+ let bodyData = {};
419
+ try {
420
+ bodyData = validator.extractDataFromMarkdown(content, {}) || {};
421
+ } catch {
422
+ bodyData = {};
423
+ }
424
+ const fm = parseFrontmatter(content) || {};
425
+ return { ...bodyData, ...fm };
426
+ }
427
+
428
+ async function validateArtifacts(opts) {
429
+ const summary = { kinds: {}, total: 0, valid: 0, invalid: 0 };
430
+
431
+ for (const conv of ARTIFACT_CONVENTIONS) {
432
+ const root = path.join(opts.artifactsRoot, conv.dir);
433
+ const files = collectArtifacts(root, conv.suffix, []);
434
+ summary.kinds[conv.kind] = files.length;
435
+ summary.total += files.length;
436
+
437
+ for (const file of files) {
438
+ const relPath = rel(file, opts.artifactsRoot);
439
+ let content;
440
+ try {
441
+ content = fs.readFileSync(file, 'utf8');
442
+ } catch (err) {
443
+ addViolation(relPath, `cannot read artifact: ${err.message}`);
444
+ summary.invalid += 1;
445
+ continue;
446
+ }
447
+ const data = extractArtifactData(content);
448
+ let result;
449
+ try {
450
+ // REUSE: kind-aware Ajv validate; errors already formatted as
451
+ // "<instancePath>: <message> (<details>)" by validator.formatErrors().
452
+ result = await validator.validate(data, conv.kind);
453
+ } catch (err) {
454
+ addViolation(relPath, `validation error for kind '${conv.kind}': ${err.message}`);
455
+ summary.invalid += 1;
456
+ continue;
457
+ }
458
+ if (result.isValid) {
459
+ summary.valid += 1;
460
+ if (!opts.quiet) process.stdout.write(` ok ${relPath} (${conv.kind})\n`);
461
+ } else {
462
+ summary.invalid += 1;
463
+ for (const e of result.errors) {
464
+ addViolation(relPath, `[${conv.kind}] ${e}`);
465
+ }
466
+ }
467
+ }
468
+ }
469
+ return summary;
470
+ }
471
+
472
+ // ---------------------------------------------------------------------------
473
+ // Main
474
+ // ---------------------------------------------------------------------------
475
+
476
+ async function main() {
477
+ const opts = parseArgs(process.argv.slice(2));
478
+
479
+ // LAYER 1 — meta-validation (always).
480
+ const { files: schemaFiles, method } = discoverSchemas();
481
+ if (schemaFiles.length === 0) {
482
+ process.stderr.write(`[validate-schemas] FATAL: no *.schema.json discovered (method: ${method}).\n`);
483
+ process.exit(2);
484
+ }
485
+ if (!opts.quiet) process.stdout.write(`[validate-schemas] meta-validating ${schemaFiles.length} schema(s) (${method}):\n`);
486
+ const compiledOk = metaValidate(schemaFiles, opts);
487
+
488
+ // LAYER 2 — kind coverage.
489
+ const coverage = await kindCoverage();
490
+
491
+ // LAYER 3 — artifacts (no-op clean when absent).
492
+ const artifacts = await validateArtifacts(opts);
493
+
494
+ // -------------------------------------------------------------------------
495
+ // Summary
496
+ // -------------------------------------------------------------------------
497
+ process.stdout.write('\n[validate-schemas] summary\n');
498
+ process.stdout.write(
499
+ ` schemas checked : ${schemaFiles.length} (${compiledOk} compiled OK, ${schemaFiles.length - compiledOk} failed)\n`,
500
+ );
501
+ process.stdout.write(
502
+ ` kinds covered : ${coverage.found.length}/${KNOWN_KINDS.length} ` +
503
+ `(found: ${coverage.found.join(', ') || 'none'}` +
504
+ `${coverage.missing.length ? ` | missing: ${coverage.missing.join(', ')}` : ''})\n`,
505
+ );
506
+ if (artifacts.total === 0) {
507
+ process.stdout.write(' artifacts : 0 artifacts found (skipped)\n');
508
+ } else {
509
+ const perKind = Object.entries(artifacts.kinds)
510
+ .map(([k, n]) => `${k}:${n}`)
511
+ .join(', ');
512
+ process.stdout.write(
513
+ ` artifacts : ${artifacts.total} validated (${artifacts.valid} valid, ${artifacts.invalid} invalid) [${perKind}]\n`,
514
+ );
515
+ }
516
+
517
+ if (violations.length === 0) {
518
+ process.stdout.write('\n[validate-schemas] OK — all schemas compile, all known kinds covered, all artifacts valid.\n');
519
+ process.exit(0);
520
+ }
521
+
522
+ process.stdout.write(`\n[validate-schemas] FAIL — ${violations.length} violation(s):\n`);
523
+ const byFile = new Map();
524
+ for (const v of violations) {
525
+ if (!byFile.has(v.file)) byFile.set(v.file, []);
526
+ byFile.get(v.file).push(v.message);
527
+ }
528
+ for (const [file, msgs] of byFile) {
529
+ process.stdout.write(`\n ${file}\n`);
530
+ for (const m of msgs) process.stdout.write(` - ${m}\n`);
531
+ }
532
+ process.stdout.write('\n');
533
+ process.exit(1);
534
+ }
535
+
536
+ main().catch((err) => {
537
+ process.stderr.write(`[validate-schemas] FATAL (uncaught): ${err && err.stack ? err.stack : err}\n`);
538
+ process.exit(2);
539
+ });
@@ -123,8 +123,14 @@ function parseOrqxFormat(content) {
123
123
  const nameMatch = content.match(/\*\*Nome:\*\*\s*([^\n]+)/);
124
124
  if (nameMatch) data.agent.name = nameMatch[1].trim();
125
125
 
126
- const roleHeadingMatch = content.match(/^##\s+Role\s*\n+([\s\S]+?)(?:\n##|\n$)/m);
126
+ // Accept "## Role" or "## Papel" (PT-BR alias)
127
+ const roleHeadingMatch = content.match(/^##\s+(?:Role|Papel)\s*\n+([\s\S]+?)(?:\n##|\n$)/m);
127
128
  if (roleHeadingMatch) data.persona.role = roleHeadingMatch[1].trim().split('\n')[0];
129
+ // Inline role in list item (e.g. "- **Role:** Product Operations Orchestrator")
130
+ if (!data.persona.role) {
131
+ const inlineRoleMatch = content.match(/\*\*(?:Role|Papel):\*\*\s*([^\n]+)/);
132
+ if (inlineRoleMatch) data.persona.role = inlineRoleMatch[1].trim();
133
+ }
128
134
 
129
135
  return data;
130
136
  }
@@ -141,7 +147,8 @@ function parseOrqxFormat(content) {
141
147
  const idMatch = content.match(/\*\*Agent ID\*\*\s*\|\s*`?@?([^|`\n]+?)`?\s*\|/);
142
148
  if (idMatch) data.agent.id = idMatch[1].trim();
143
149
 
144
- const roleHeadingMatch = content.match(/^##\s+Role\s*\n+([\s\S]+?)(?:\n##|\n$)/m);
150
+ // Accept "## Role" or "## Papel" (PT-BR alias)
151
+ const roleHeadingMatch = content.match(/^##\s+(?:Role|Papel)\s*\n+([\s\S]+?)(?:\n##|\n$)/m);
145
152
  if (roleHeadingMatch) data.persona.role = roleHeadingMatch[1].trim().split('\n')[0];
146
153
 
147
154
  return data;
@@ -339,7 +339,7 @@ class AgentMemory:
339
339
  ```python
340
340
  # Track how facts change over time
341
341
  fact = KnowledgeFact(
342
- content="User works at Astro Brand Studio",
342
+ content="User works at Acme Corp",
343
343
  valid_from="2025-01",
344
344
  valid_to=None, # Still valid
345
345
  ingested_at="2025-01-15",
@@ -5,7 +5,7 @@
5
5
  ---
6
6
 
7
7
  ## Slide 1: Capa
8
- {Logo do projeto + "Entrega {N}: {phase_name}" + data + Astro Brand Studio logo}
8
+ {Logo do projeto + "Entrega {N}: {phase_name}" + data + {{your_brand}} logo}
9
9
 
10
10
  ## Slide 2: Agenda
11
11
  {Lista dos topicos que serao apresentados nesta entrega}
@@ -1,6 +1,6 @@
1
1
  # Social Compression Framework — Compressao de Tese Densa em Conteudo Social-Native
2
2
 
3
- > Fonte: Inteligencia extraida do posicionamento de Matheus Soier — embalagem social-native e retencao.
3
+ > Fonte: padrões de posicionamento de alta densidade — embalagem social-native e retencao.
4
4
 
5
5
  ## Principio Central
6
6
 
@@ -173,7 +173,7 @@ Frameworks para construcao, gestao e posicionamento de marca. Da identidade ao v
173
173
  - **Network Effect**: Conecte pessoas de forma generosa — voce se torna o hub de conexoes
174
174
 
175
175
  **Ferramentas**: LinkedIn (B2B), Twitter/X (tech/thought leadership), YouTube (profundidade), Substack/Newsletter (ownership), Podcast (intimidade)
176
- - **Example Application**: Caio Imori (contexto Astro Brand Studio): Specific Knowledge = intersection de IA + branding + storytelling. Public: publicar casos de uso, frameworks proprios, resultados dos clientes. Leverage: SINAPSE como produto que escala o conhecimento.
176
+ - **Example Application**: a solo founder (boutique brand studio context): Specific Knowledge = intersection de IA + branding + storytelling. Public: publicar casos de uso, frameworks proprios, resultados dos clientes. Leverage: SINAPSE como produto que escala o conhecimento.
177
177
  - **Key Metrics**: Inbound leads via personal brand; speaking invites; colaboracoes inbound; preco hora premium vs. mercado
178
178
  - **Cross-References**: Productize Yourself (Naval), Golden Circle (Sinek), Specific Knowledge Audit
179
179