sinapse-ai 7.7.3 → 7.7.4
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/.codex/catalog.json +157 -0
- package/.codex/command-registry.json +441 -0
- package/.codex/scripts/generate-codex-greeting.js +101 -0
- package/.codex/scripts/resolve-codex-command.js +147 -0
- package/.codex/skills/sinapse-analyst/SKILL.md +5 -4
- package/.codex/skills/sinapse-architect/SKILL.md +5 -4
- package/.codex/skills/sinapse-data-engineer/SKILL.md +5 -4
- package/.codex/skills/sinapse-dev/SKILL.md +5 -4
- package/.codex/skills/sinapse-devops/SKILL.md +5 -4
- package/.codex/skills/sinapse-orqx/SKILL.md +10 -15
- package/.codex/skills/sinapse-pm/SKILL.md +5 -4
- package/.codex/skills/sinapse-po/SKILL.md +4 -3
- package/.codex/skills/sinapse-qa/SKILL.md +12 -11
- package/.codex/skills/sinapse-sm/SKILL.md +5 -4
- package/.codex/skills/sinapse-squad-creator/SKILL.md +5 -4
- package/.codex/skills/sinapse-ux-design-expert/SKILL.md +5 -4
- package/.codex/tasks/convene-sinapse-council.md +28 -0
- package/.codex/tasks/create-sinapse-strategic-brief.md +29 -0
- package/.codex/tasks/onboard-sinapse-codex.md +34 -0
- package/.codex/tasks/plan-sinapse-initiative.md +33 -0
- package/.codex/tasks/resolve-sinapse-conflict.md +28 -0
- package/.codex/tasks/route-sinapse-request.md +33 -0
- package/.codex/tasks/status-sinapse-capabilities.md +28 -0
- package/.sinapse-ai/core-config.yaml +1 -1
- package/.sinapse-ai/data/entity-registry.yaml +848 -751
- package/.sinapse-ai/data/registry-update-log.jsonl +10 -0
- package/.sinapse-ai/infrastructure/scripts/codex-parity/catalog.js +123 -0
- package/.sinapse-ai/infrastructure/scripts/codex-skills-sync/index.js +60 -11
- package/.sinapse-ai/infrastructure/scripts/codex-skills-sync/validate.js +44 -16
- package/.sinapse-ai/infrastructure/scripts/sync-codex-local-first.js +156 -0
- package/.sinapse-ai/infrastructure/scripts/validate-codex-command-registry.js +264 -0
- package/.sinapse-ai/infrastructure/scripts/validate-codex-integration.js +15 -6
- package/.sinapse-ai/infrastructure/scripts/validate-codex-sync.js +156 -0
- package/.sinapse-ai/infrastructure/scripts/validate-parity.js +3 -1
- package/.sinapse-ai/infrastructure/scripts/validate-paths.js +8 -10
- package/.sinapse-ai/infrastructure/templates/safe-collab/README.md +8 -0
- package/.sinapse-ai/install-manifest.yaml +35 -19
- package/.sinapse-ai/project-config.yaml +1 -1
- package/bin/utils/collab-start.js +267 -0
- package/bin/utils/git-branch-guard.js +76 -0
- package/bin/utils/pre-push-safety.js +110 -0
- package/bin/utils/staged-secret-scan.js +108 -0
- package/docs/codex-parity-program.md +670 -0
- package/docs/codex-total-parity-orchestration-plan.md +301 -0
- package/docs/codex-workflow-task-parity.md +87 -0
- package/docs/collaboration-autonomy-plan.md +243 -0
- package/docs/guides/framework-contributor-mode.md +310 -0
- package/docs/guides/parallel-collaboration-source-of-truth.md +481 -0
- package/package.json +11 -3
- package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +2 -2
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const REQUIRED_COMMAND_COVERAGE = Object.freeze({
|
|
8
|
+
'sinapse-orqx': ['onboard', 'route', 'plan', 'status', 'brief', 'resolve', 'council'],
|
|
9
|
+
'sinapse-pm': [
|
|
10
|
+
'create-prd',
|
|
11
|
+
'create-brownfield-prd',
|
|
12
|
+
'create-epic',
|
|
13
|
+
'create-story',
|
|
14
|
+
'research',
|
|
15
|
+
'execute-epic',
|
|
16
|
+
'gather-requirements',
|
|
17
|
+
'write-spec',
|
|
18
|
+
'shard-prd',
|
|
19
|
+
],
|
|
20
|
+
'sinapse-po': [
|
|
21
|
+
'validate-story',
|
|
22
|
+
'validate-story-draft',
|
|
23
|
+
'backlog-review',
|
|
24
|
+
'backlog-prioritize',
|
|
25
|
+
'backlog-schedule',
|
|
26
|
+
'close-story',
|
|
27
|
+
'sync-story',
|
|
28
|
+
'pull-story',
|
|
29
|
+
'stories-index',
|
|
30
|
+
],
|
|
31
|
+
'sinapse-sm': ['draft', 'story-checklist'],
|
|
32
|
+
'sinapse-dev': [
|
|
33
|
+
'develop',
|
|
34
|
+
'run-tests',
|
|
35
|
+
'apply-qa-fixes',
|
|
36
|
+
'execute-subtask',
|
|
37
|
+
'verify-subtask',
|
|
38
|
+
'build-autonomous',
|
|
39
|
+
'build-resume',
|
|
40
|
+
'build-status',
|
|
41
|
+
'build',
|
|
42
|
+
],
|
|
43
|
+
'sinapse-qa': [
|
|
44
|
+
'review',
|
|
45
|
+
'review-story',
|
|
46
|
+
'code-review',
|
|
47
|
+
'gate',
|
|
48
|
+
'review-build',
|
|
49
|
+
'create-fix-request',
|
|
50
|
+
'test-design',
|
|
51
|
+
'generate-tests',
|
|
52
|
+
'run-tests',
|
|
53
|
+
'nfr-assess',
|
|
54
|
+
'validate-libraries',
|
|
55
|
+
'security-check',
|
|
56
|
+
'validate-migrations',
|
|
57
|
+
'evidence-check',
|
|
58
|
+
'false-positive-check',
|
|
59
|
+
'console-check',
|
|
60
|
+
],
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
function parseArgs(argv = process.argv.slice(2)) {
|
|
64
|
+
const args = new Set(argv);
|
|
65
|
+
return {
|
|
66
|
+
quiet: args.has('--quiet') || args.has('-q'),
|
|
67
|
+
json: args.has('--json'),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function normalizeAgentAlias(value) {
|
|
72
|
+
return String(value || '').trim().replace(/^@/, '').toLowerCase();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function normalizeCommandAlias(value) {
|
|
76
|
+
return String(value || '').trim().replace(/^\*/, '').toLowerCase();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function collectAgentAliases(agentId, agentSpec) {
|
|
80
|
+
return [agentId, ...(agentSpec.aliases || [])]
|
|
81
|
+
.map((alias) => normalizeAgentAlias(alias))
|
|
82
|
+
.filter(Boolean);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function collectCommandAliases(commandId, commandSpec) {
|
|
86
|
+
return [commandId, ...(commandSpec.aliases || [])]
|
|
87
|
+
.map((alias) => normalizeCommandAlias(alias))
|
|
88
|
+
.filter(Boolean);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function loadRegistry(projectRoot) {
|
|
92
|
+
const registryPath = path.join(projectRoot, '.codex', 'command-registry.json');
|
|
93
|
+
if (!fs.existsSync(registryPath)) {
|
|
94
|
+
return {
|
|
95
|
+
registryPath,
|
|
96
|
+
registry: null,
|
|
97
|
+
error: `Missing Codex command registry: ${path.relative(projectRoot, registryPath)}`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
return {
|
|
103
|
+
registryPath,
|
|
104
|
+
registry: JSON.parse(fs.readFileSync(registryPath, 'utf8')),
|
|
105
|
+
error: null,
|
|
106
|
+
};
|
|
107
|
+
} catch (error) {
|
|
108
|
+
return {
|
|
109
|
+
registryPath,
|
|
110
|
+
registry: null,
|
|
111
|
+
error: `Unable to parse Codex command registry: ${error.message}`,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function validateRequiredCoverage(registry, requiredCoverage, errors) {
|
|
117
|
+
for (const [agentId, requiredCommands] of Object.entries(requiredCoverage || {})) {
|
|
118
|
+
const agentSpec = (registry.agents || {})[agentId];
|
|
119
|
+
if (!agentSpec) {
|
|
120
|
+
errors.push(`missing required agent coverage: ${agentId}`);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const availableCommands = new Set();
|
|
125
|
+
for (const [commandId, commandSpec] of Object.entries(agentSpec.commands || {})) {
|
|
126
|
+
for (const alias of collectCommandAliases(commandId, commandSpec)) {
|
|
127
|
+
availableCommands.add(alias);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (const requiredCommand of requiredCommands) {
|
|
132
|
+
if (!availableCommands.has(normalizeCommandAlias(requiredCommand))) {
|
|
133
|
+
errors.push(`${agentId}: missing required command coverage for ${requiredCommand}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function validateCodexCommandRegistry(options = {}) {
|
|
140
|
+
const projectRoot = options.projectRoot || process.cwd();
|
|
141
|
+
const { registryPath, registry, error } = loadRegistry(projectRoot);
|
|
142
|
+
const errors = [];
|
|
143
|
+
const requiredCoverage =
|
|
144
|
+
options.requiredCoverage === false
|
|
145
|
+
? null
|
|
146
|
+
: options.requiredCoverage || REQUIRED_COMMAND_COVERAGE;
|
|
147
|
+
|
|
148
|
+
if (error) {
|
|
149
|
+
errors.push(error);
|
|
150
|
+
return {
|
|
151
|
+
ok: false,
|
|
152
|
+
errors,
|
|
153
|
+
warnings: [],
|
|
154
|
+
metrics: { agents: 0, commands: 0 },
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let commandCount = 0;
|
|
159
|
+
const seenAgentAliases = new Map();
|
|
160
|
+
for (const [agentId, agentSpec] of Object.entries(registry.agents || {})) {
|
|
161
|
+
const skillPath = path.join(projectRoot, '.codex', 'skills', agentSpec.skillId || agentId, 'SKILL.md');
|
|
162
|
+
if (!fs.existsSync(skillPath)) {
|
|
163
|
+
errors.push(`${agentId}: missing skill file ${path.relative(projectRoot, skillPath)}`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const sourceOfTruth = path.join(projectRoot, agentSpec.sourceOfTruth || '');
|
|
167
|
+
if (!fs.existsSync(sourceOfTruth)) {
|
|
168
|
+
errors.push(`${agentId}: missing source of truth ${path.relative(projectRoot, sourceOfTruth)}`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
for (const alias of collectAgentAliases(agentId, agentSpec)) {
|
|
172
|
+
const owner = seenAgentAliases.get(alias);
|
|
173
|
+
if (owner && owner !== agentId) {
|
|
174
|
+
errors.push(`duplicate agent alias "${alias}" claimed by ${owner} and ${agentId}`);
|
|
175
|
+
} else {
|
|
176
|
+
seenAgentAliases.set(alias, agentId);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const seenCommandAliases = new Map();
|
|
181
|
+
for (const [commandId, commandSpec] of Object.entries(agentSpec.commands || {})) {
|
|
182
|
+
commandCount += 1;
|
|
183
|
+
|
|
184
|
+
const targetPath = path.join(projectRoot, commandSpec.target || '');
|
|
185
|
+
if (!fs.existsSync(targetPath)) {
|
|
186
|
+
errors.push(`${agentId}.${commandId}: missing target ${path.relative(projectRoot, targetPath)}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
for (const resource of commandSpec.resources || []) {
|
|
190
|
+
const resourcePath = path.join(projectRoot, resource);
|
|
191
|
+
if (!fs.existsSync(resourcePath)) {
|
|
192
|
+
errors.push(`${agentId}.${commandId}: missing resource ${path.relative(projectRoot, resourcePath)}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
for (const alias of collectCommandAliases(commandId, commandSpec)) {
|
|
197
|
+
const owner = seenCommandAliases.get(alias);
|
|
198
|
+
if (owner && owner !== commandId) {
|
|
199
|
+
errors.push(`${agentId}: duplicate command alias "${alias}" claimed by ${owner} and ${commandId}`);
|
|
200
|
+
} else {
|
|
201
|
+
seenCommandAliases.set(alias, commandId);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
validateRequiredCoverage(registry, requiredCoverage, errors);
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
ok: errors.length === 0,
|
|
211
|
+
errors,
|
|
212
|
+
warnings: [],
|
|
213
|
+
metrics: {
|
|
214
|
+
agents: Object.keys(registry.agents || {}).length,
|
|
215
|
+
commands: commandCount,
|
|
216
|
+
registryPath: path.relative(projectRoot, registryPath),
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function formatHumanReport(result) {
|
|
222
|
+
if (result.ok) {
|
|
223
|
+
return `OK Codex command registry validation passed (agents: ${result.metrics.agents}, commands: ${result.metrics.commands})`;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return [
|
|
227
|
+
`X Codex command registry validation failed (${result.errors.length} issue(s))`,
|
|
228
|
+
...result.errors.map((error) => `- ${error}`),
|
|
229
|
+
].join('\n');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function main() {
|
|
233
|
+
const args = parseArgs();
|
|
234
|
+
const result = validateCodexCommandRegistry(args);
|
|
235
|
+
|
|
236
|
+
if (!args.quiet) {
|
|
237
|
+
if (args.json) {
|
|
238
|
+
console.log(JSON.stringify(result, null, 2));
|
|
239
|
+
} else {
|
|
240
|
+
console.log(formatHumanReport(result));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (!result.ok) {
|
|
245
|
+
process.exitCode = 1;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (require.main === module) {
|
|
250
|
+
main();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
module.exports = {
|
|
254
|
+
parseArgs,
|
|
255
|
+
loadRegistry,
|
|
256
|
+
normalizeAgentAlias,
|
|
257
|
+
normalizeCommandAlias,
|
|
258
|
+
collectAgentAliases,
|
|
259
|
+
collectCommandAliases,
|
|
260
|
+
validateRequiredCoverage,
|
|
261
|
+
validateCodexCommandRegistry,
|
|
262
|
+
formatHumanReport,
|
|
263
|
+
REQUIRED_COMMAND_COVERAGE,
|
|
264
|
+
};
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
|
+
const {
|
|
7
|
+
loadCodexCatalogConfig,
|
|
8
|
+
getConfiguredSkillIds,
|
|
9
|
+
} = require('./codex-parity/catalog');
|
|
6
10
|
|
|
7
11
|
function getDefaultOptions() {
|
|
8
12
|
const projectRoot = process.cwd();
|
|
@@ -41,14 +45,15 @@ function countSkillFiles(skillsDir) {
|
|
|
41
45
|
|
|
42
46
|
function validateCodexIntegration(options = {}) {
|
|
43
47
|
const projectRoot = options.projectRoot || process.cwd();
|
|
48
|
+
const config = loadCodexCatalogConfig(projectRoot);
|
|
44
49
|
const resolved = {
|
|
45
50
|
...getDefaultOptions(),
|
|
46
51
|
...options,
|
|
47
52
|
projectRoot,
|
|
48
53
|
instructionsFile: options.instructionsFile || path.join(projectRoot, 'AGENTS.md'),
|
|
49
|
-
agentsDir: options.agentsDir || path.join(projectRoot, '.codex
|
|
50
|
-
skillsDir: options.skillsDir || path.join(projectRoot, '.codex
|
|
51
|
-
sourceAgentsDir: options.sourceAgentsDir || path.join(projectRoot, '.sinapse-ai
|
|
54
|
+
agentsDir: options.agentsDir || path.join(projectRoot, config.codexAgentsDir || '.codex/agents'),
|
|
55
|
+
skillsDir: options.skillsDir || path.join(projectRoot, config.skillsDir || '.codex/skills'),
|
|
56
|
+
sourceAgentsDir: options.sourceAgentsDir || path.join(projectRoot, config.canonicalAgentsDir || '.sinapse-ai/development/agents'),
|
|
52
57
|
};
|
|
53
58
|
const errors = [];
|
|
54
59
|
const warnings = [];
|
|
@@ -70,12 +75,15 @@ function validateCodexIntegration(options = {}) {
|
|
|
70
75
|
const sourceCount = countMarkdownFiles(resolved.sourceAgentsDir);
|
|
71
76
|
const codexAgentsCount = countMarkdownFiles(resolved.agentsDir);
|
|
72
77
|
const codexSkillsCount = countSkillFiles(resolved.skillsDir);
|
|
78
|
+
const expectedSkillIds = getConfiguredSkillIds(config);
|
|
73
79
|
|
|
74
|
-
if (sourceCount > 0 && codexAgentsCount !== sourceCount) {
|
|
80
|
+
if (config.catalogMode !== 'expanded' && sourceCount > 0 && codexAgentsCount !== sourceCount) {
|
|
75
81
|
warnings.push(`Codex agent count differs from source (${codexAgentsCount}/${sourceCount})`);
|
|
76
82
|
}
|
|
77
83
|
|
|
78
|
-
if (
|
|
84
|
+
if (expectedSkillIds && codexSkillsCount !== expectedSkillIds.length) {
|
|
85
|
+
warnings.push(`Codex skill count differs from configured catalog (${codexSkillsCount}/${expectedSkillIds.length})`);
|
|
86
|
+
} else if (!expectedSkillIds && sourceCount > 0 && codexSkillsCount !== sourceCount) {
|
|
79
87
|
warnings.push(`Codex skill count differs from source (${codexSkillsCount}/${sourceCount})`);
|
|
80
88
|
}
|
|
81
89
|
|
|
@@ -84,9 +92,10 @@ function validateCodexIntegration(options = {}) {
|
|
|
84
92
|
errors,
|
|
85
93
|
warnings,
|
|
86
94
|
metrics: {
|
|
87
|
-
|
|
95
|
+
canonicalAgents: sourceCount,
|
|
88
96
|
codexAgents: codexAgentsCount,
|
|
89
97
|
codexSkills: codexSkillsCount,
|
|
98
|
+
expectedSkills: expectedSkillIds ? expectedSkillIds.length : sourceCount,
|
|
90
99
|
},
|
|
91
100
|
};
|
|
92
101
|
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { spawnSync } = require('child_process');
|
|
7
|
+
const { loadCodexCatalogConfig } = require('./codex-parity/catalog');
|
|
8
|
+
const { validateCodexCommandRegistry } = require('./validate-codex-command-registry');
|
|
9
|
+
const { validateCodexIntegration } = require('./validate-codex-integration');
|
|
10
|
+
const { validateCodexSkills } = require('./codex-skills-sync/validate');
|
|
11
|
+
const { validatePaths } = require('./validate-paths');
|
|
12
|
+
|
|
13
|
+
function parseArgs(argv = process.argv.slice(2)) {
|
|
14
|
+
const args = new Set(argv);
|
|
15
|
+
return {
|
|
16
|
+
quiet: args.has('--quiet') || args.has('-q'),
|
|
17
|
+
json: args.has('--json'),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function runLegacyCodexValidate(projectRoot, options = {}) {
|
|
22
|
+
const args = [
|
|
23
|
+
path.join('.sinapse-ai', 'infrastructure', 'scripts', 'ide-sync', 'index.js'),
|
|
24
|
+
'validate',
|
|
25
|
+
'--ide',
|
|
26
|
+
'codex',
|
|
27
|
+
'--strict',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
if (options.quiet) args.push('--quiet');
|
|
31
|
+
|
|
32
|
+
const result = spawnSync(process.execPath, args, {
|
|
33
|
+
cwd: projectRoot,
|
|
34
|
+
encoding: 'utf8',
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
ok: result.status === 0,
|
|
39
|
+
mode: 'canonical',
|
|
40
|
+
checks: [],
|
|
41
|
+
errors: result.status === 0 ? [] : ['Legacy Codex sync validation failed'],
|
|
42
|
+
warnings: [],
|
|
43
|
+
raw: [result.stdout, result.stderr].filter(Boolean).join('\n').trim(),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function normalizeCheck(id, input) {
|
|
48
|
+
return {
|
|
49
|
+
id,
|
|
50
|
+
ok: Boolean(input?.ok),
|
|
51
|
+
errors: Array.isArray(input?.errors) ? input.errors : [],
|
|
52
|
+
warnings: Array.isArray(input?.warnings) ? input.warnings : [],
|
|
53
|
+
metrics: input?.metrics || {},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function validateCodexSync(options = {}, deps = {}) {
|
|
58
|
+
const projectRoot = options.projectRoot || process.cwd();
|
|
59
|
+
const config = loadCodexCatalogConfig(projectRoot);
|
|
60
|
+
const runLegacyValidate = deps.runLegacyCodexValidate || runLegacyCodexValidate;
|
|
61
|
+
const runCodexCommands = deps.validateCodexCommandRegistry || validateCodexCommandRegistry;
|
|
62
|
+
const runCodexIntegration = deps.validateCodexIntegration || validateCodexIntegration;
|
|
63
|
+
const runCodexSkills = deps.validateCodexSkills || validateCodexSkills;
|
|
64
|
+
const runPaths = deps.validatePaths || validatePaths;
|
|
65
|
+
|
|
66
|
+
if (config.catalogMode !== 'expanded') {
|
|
67
|
+
return runLegacyValidate(projectRoot, options);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const catalogPath = path.join(projectRoot, '.codex', 'catalog.json');
|
|
71
|
+
const checks = [
|
|
72
|
+
normalizeCheck('codex-integration', runCodexIntegration({ projectRoot, quiet: true })),
|
|
73
|
+
normalizeCheck('codex-commands', runCodexCommands({ projectRoot, quiet: true })),
|
|
74
|
+
normalizeCheck('codex-skills', runCodexSkills({ projectRoot, strict: true, quiet: true })),
|
|
75
|
+
normalizeCheck('paths', runPaths({ projectRoot, quiet: true })),
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
if (!fs.existsSync(catalogPath)) {
|
|
79
|
+
checks.unshift({
|
|
80
|
+
id: 'codex-catalog',
|
|
81
|
+
ok: false,
|
|
82
|
+
errors: ['Missing Codex catalog file: .codex/catalog.json'],
|
|
83
|
+
warnings: [],
|
|
84
|
+
metrics: {},
|
|
85
|
+
});
|
|
86
|
+
} else {
|
|
87
|
+
checks.unshift({
|
|
88
|
+
id: 'codex-catalog',
|
|
89
|
+
ok: true,
|
|
90
|
+
errors: [],
|
|
91
|
+
warnings: [],
|
|
92
|
+
metrics: {},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
ok: checks.every((check) => check.ok),
|
|
98
|
+
mode: 'expanded',
|
|
99
|
+
checks,
|
|
100
|
+
errors: checks.flatMap((check) => check.errors.map((error) => `${check.id}: ${error}`)),
|
|
101
|
+
warnings: checks.flatMap((check) => check.warnings.map((warning) => `${check.id}: ${warning}`)),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function formatHumanReport(result) {
|
|
106
|
+
if (result.mode === 'canonical' && result.raw) {
|
|
107
|
+
return result.raw;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const lines = [
|
|
111
|
+
result.ok
|
|
112
|
+
? 'OK Codex sync validation passed'
|
|
113
|
+
: `X Codex sync validation failed (${result.errors.length} issue(s))`,
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
for (const check of result.checks || []) {
|
|
117
|
+
lines.push(`${check.ok ? 'OK' : 'X'} ${check.id}`);
|
|
118
|
+
if (check.errors.length > 0) {
|
|
119
|
+
lines.push(...check.errors.map((error) => `- ${error}`));
|
|
120
|
+
}
|
|
121
|
+
if (check.warnings.length > 0) {
|
|
122
|
+
lines.push(...check.warnings.map((warning) => `! ${warning}`));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return lines.join('\n');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function main() {
|
|
130
|
+
const args = parseArgs();
|
|
131
|
+
const result = validateCodexSync(args);
|
|
132
|
+
|
|
133
|
+
if (!args.quiet) {
|
|
134
|
+
if (args.json) {
|
|
135
|
+
console.log(JSON.stringify(result, null, 2));
|
|
136
|
+
} else {
|
|
137
|
+
console.log(formatHumanReport(result));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!result.ok) {
|
|
142
|
+
process.exitCode = 1;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (require.main === module) {
|
|
147
|
+
main();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
module.exports = {
|
|
151
|
+
parseArgs,
|
|
152
|
+
validateCodexSync,
|
|
153
|
+
formatHumanReport,
|
|
154
|
+
runLegacyCodexValidate,
|
|
155
|
+
normalizeCheck,
|
|
156
|
+
};
|
|
@@ -6,6 +6,7 @@ const path = require('path');
|
|
|
6
6
|
const yaml = require('js-yaml');
|
|
7
7
|
const { spawnSync } = require('child_process');
|
|
8
8
|
const { validateClaudeIntegration } = require('./validate-claude-integration');
|
|
9
|
+
const { validateCodexSync } = require('./validate-codex-sync');
|
|
9
10
|
const { validateCodexIntegration } = require('./validate-codex-integration');
|
|
10
11
|
const { validateCodexSkills } = require('./codex-skills-sync/validate');
|
|
11
12
|
const { validatePaths } = require('./validate-paths');
|
|
@@ -218,6 +219,7 @@ function diffCompatibilityContracts(currentContract, previousContract) {
|
|
|
218
219
|
function runParityValidation(options = {}, deps = {}) {
|
|
219
220
|
const projectRoot = options.projectRoot || process.cwd();
|
|
220
221
|
const runSync = deps.runSyncValidate || runSyncValidate;
|
|
222
|
+
const runCodexSync = deps.validateCodexSync || validateCodexSync;
|
|
221
223
|
const runClaudeIntegration = deps.validateClaudeIntegration || validateClaudeIntegration;
|
|
222
224
|
const runCodexIntegration = deps.validateCodexIntegration || validateCodexIntegration;
|
|
223
225
|
const runCodexSkills = deps.validateCodexSkills || validateCodexSkills;
|
|
@@ -234,7 +236,7 @@ function runParityValidation(options = {}, deps = {}) {
|
|
|
234
236
|
const checks = [
|
|
235
237
|
{ id: 'claude-sync', exec: () => runSync('claude-code', projectRoot) },
|
|
236
238
|
{ id: 'claude-integration', exec: () => runClaudeIntegration({ projectRoot }) },
|
|
237
|
-
{ id: 'codex-sync', exec: () =>
|
|
239
|
+
{ id: 'codex-sync', exec: () => runCodexSync({ projectRoot, quiet: true }) },
|
|
238
240
|
{ id: 'codex-integration', exec: () => runCodexIntegration({ projectRoot }) },
|
|
239
241
|
{ id: 'codex-skills', exec: () => runCodexSkills({ projectRoot, strict: true, quiet: true }) },
|
|
240
242
|
{ id: 'paths', exec: () => runPaths({ projectRoot }) },
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
|
+
const {
|
|
7
|
+
loadCodexCatalogConfig,
|
|
8
|
+
validateSkillActivationPaths,
|
|
9
|
+
} = require('./codex-parity/catalog');
|
|
6
10
|
|
|
7
11
|
const FORBIDDEN_ABSOLUTE_PATTERNS = [
|
|
8
12
|
/\/Users\/[^\s/'"]+/g,
|
|
@@ -54,21 +58,15 @@ function collectAbsolutePathViolations(content, filePath) {
|
|
|
54
58
|
return errors;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
function validateSkillPathConventions(content, filePath) {
|
|
58
|
-
|
|
59
|
-
if (!content.includes('.sinapse-ai/development/agents/')) {
|
|
60
|
-
errors.push(`${filePath} missing canonical source path ".sinapse-ai/development/agents/"`);
|
|
61
|
-
}
|
|
62
|
-
if (!content.includes('.sinapse-ai/development/scripts/generate-greeting.js')) {
|
|
63
|
-
errors.push(`${filePath} missing canonical greeting script path`);
|
|
64
|
-
}
|
|
65
|
-
return errors;
|
|
61
|
+
function validateSkillPathConventions(content, filePath, config) {
|
|
62
|
+
return validateSkillActivationPaths(content, filePath, config);
|
|
66
63
|
}
|
|
67
64
|
|
|
68
65
|
function validatePaths(options = {}) {
|
|
69
66
|
const resolved = { ...getDefaultOptions(), ...options };
|
|
70
67
|
const errors = [];
|
|
71
68
|
const checkedFiles = [];
|
|
69
|
+
const config = loadCodexCatalogConfig(resolved.projectRoot);
|
|
72
70
|
|
|
73
71
|
const skillFiles = listSkillFiles(resolved.skillsDir);
|
|
74
72
|
const filesToCheck = [...resolved.requiredFiles, ...skillFiles];
|
|
@@ -90,7 +88,7 @@ function validatePaths(options = {}) {
|
|
|
90
88
|
errors.push(...collectAbsolutePathViolations(content, path.relative(resolved.projectRoot, file)));
|
|
91
89
|
|
|
92
90
|
if (file.endsWith('SKILL.md')) {
|
|
93
|
-
errors.push(...validateSkillPathConventions(content, path.relative(resolved.projectRoot, file)));
|
|
91
|
+
errors.push(...validateSkillPathConventions(content, path.relative(resolved.projectRoot, file), config));
|
|
94
92
|
}
|
|
95
93
|
}
|
|
96
94
|
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Template reutilizavel para configurar colaboracao segura em qualquer projeto.
|
|
4
4
|
|
|
5
|
+
## Fonte canonica
|
|
6
|
+
|
|
7
|
+
Para a politica completa e atualizada de colaboracao paralela, use:
|
|
8
|
+
|
|
9
|
+
- `docs/guides/parallel-collaboration-source-of-truth.md`
|
|
10
|
+
|
|
11
|
+
Este README explica o template. O documento acima define a regra mestra.
|
|
12
|
+
|
|
5
13
|
## Uso rapido
|
|
6
14
|
|
|
7
15
|
```bash
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
# - SHA256 hashes for change detection
|
|
8
8
|
# - File types for categorization
|
|
9
9
|
#
|
|
10
|
-
version: 7.7.
|
|
11
|
-
generated_at: "2026-04-
|
|
10
|
+
version: 7.7.4
|
|
11
|
+
generated_at: "2026-04-03T00:06:05.314Z"
|
|
12
12
|
generator: scripts/generate-install-manifest.js
|
|
13
|
-
file_count:
|
|
13
|
+
file_count: 1117
|
|
14
14
|
files:
|
|
15
15
|
- path: cli/commands/config/index.js
|
|
16
16
|
hash: sha256:66f111eceef0f60fa0a8904add783b615d55b01d5fe36408623c3dd828e702f6
|
|
@@ -189,9 +189,9 @@ files:
|
|
|
189
189
|
type: cli
|
|
190
190
|
size: 5907
|
|
191
191
|
- path: core-config.yaml
|
|
192
|
-
hash: sha256:
|
|
192
|
+
hash: sha256:fc24a8286b20ec2558c90186e99124b96d26b287ff107b747c2b68b1102e0cc8
|
|
193
193
|
type: config
|
|
194
|
-
size:
|
|
194
|
+
size: 10513
|
|
195
195
|
- path: core/code-intel/code-intel-client.js
|
|
196
196
|
hash: sha256:6c9a08a37775acf90397aa079a4ad2c5edcc47f2cfd592b26ae9f3d154d1deb8
|
|
197
197
|
type: core
|
|
@@ -1237,9 +1237,9 @@ files:
|
|
|
1237
1237
|
type: data
|
|
1238
1238
|
size: 9586
|
|
1239
1239
|
- path: data/entity-registry.yaml
|
|
1240
|
-
hash: sha256:
|
|
1240
|
+
hash: sha256:265b44f0e9c36e85375f05ba88dbf19ed9033244a6eea338f4b8e3a4e453dd12
|
|
1241
1241
|
type: data
|
|
1242
|
-
size:
|
|
1242
|
+
size: 514885
|
|
1243
1243
|
- path: data/learned-patterns.yaml
|
|
1244
1244
|
hash: sha256:24ac0b160615583a0ff783d3da8af80b7f94191575d6db2054ec8e10a3f945dc
|
|
1245
1245
|
type: data
|
|
@@ -3052,14 +3052,18 @@ files:
|
|
|
3052
3052
|
hash: sha256:47b3f9044ce9b92b8c486a75da82afc4cc6b49d5d97e722ef5a1938fbf49943a
|
|
3053
3053
|
type: script
|
|
3054
3054
|
size: 40744
|
|
3055
|
+
- path: infrastructure/scripts/codex-parity/catalog.js
|
|
3056
|
+
hash: sha256:cfef97860788a119c44cbb18b4249ad538814f99a03b2ca13e66dd74aa8b5242
|
|
3057
|
+
type: script
|
|
3058
|
+
size: 3527
|
|
3055
3059
|
- path: infrastructure/scripts/codex-skills-sync/index.js
|
|
3056
|
-
hash: sha256:
|
|
3060
|
+
hash: sha256:9eb2637a4f1f6edeabf358734b14e4c709bed37560f2e40aebf1ea3ef4572c3c
|
|
3057
3061
|
type: script
|
|
3058
|
-
size:
|
|
3062
|
+
size: 7494
|
|
3059
3063
|
- path: infrastructure/scripts/codex-skills-sync/validate.js
|
|
3060
|
-
hash: sha256:
|
|
3064
|
+
hash: sha256:1a1301d2e3f558bedf3a1ab2c5c9ee2868a4c253068311d5014987917f367443
|
|
3061
3065
|
type: script
|
|
3062
|
-
size:
|
|
3066
|
+
size: 5626
|
|
3063
3067
|
- path: infrastructure/scripts/collect-tool-usage.js
|
|
3064
3068
|
hash: sha256:510b621078602273fb146eef57d115b08988ea43d03eb5d92192050c13e95efe
|
|
3065
3069
|
type: script
|
|
@@ -3372,6 +3376,10 @@ files:
|
|
|
3372
3376
|
hash: sha256:ceb0450fa12fa48f0255bb4565858eb1a97b28c30b98d36cb61d52d72e08b054
|
|
3373
3377
|
type: script
|
|
3374
3378
|
size: 22394
|
|
3379
|
+
- path: infrastructure/scripts/sync-codex-local-first.js
|
|
3380
|
+
hash: sha256:ad5245ead7243a39cd5116f44fcf1234ad54b016e365dfefa017764a76f4f3eb
|
|
3381
|
+
type: script
|
|
3382
|
+
size: 4089
|
|
3375
3383
|
- path: infrastructure/scripts/template-engine.js
|
|
3376
3384
|
hash: sha256:de1bc8ce51eeabf6f6ec558d35107fbc4843ac76e3361044ba9f47bb6af4f058
|
|
3377
3385
|
type: script
|
|
@@ -3420,22 +3428,30 @@ files:
|
|
|
3420
3428
|
hash: sha256:4447fbf8cffdf20b34fad71eb4caf5aec0726f2b8f27cd49cd1bd59d69cdc009
|
|
3421
3429
|
type: script
|
|
3422
3430
|
size: 2838
|
|
3431
|
+
- path: infrastructure/scripts/validate-codex-command-registry.js
|
|
3432
|
+
hash: sha256:a37a4c5fc8a4c3a7ce7ba240aeea16abc0a75871751f66eeb84991604ff066bf
|
|
3433
|
+
type: script
|
|
3434
|
+
size: 7266
|
|
3423
3435
|
- path: infrastructure/scripts/validate-codex-integration.js
|
|
3424
|
-
hash: sha256:
|
|
3436
|
+
hash: sha256:c553cc493ddbfecf41b865f8a1075df56b6500c3b2b315bae8b7e7bcec4db85a
|
|
3425
3437
|
type: script
|
|
3426
|
-
size:
|
|
3438
|
+
size: 4742
|
|
3439
|
+
- path: infrastructure/scripts/validate-codex-sync.js
|
|
3440
|
+
hash: sha256:f7f2963f995df0dc1fc0a4662146318aa4dba2699c8dbfc4fa748b3201b1db56
|
|
3441
|
+
type: script
|
|
3442
|
+
size: 4427
|
|
3427
3443
|
- path: infrastructure/scripts/validate-output-pattern.js
|
|
3428
3444
|
hash: sha256:91111d656e8d7b38a20a1bda753e663b74318f75cdab2025c7e0b84c775fc83d
|
|
3429
3445
|
type: script
|
|
3430
3446
|
size: 6692
|
|
3431
3447
|
- path: infrastructure/scripts/validate-parity.js
|
|
3432
|
-
hash: sha256:
|
|
3448
|
+
hash: sha256:284c7715cc65b76579284024bbe5176b9230340d841dbfe79559c8f5844109cb
|
|
3433
3449
|
type: script
|
|
3434
|
-
size:
|
|
3450
|
+
size: 12266
|
|
3435
3451
|
- path: infrastructure/scripts/validate-paths.js
|
|
3436
|
-
hash: sha256:
|
|
3452
|
+
hash: sha256:942f6de9e621b7331f61dc915db5d24b987b67d1ae3377882330f7013dd214e9
|
|
3437
3453
|
type: script
|
|
3438
|
-
size:
|
|
3454
|
+
size: 3671
|
|
3439
3455
|
- path: infrastructure/scripts/validate-user-profile.js
|
|
3440
3456
|
hash: sha256:0f78a5aebd85b4b0d2a5b0f2d81ccbbbe0f2d25ed1cfcafeb129734852217683
|
|
3441
3457
|
type: script
|
|
@@ -3525,9 +3541,9 @@ files:
|
|
|
3525
3541
|
type: template
|
|
3526
3542
|
size: 338
|
|
3527
3543
|
- path: infrastructure/templates/safe-collab/README.md
|
|
3528
|
-
hash: sha256:
|
|
3544
|
+
hash: sha256:0b4f3d0ce9b7111d812917312ae504df976245d902eecfa501f73e7aa0719813
|
|
3529
3545
|
type: template
|
|
3530
|
-
size:
|
|
3546
|
+
size: 2179
|
|
3531
3547
|
- path: infrastructure/templates/safe-collab/safe-collaboration-rule.md
|
|
3532
3548
|
hash: sha256:9631681340fddc314080f9182b76ccfbb1ee3441d92ce181067e76cace960a5e
|
|
3533
3549
|
type: template
|