sinapse-ai 7.7.3 → 7.7.5
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/delegation-matrix.json +512 -0
- package/.codex/handoff-packet.schema.json +148 -0
- package/.codex/scripts/generate-codex-greeting.js +101 -0
- package/.codex/scripts/resolve-codex-command.js +147 -0
- package/.codex/scripts/resolve-codex-delegation.js +205 -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 +35 -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 +874 -749
- package/.sinapse-ai/data/registry-update-log.jsonl +13 -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-delegation.js +292 -0
- package/.sinapse-ai/infrastructure/scripts/validate-codex-integration.js +15 -6
- package/.sinapse-ai/infrastructure/scripts/validate-codex-sync.js +159 -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 +39 -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 +14 -3
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +7 -2
- package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +2 -2
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
|
|
5
|
+
function execGit(command, options = {}) {
|
|
6
|
+
return execSync(command, {
|
|
7
|
+
encoding: 'utf8',
|
|
8
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
9
|
+
...options,
|
|
10
|
+
}).trim();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function resolveDefaultBranch() {
|
|
14
|
+
try {
|
|
15
|
+
const remoteHead = execGit('git symbolic-ref --short refs/remotes/origin/HEAD');
|
|
16
|
+
return remoteHead.replace(/^origin\//, '');
|
|
17
|
+
} catch {
|
|
18
|
+
return 'main';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getCurrentBranch() {
|
|
23
|
+
return execGit('git rev-parse --abbrev-ref HEAD');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getStagedFiles() {
|
|
27
|
+
try {
|
|
28
|
+
const output = execGit('git diff --cached --name-only');
|
|
29
|
+
return output ? output.split('\n').filter(Boolean) : [];
|
|
30
|
+
} catch {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function shouldBlockCommit({ branchName, defaultBranch, stagedFiles }) {
|
|
36
|
+
const protectedBranches = new Set([defaultBranch, 'master']);
|
|
37
|
+
return Boolean(stagedFiles.length) && (protectedBranches.has(branchName) || branchName === 'HEAD');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function main() {
|
|
41
|
+
const defaultBranch = resolveDefaultBranch();
|
|
42
|
+
const branchName = getCurrentBranch();
|
|
43
|
+
const stagedFiles = getStagedFiles();
|
|
44
|
+
|
|
45
|
+
if (!shouldBlockCommit({ branchName, defaultBranch, stagedFiles })) {
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.error('');
|
|
50
|
+
console.error('Git Branch Guard: commit blocked.');
|
|
51
|
+
console.error('');
|
|
52
|
+
if (branchName === 'HEAD') {
|
|
53
|
+
console.error('You are in detached HEAD state. Create an isolated branch or worktree first.');
|
|
54
|
+
} else {
|
|
55
|
+
console.error(`Commits are blocked on the protected branch '${branchName}'.`);
|
|
56
|
+
}
|
|
57
|
+
console.error('');
|
|
58
|
+
console.error('Start a safe maintainer workspace first:');
|
|
59
|
+
console.error(' npm run collab:start -- <story-id> <slug>');
|
|
60
|
+
console.error('');
|
|
61
|
+
console.error('Example:');
|
|
62
|
+
console.error(' npm run collab:start -- 7.7.4 codex-collab-hardening');
|
|
63
|
+
console.error('');
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
getCurrentBranch,
|
|
69
|
+
getStagedFiles,
|
|
70
|
+
resolveDefaultBranch,
|
|
71
|
+
shouldBlockCommit,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
if (require.main === module) {
|
|
75
|
+
main();
|
|
76
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { execFileSync, execSync, spawnSync } = require('child_process');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
|
|
6
|
+
function execGit(command) {
|
|
7
|
+
return execSync(command, {
|
|
8
|
+
encoding: 'utf8',
|
|
9
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
10
|
+
}).trim();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function resolveDefaultBranch() {
|
|
14
|
+
try {
|
|
15
|
+
const remoteHead = execGit('git symbolic-ref --short refs/remotes/origin/HEAD');
|
|
16
|
+
return remoteHead.replace(/^origin\//, '');
|
|
17
|
+
} catch {
|
|
18
|
+
return 'main';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getCurrentBranch() {
|
|
23
|
+
return execGit('git rev-parse --abbrev-ref HEAD');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function parsePushRefs(stdinBuffer) {
|
|
27
|
+
const payload = stdinBuffer.toString('utf8').trim();
|
|
28
|
+
if (!payload) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return payload
|
|
33
|
+
.split('\n')
|
|
34
|
+
.filter(Boolean)
|
|
35
|
+
.map((line) => {
|
|
36
|
+
const [localRef, localSha, remoteRef, remoteSha] = line.trim().split(/\s+/);
|
|
37
|
+
return { localRef, localSha, remoteRef, remoteSha };
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isProtectedPushTarget(remoteRef, defaultBranch) {
|
|
42
|
+
return remoteRef === `refs/heads/${defaultBranch}` || remoteRef === 'refs/heads/master';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function branchContainsRemoteDefault(defaultBranch) {
|
|
46
|
+
const result = spawnSync('git', ['merge-base', '--is-ancestor', `origin/${defaultBranch}`, 'HEAD'], {
|
|
47
|
+
stdio: 'ignore',
|
|
48
|
+
});
|
|
49
|
+
return result.status === 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function fetchRemoteDefault(defaultBranch) {
|
|
53
|
+
execFileSync('git', ['fetch', 'origin', defaultBranch, '--quiet'], {
|
|
54
|
+
stdio: ['ignore', 'ignore', 'pipe'],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function main() {
|
|
59
|
+
const defaultBranch = resolveDefaultBranch();
|
|
60
|
+
const branchName = getCurrentBranch();
|
|
61
|
+
const refs = parsePushRefs(fs.readFileSync(0));
|
|
62
|
+
|
|
63
|
+
if (branchName === defaultBranch || branchName === 'master') {
|
|
64
|
+
console.error('');
|
|
65
|
+
console.error(`Pre-push Safety: push blocked on protected branch '${branchName}'.`);
|
|
66
|
+
console.error('Open a feature branch or worktree first.');
|
|
67
|
+
console.error('');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (refs.some((ref) => isProtectedPushTarget(ref.remoteRef, defaultBranch))) {
|
|
72
|
+
console.error('');
|
|
73
|
+
console.error(`Pre-push Safety: direct push to '${defaultBranch}' is blocked.`);
|
|
74
|
+
console.error('Open a pull request instead.');
|
|
75
|
+
console.error('');
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
fetchRemoteDefault(defaultBranch);
|
|
81
|
+
} catch {
|
|
82
|
+
console.error('');
|
|
83
|
+
console.error(`Pre-push Safety: could not fetch origin/${defaultBranch}.`);
|
|
84
|
+
console.error('Sync with the remote before pushing.');
|
|
85
|
+
console.error('');
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!branchContainsRemoteDefault(defaultBranch)) {
|
|
90
|
+
console.error('');
|
|
91
|
+
console.error(`Pre-push Safety: your branch is missing commits from origin/${defaultBranch}.`);
|
|
92
|
+
console.error(`Merge or rebase origin/${defaultBranch} before pushing.`);
|
|
93
|
+
console.error('');
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = {
|
|
101
|
+
branchContainsRemoteDefault,
|
|
102
|
+
getCurrentBranch,
|
|
103
|
+
isProtectedPushTarget,
|
|
104
|
+
parsePushRefs,
|
|
105
|
+
resolveDefaultBranch,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
if (require.main === module) {
|
|
109
|
+
main();
|
|
110
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { execFileSync, execSync } = require('child_process');
|
|
4
|
+
|
|
5
|
+
const BLOCKED_ENV_FILE_PATTERN = /(^|\/)\.env(\..+)?$/i;
|
|
6
|
+
const SAFE_ENV_FILE_PATTERN = /(^|\/)\.env\.(example|sample|template)$/i;
|
|
7
|
+
const SECRET_PATTERNS = [
|
|
8
|
+
{ label: 'private key', pattern: /BEGIN (RSA|DSA|EC|OPENSSH|PGP) PRIVATE KEY/ },
|
|
9
|
+
{ label: 'generic private key', pattern: /BEGIN PRIVATE KEY/ },
|
|
10
|
+
{ label: 'GitHub personal token', pattern: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/ },
|
|
11
|
+
{ label: 'GitHub fine-grained token', pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/ },
|
|
12
|
+
{ label: 'OpenAI key', pattern: /\bsk-(proj-)?[A-Za-z0-9_-]{20,}\b/ },
|
|
13
|
+
{ label: 'AWS access key', pattern: /\bAKIA[0-9A-Z]{16}\b/ },
|
|
14
|
+
{ label: 'Google API key', pattern: /\bAIza[0-9A-Za-z\-_]{35}\b/ },
|
|
15
|
+
{ label: 'Slack token', pattern: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/ },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
function getStagedFiles() {
|
|
19
|
+
try {
|
|
20
|
+
const output = execSync('git diff --cached --name-only --diff-filter=ACMR', {
|
|
21
|
+
encoding: 'utf8',
|
|
22
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
23
|
+
}).trim();
|
|
24
|
+
return output ? output.split('\n').filter(Boolean) : [];
|
|
25
|
+
} catch {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isBlockedEnvFile(filePath) {
|
|
31
|
+
return BLOCKED_ENV_FILE_PATTERN.test(filePath) && !SAFE_ENV_FILE_PATTERN.test(filePath);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readStagedFile(filePath) {
|
|
35
|
+
try {
|
|
36
|
+
return execFileSync('git', ['show', `:${filePath}`], {
|
|
37
|
+
encoding: 'utf8',
|
|
38
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
39
|
+
maxBuffer: 5 * 1024 * 1024,
|
|
40
|
+
});
|
|
41
|
+
} catch {
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function findSecretMatches(content) {
|
|
47
|
+
const matches = [];
|
|
48
|
+
for (const descriptor of SECRET_PATTERNS) {
|
|
49
|
+
if (descriptor.pattern.test(content)) {
|
|
50
|
+
matches.push(descriptor.label);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return matches;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function scanStagedFiles(files) {
|
|
57
|
+
const findings = [];
|
|
58
|
+
|
|
59
|
+
for (const filePath of files) {
|
|
60
|
+
if (isBlockedEnvFile(filePath)) {
|
|
61
|
+
findings.push({ filePath, reason: 'environment file' });
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const content = readStagedFile(filePath);
|
|
66
|
+
const matches = findSecretMatches(content);
|
|
67
|
+
for (const match of matches) {
|
|
68
|
+
findings.push({ filePath, reason: match });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return findings;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function main() {
|
|
76
|
+
const stagedFiles = getStagedFiles();
|
|
77
|
+
if (stagedFiles.length === 0) {
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const findings = scanStagedFiles(stagedFiles);
|
|
82
|
+
if (findings.length === 0) {
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
console.error('');
|
|
87
|
+
console.error('Staged Secret Scan: commit blocked.');
|
|
88
|
+
console.error('');
|
|
89
|
+
for (const finding of findings) {
|
|
90
|
+
console.error(`- ${finding.filePath}: ${finding.reason}`);
|
|
91
|
+
}
|
|
92
|
+
console.error('');
|
|
93
|
+
console.error('Remove the sensitive content before committing.');
|
|
94
|
+
console.error('');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module.exports = {
|
|
99
|
+
SECRET_PATTERNS,
|
|
100
|
+
findSecretMatches,
|
|
101
|
+
getStagedFiles,
|
|
102
|
+
isBlockedEnvFile,
|
|
103
|
+
scanStagedFiles,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
if (require.main === module) {
|
|
107
|
+
main();
|
|
108
|
+
}
|