sinapse-ai 9.4.0 → 9.5.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/.claude/CLAUDE.md +10 -4
- package/.claude/hooks/enforce-architecture-first.py +197 -197
- package/.claude/hooks/enforce-git-push-authority.sh +25 -4
- package/.claude/hooks/mind-clone-governance.py +193 -193
- package/.claude/hooks/read-protection.py +152 -152
- package/.claude/hooks/sql-governance.py +183 -183
- package/.claude/hooks/verify-packages.cjs +83 -0
- package/.claude/hooks/write-path-validation.py +195 -195
- package/.claude/rules/hook-governance.md +1 -0
- package/.claude/rules/mandatory-delegation.md +24 -0
- package/.claude/rules/project-intelligence.md +63 -0
- package/.claude/rules/response-format.md +4 -0
- package/.claude/rules/safe-collaboration.md +4 -2
- package/.claude/rules/security-data-protection.md +18 -0
- package/.claude/rules/squad-awareness.md +93 -67
- package/.claude/rules/token-economy.md +148 -0
- package/.codex/agents/analyst.md +90 -0
- package/.codex/agents/architect.md +78 -0
- package/.codex/agents/data-engineer.md +38 -0
- package/.codex/agents/developer.md +97 -0
- package/.codex/agents/devops.md +121 -0
- package/.codex/agents/product-lead.md +27 -0
- package/.codex/agents/project-lead.md +28 -0
- package/.codex/agents/quality-gate.md +89 -0
- package/.codex/agents/sprint-lead.md +28 -0
- package/.codex/agents/squad-creator.md +58 -0
- package/.codex/agents/ux-design-expert.md +28 -0
- package/.sinapse-ai/core/code-intel/registry-syncer.js +56 -3
- package/.sinapse-ai/core/doctor/checks/agent-memory.js +5 -1
- package/.sinapse-ai/core/doctor/checks/claude-md.js +4 -1
- package/.sinapse-ai/core/doctor/checks/code-intel.js +5 -1
- package/.sinapse-ai/core/doctor/checks/commands-count.js +4 -1
- package/.sinapse-ai/core/doctor/checks/constitution-consistency.js +4 -1
- package/.sinapse-ai/core/doctor/checks/core-config.js +4 -1
- package/.sinapse-ai/core/doctor/checks/entity-registry.js +6 -1
- package/.sinapse-ai/core/doctor/checks/git-hooks.js +5 -1
- package/.sinapse-ai/core/doctor/checks/graph-dashboard.js +4 -1
- package/.sinapse-ai/core/doctor/checks/hooks-claude-count.js +5 -1
- package/.sinapse-ai/core/doctor/checks/ide-sync.js +4 -1
- package/.sinapse-ai/core/doctor/checks/node-version.js +4 -1
- package/.sinapse-ai/core/doctor/checks/npm-packages.js +4 -1
- package/.sinapse-ai/core/doctor/checks/rules-files.js +4 -1
- package/.sinapse-ai/core/doctor/checks/settings-json.js +4 -1
- package/.sinapse-ai/core/doctor/checks/skills-count.js +4 -1
- package/.sinapse-ai/core/doctor/index.js +157 -50
- package/.sinapse-ai/core/ids/registry-updater.js +6 -1
- package/.sinapse-ai/core/logger/index.js +319 -0
- package/.sinapse-ai/core/orchestration/terminal-spawner.js +2 -2
- package/.sinapse-ai/core/telemetry/index.js +247 -0
- package/.sinapse-ai/data/entity-registry.yaml +1384 -944
- package/.sinapse-ai/development/agents/architect.md +5 -0
- package/.sinapse-ai/development/agents/data-engineer.md +38 -0
- package/.sinapse-ai/development/agents/developer.md +28 -0
- package/.sinapse-ai/development/agents/devops.md +4 -0
- package/.sinapse-ai/development/agents/product-lead.md +27 -0
- package/.sinapse-ai/development/agents/project-lead.md +28 -0
- package/.sinapse-ai/development/agents/quality-gate.md +4 -0
- package/.sinapse-ai/development/agents/sprint-lead/MEMORY.md +8 -0
- package/.sinapse-ai/development/agents/sprint-lead.md +28 -0
- package/.sinapse-ai/development/agents/squad-creator.md +58 -0
- package/.sinapse-ai/development/agents/ux-design-expert.md +28 -0
- package/.sinapse-ai/development/knowledge-base/agent-communication-protocol.md +127 -0
- package/.sinapse-ai/development/knowledge-base/database-scaling-patterns.md +374 -0
- package/.sinapse-ai/development/knowledge-base/environment-deployment-patterns.md +353 -0
- package/.sinapse-ai/development/knowledge-base/gotchas-patterns.md +224 -0
- package/.sinapse-ai/development/knowledge-base/infrastructure-decision-framework.md +221 -0
- package/.sinapse-ai/development/knowledge-base/security-pre-deploy-checklist.md +410 -0
- package/.sinapse-ai/development/knowledge-base/software-architecture-patterns.md +299 -0
- package/.sinapse-ai/development/knowledge-base/token-economy-guide.md +198 -0
- package/.sinapse-ai/development/scripts/populate-entity-registry.js +5 -1
- package/.sinapse-ai/development/skills/captcha-handler.md +82 -0
- package/.sinapse-ai/development/skills/chrome-brain.md +81 -0
- package/.sinapse-ai/development/skills/deploy-readiness.md +93 -0
- package/.sinapse-ai/development/skills/model-router.md +92 -0
- package/.sinapse-ai/development/skills/sinapse-methodology.md +175 -0
- package/.sinapse-ai/development/skills/story-fast-track.md +71 -0
- package/.sinapse-ai/development/tasks/dev-develop-story.md +10 -0
- package/.sinapse-ai/development/tasks/environment-promotion-pipeline.md +582 -0
- package/.sinapse-ai/development/tasks/generate-agent-handoff.md +223 -0
- package/.sinapse-ai/development/tasks/infrastructure-assessment.md +432 -0
- package/.sinapse-ai/development/tasks/load-testing-setup.md +611 -0
- package/.sinapse-ai/development/tasks/observability-blueprint.md +562 -0
- package/.sinapse-ai/development/templates/legal/breach-notification-tmpl.md +113 -0
- package/.sinapse-ai/development/templates/legal/privacy-policy-tmpl.md +93 -0
- package/.sinapse-ai/development/templates/legal/terms-of-service-tmpl.md +85 -0
- package/.sinapse-ai/development/templates/service-template/README.md.hbs +159 -159
- package/.sinapse-ai/development/templates/service-template/__tests__/index.test.ts.hbs +238 -238
- package/.sinapse-ai/development/templates/service-template/client.ts.hbs +404 -404
- package/.sinapse-ai/development/templates/service-template/errors.ts.hbs +183 -183
- package/.sinapse-ai/development/templates/service-template/index.ts.hbs +121 -121
- package/.sinapse-ai/development/templates/service-template/package.json.hbs +88 -88
- package/.sinapse-ai/development/templates/service-template/types.ts.hbs +146 -146
- package/.sinapse-ai/development/templates/squad-template/LICENSE +22 -22
- package/.sinapse-ai/development/workflows/story-development-cycle.yaml +40 -1
- package/.sinapse-ai/hooks/ids-post-commit.js +22 -0
- package/.sinapse-ai/infrastructure/contracts/compatibility/README.md +42 -0
- package/.sinapse-ai/infrastructure/contracts/compatibility/sinapse-current.yaml +35 -0
- package/.sinapse-ai/infrastructure/scripts/llm-routing/templates/claude-free-tracked.cmd +127 -127
- package/.sinapse-ai/infrastructure/scripts/llm-routing/templates/deepseek-proxy.cmd +71 -71
- package/.sinapse-ai/infrastructure/scripts/llm-routing/templates/deepseek-usage.cmd +51 -51
- package/.sinapse-ai/infrastructure/scripts/pr-review-ai.js +16 -13
- package/.sinapse-ai/infrastructure/scripts/setup-project-infra.js +128 -0
- package/.sinapse-ai/infrastructure/scripts/test-discovery.js +8 -3
- package/.sinapse-ai/infrastructure/scripts/validate-manifest-parity.js +380 -0
- package/.sinapse-ai/infrastructure/scripts/validate-parity.js +76 -25
- package/.sinapse-ai/infrastructure/templates/coderabbit.yaml.template +280 -280
- package/.sinapse-ai/infrastructure/templates/config/env.example +16 -0
- package/.sinapse-ai/infrastructure/templates/config/gitignore-additions.tmpl +59 -0
- package/.sinapse-ai/infrastructure/templates/github/CODEOWNERS.template +12 -0
- package/.sinapse-ai/infrastructure/templates/github/PULL_REQUEST_TEMPLATE.md +29 -0
- package/.sinapse-ai/infrastructure/templates/github/ci-template.yml +77 -0
- package/.sinapse-ai/infrastructure/templates/github/issue-templates/bug_report.md +34 -0
- package/.sinapse-ai/infrastructure/templates/github/issue-templates/feature_request.md +19 -0
- package/.sinapse-ai/infrastructure/templates/github-workflows/ci.yml.template +170 -170
- package/.sinapse-ai/infrastructure/templates/github-workflows/pr-automation.yml.template +331 -331
- package/.sinapse-ai/infrastructure/templates/github-workflows/release.yml.template +197 -197
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +19 -19
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-node.tmpl +86 -86
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-python.tmpl +146 -146
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-sinapse-base.tmpl +64 -64
- package/.sinapse-ai/infrastructure/templates/sinapse-sync.yaml.template +183 -183
- package/.sinapse-ai/install-manifest.yaml +275 -140
- package/.sinapse-ai/local-config.yaml.template +65 -65
- package/.sinapse-ai/monitor/hooks/lib/__init__.py +2 -2
- package/.sinapse-ai/monitor/hooks/lib/enrich.py +59 -59
- package/.sinapse-ai/monitor/hooks/lib/send_event.py +48 -48
- package/.sinapse-ai/monitor/hooks/notification.py +30 -30
- package/.sinapse-ai/monitor/hooks/post_tool_use.py +46 -46
- package/.sinapse-ai/monitor/hooks/pre_compact.py +30 -30
- package/.sinapse-ai/monitor/hooks/pre_tool_use.py +41 -41
- package/.sinapse-ai/monitor/hooks/stop.py +30 -30
- package/.sinapse-ai/monitor/hooks/subagent_stop.py +30 -30
- package/.sinapse-ai/monitor/hooks/user_prompt_submit.py +39 -39
- package/.sinapse-ai/product/templates/adr.hbs +126 -126
- package/.sinapse-ai/product/templates/dbdr.hbs +242 -242
- package/.sinapse-ai/product/templates/epic.hbs +213 -213
- package/.sinapse-ai/product/templates/pmdr.hbs +187 -187
- package/.sinapse-ai/product/templates/prd-v2.0.hbs +217 -217
- package/.sinapse-ai/product/templates/prd.hbs +202 -202
- package/.sinapse-ai/product/templates/story-tmpl.yaml +59 -0
- package/.sinapse-ai/product/templates/story.hbs +264 -264
- package/.sinapse-ai/product/templates/task.hbs +171 -171
- package/.sinapse-ai/product/templates/tmpl-comment-on-examples.sql +159 -159
- package/.sinapse-ai/product/templates/tmpl-migration-script.sql +92 -92
- package/.sinapse-ai/product/templates/tmpl-rls-granular-policies.sql +105 -105
- package/.sinapse-ai/product/templates/tmpl-rls-kiss-policy.sql +11 -11
- package/.sinapse-ai/product/templates/tmpl-rls-roles.sql +136 -136
- package/.sinapse-ai/product/templates/tmpl-rls-simple.sql +78 -78
- package/.sinapse-ai/product/templates/tmpl-rls-tenant.sql +153 -153
- package/.sinapse-ai/product/templates/tmpl-rollback-script.sql +78 -78
- package/.sinapse-ai/product/templates/tmpl-seed-data.sql +141 -141
- package/.sinapse-ai/product/templates/tmpl-smoke-test.sql +17 -17
- package/.sinapse-ai/product/templates/tmpl-staging-copy-merge.sql +140 -140
- package/.sinapse-ai/product/templates/tmpl-stored-proc.sql +141 -141
- package/.sinapse-ai/product/templates/tmpl-trigger.sql +153 -153
- package/.sinapse-ai/product/templates/tmpl-view-materialized.sql +134 -134
- package/.sinapse-ai/product/templates/tmpl-view.sql +178 -178
- package/.sinapse-ai/scripts/diagnostics/health-dashboard/package-lock.json +427 -355
- package/LICENSE +34 -34
- package/README.en.md +167 -20
- package/README.md +190 -22
- package/bin/cli.js +510 -196
- package/bin/postinstall.js +564 -0
- package/bin/sinapse-cli +283 -283
- package/bin/sinapse-graph.js +9 -0
- package/bin/sinapse-init.js +36 -4
- package/bin/sinapse-minimal.js +20 -9
- package/bin/sinapse.js +202 -122
- package/bin/utils/deprecation-warning.js +46 -0
- package/bin/utils/pre-push-safety.js +14 -0
- package/docs/TELEMETRY.md +131 -0
- package/docs/chrome-brain-upgrade-plan.md +624 -0
- package/docs/framework/orqx-plan.md +1 -1
- package/docs/installation/chrome-brain.md +17 -7
- package/docs/mega-upgrade-orchestration-plan.md +71 -0
- package/docs/pt/contributing.md +20 -0
- package/docs/research-synthesis-for-upgrade.md +511 -0
- package/docs/security-audit-report.md +306 -0
- package/package.json +20 -8
- package/packages/installer/src/config/configure-environment.js +19 -44
- package/packages/installer/src/detection/detect-project-type.js +181 -63
- package/packages/installer/src/installer/manifest-signature.js +32 -17
- package/packages/installer/src/wizard/i18n.js +12 -0
- package/packages/installer/src/wizard/ide-config-generator.js +8 -39
- package/packages/installer/src/wizard/index.js +119 -14
- package/packages/installer/src/wizard/questions.js +2 -3
- package/packages/installer/tests/integration/environment-configuration.test.js +7 -5
- package/packages/installer/tests/unit/detection/detect-project-type.test.js +138 -1
- package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +3 -3
- package/packages/sinapse-install/bin/edmcp.js +0 -0
- package/packages/sinapse-install/bin/sinapse-install.js +0 -0
- package/packages/sinapse-pro-cli/bin/sinapse-pro.js +0 -0
- package/scripts/check-markdown-links.py +353 -353
- package/scripts/coverage-report-summary.js +169 -0
- package/scripts/generate-install-manifest.js +6 -2
- package/scripts/release-readiness.js +169 -0
- package/scripts/test-install-matrix-local.sh +153 -0
- package/scripts/validate-install-docs.js +394 -0
- package/scripts/validate-no-external-refs.js +376 -0
- package/scripts/validate-squad-orqx.js +302 -0
- package/scripts/validate-story-meta.js +263 -0
- package/squads/claude-code-mastery/CHANGELOG.md +1 -1
- package/squads/claude-code-mastery/README.md +2 -2
- package/squads/claude-code-mastery/squad.yaml +1 -1
- package/squads/squad-artdir/README.md +90 -0
- package/squads/squad-artdir/agents/accessibility-guardian.md +184 -0
- package/squads/squad-artdir/agents/artdir-orqx.md +145 -0
- package/squads/squad-artdir/agents/color-psychologist.md +166 -0
- package/squads/squad-artdir/agents/cro-persuasion.md +161 -0
- package/squads/squad-artdir/agents/design-system-architect.md +100 -0
- package/squads/squad-artdir/agents/ia-architect.md +169 -0
- package/squads/squad-artdir/agents/interaction-designer.md +162 -0
- package/squads/squad-artdir/agents/layout-engineer.md +163 -0
- package/squads/squad-artdir/agents/motion-architect.md +185 -0
- package/squads/squad-artdir/agents/platform-aesthetic-director.md +84 -0
- package/squads/squad-artdir/agents/premium-packaging-strategist.md +107 -0
- package/squads/squad-artdir/agents/product-surface-director.md +86 -0
- package/squads/squad-artdir/agents/type-systemist.md +138 -0
- package/squads/squad-artdir/agents/visual-strategist.md +127 -0
- package/squads/squad-artdir/checklists/seven-pillars-validation-checklist.md +172 -0
- package/squads/squad-artdir/knowledge-base/case-nyo-ia-reference.md +289 -0
- package/squads/squad-artdir/knowledge-base/deliverables-templates.md +457 -0
- package/squads/squad-artdir/knowledge-base/motion-technique-catalog.md +247 -0
- package/squads/squad-artdir/knowledge-base/premium-packaging-principles.md +133 -0
- package/squads/squad-artdir/knowledge-base/psychological-toolkit.md +229 -0
- package/squads/squad-artdir/knowledge-base/saas-art-direction-canon.md +242 -0
- package/squads/squad-artdir/knowledge-base/seven-pillars-framework.md +289 -0
- package/squads/squad-artdir/knowledge-base/ten-pillars-framework.md +221 -0
- package/squads/squad-artdir/package.json +20 -0
- package/squads/squad-artdir/squad.yaml +271 -0
- package/squads/squad-artdir/tasks/audit-conversion.md +97 -0
- package/squads/squad-artdir/tasks/audit-drift-multi-surface.md +55 -0
- package/squads/squad-artdir/tasks/consult-saas-canon.md +54 -0
- package/squads/squad-artdir/tasks/create-art-direction-brief.md +110 -0
- package/squads/squad-artdir/tasks/create-premium-packaging-brief.md +61 -0
- package/squads/squad-artdir/tasks/create-wireflow.md +84 -0
- package/squads/squad-artdir/tasks/design-color-system.md +81 -0
- package/squads/squad-artdir/tasks/design-product-surface.md +60 -0
- package/squads/squad-artdir/tasks/design-token-system.md +58 -0
- package/squads/squad-artdir/tasks/diagnose-visual-language.md +92 -0
- package/squads/squad-artdir/tasks/first-5-minutes-choreography.md +65 -0
- package/squads/squad-artdir/tasks/specify-motion-system.md +84 -0
- package/squads/squad-artdir/tasks/validate-against-pillars.md +143 -0
- package/squads/squad-artdir/templates/art-direction-brief-template.md +215 -0
- package/squads/squad-artdir/workflows/conversion-audit-cycle.yaml +78 -0
- package/squads/squad-artdir/workflows/full-art-direction-cycle.yaml +98 -0
- package/squads/squad-artdir/workflows/saas-platform-art-direction-cycle.yaml +174 -0
- package/squads/squad-brand/knowledge-base/ai-visual-generation-canon.md +234 -0
- package/squads/squad-brand/squad.yaml +20 -6
- package/squads/squad-claude/knowledge-base/context-window-optimization.md +1 -1
- package/squads/squad-claude/knowledge-base/swarm-orchestration-patterns.md +2 -2
- package/squads/squad-content/knowledge-base/ai-native-content-loop.md +220 -0
- package/squads/squad-content/knowledge-base/signal-intelligence-v2.md +234 -0
- package/squads/squad-content/knowledge-base/task-ownership-map.md +235 -0
- package/squads/squad-content/squad.yaml +187 -27
- package/squads/squad-copy/knowledge-base/ai-copy-human-loop-canon.md +235 -0
- package/squads/squad-copy/squad.yaml +19 -4
- package/squads/squad-design/knowledge-base/cross-surface-token-canon.md +209 -0
- package/squads/squad-design/squad.yaml +19 -4
- package/.sinapse-ai/core/registry/service-registry.json +0 -6346
- package/.sinapse-ai/data/registry-update-log.jsonl +0 -1323
- package/.sinapse-ai/manifests/agents.csv +0 -29
- package/.sinapse-ai/manifests/tasks.csv +0 -204
- package/.sinapse-ai/manifests/workers.csv +0 -196
- package/squads/squad-growth/tasks/calculate-sample-size.md +0 -121
- package/squads/squad-paidmedia/tasks/calculate-sample-size.md +0 -57
|
@@ -58,5 +58,8 @@ async function run(context) {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
// Story A.3: rules files ship with the framework; exceptions indicate real damage.
|
|
62
|
+
const onError = 'fail';
|
|
63
|
+
|
|
64
|
+
module.exports = { name, run, EXPECTED_RULES, onError };
|
|
62
65
|
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SINAPSE Doctor — Environment Health Check Orchestrator
|
|
3
3
|
*
|
|
4
|
-
* Runs
|
|
4
|
+
* Runs modular checks against the SINAPSE environment and returns
|
|
5
5
|
* structured results with optional --fix, --json, and --dry-run support.
|
|
6
6
|
*
|
|
7
|
+
* Exception Classification (Story A.3):
|
|
8
|
+
* Each check module may export an `onError` field with one of:
|
|
9
|
+
* - 'fail' (default) — thrown exceptions map to a FAIL verdict
|
|
10
|
+
* - 'warn' — thrown exceptions map to a WARN verdict
|
|
11
|
+
* - 'skip' — thrown exceptions cause the check to be excluded
|
|
12
|
+
* from results entirely
|
|
13
|
+
*
|
|
14
|
+
* This replaces the previous behavior where the generic catch block
|
|
15
|
+
* marked every exception as FAIL, producing false alarms on fresh
|
|
16
|
+
* installs (no git repo, empty registry, missing agent memory dirs).
|
|
17
|
+
*
|
|
7
18
|
* @module sinapse-ai/doctor
|
|
8
|
-
* @version 2.
|
|
9
|
-
* @story INS-4.1
|
|
19
|
+
* @version 2.1.0
|
|
20
|
+
* @story INS-4.1, A.3
|
|
10
21
|
*/
|
|
11
22
|
|
|
12
23
|
const path = require('path');
|
|
@@ -15,7 +26,46 @@ const { formatText } = require('./formatters/text');
|
|
|
15
26
|
const { formatJson } = require('./formatters/json');
|
|
16
27
|
const { applyFixes } = require('./fix-handler');
|
|
17
28
|
|
|
18
|
-
const DOCTOR_VERSION = '2.
|
|
29
|
+
const DOCTOR_VERSION = '2.1.0';
|
|
30
|
+
|
|
31
|
+
const VALID_ON_ERROR = new Set(['fail', 'warn', 'skip']);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Map a check module's `onError` field to the verdict produced when
|
|
35
|
+
* the check itself throws. Falls back to 'fail' for safety.
|
|
36
|
+
*
|
|
37
|
+
* @param {Object} checkModule
|
|
38
|
+
* @returns {'fail' | 'warn' | 'skip'}
|
|
39
|
+
*/
|
|
40
|
+
function resolveOnError(checkModule) {
|
|
41
|
+
const declared = checkModule && checkModule.onError;
|
|
42
|
+
if (declared && VALID_ON_ERROR.has(declared)) {
|
|
43
|
+
return declared;
|
|
44
|
+
}
|
|
45
|
+
return 'fail';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Build a structured result entry for a thrown exception, based on
|
|
50
|
+
* the check's declared error policy. Returns null if the policy is
|
|
51
|
+
* 'skip' (excluded from results).
|
|
52
|
+
*
|
|
53
|
+
* @param {Object} checkModule
|
|
54
|
+
* @param {Error} error
|
|
55
|
+
* @returns {Object|null}
|
|
56
|
+
*/
|
|
57
|
+
function buildErrorResult(checkModule, error) {
|
|
58
|
+
const policy = resolveOnError(checkModule);
|
|
59
|
+
if (policy === 'skip') {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
check: checkModule.name || 'unknown',
|
|
64
|
+
status: policy === 'warn' ? 'WARN' : 'FAIL',
|
|
65
|
+
message: `Check threw error: ${error.message}`,
|
|
66
|
+
fixCommand: null,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
19
69
|
|
|
20
70
|
/**
|
|
21
71
|
* Run all doctor checks
|
|
@@ -26,7 +76,7 @@ const DOCTOR_VERSION = '2.0.0';
|
|
|
26
76
|
* @param {boolean} [options.dryRun=false] - Show what --fix would do
|
|
27
77
|
* @param {boolean} [options.quiet=false] - Minimal output
|
|
28
78
|
* @param {string} [options.projectRoot] - Project root (defaults to cwd)
|
|
29
|
-
* @returns {Promise<Object>} Doctor results
|
|
79
|
+
* @returns {Promise<Object>} Doctor results (includes `internalError` when the runner itself crashes)
|
|
30
80
|
*/
|
|
31
81
|
async function runDoctorChecks(options = {}) {
|
|
32
82
|
const {
|
|
@@ -38,58 +88,115 @@ async function runDoctorChecks(options = {}) {
|
|
|
38
88
|
projectRoot = process.cwd(),
|
|
39
89
|
} = options;
|
|
40
90
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
91
|
+
try {
|
|
92
|
+
const context = {
|
|
93
|
+
projectRoot,
|
|
94
|
+
frameworkRoot: path.resolve(__dirname, '..', '..', '..'),
|
|
95
|
+
options: { fix, json, dryRun, quiet, deep },
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Load and run all checks (deep checks only with --deep flag)
|
|
99
|
+
const checks = loadChecks({ deep });
|
|
100
|
+
const results = [];
|
|
46
101
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
status: 'FAIL',
|
|
59
|
-
message: `Check threw error: ${error.message}`,
|
|
60
|
-
fixCommand: null,
|
|
61
|
-
});
|
|
102
|
+
for (const checkModule of checks) {
|
|
103
|
+
try {
|
|
104
|
+
const result = await checkModule.run(context);
|
|
105
|
+
results.push(result);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
const errorResult = buildErrorResult(checkModule, error);
|
|
108
|
+
if (errorResult !== null) {
|
|
109
|
+
results.push(errorResult);
|
|
110
|
+
}
|
|
111
|
+
// policy === 'skip' → silently exclude
|
|
112
|
+
}
|
|
62
113
|
}
|
|
63
|
-
}
|
|
64
114
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
115
|
+
// Apply fixes if requested
|
|
116
|
+
let fixResults = null;
|
|
117
|
+
if (fix || dryRun) {
|
|
118
|
+
fixResults = await applyFixes(results, context);
|
|
119
|
+
}
|
|
70
120
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
121
|
+
// Build summary
|
|
122
|
+
const summary = {
|
|
123
|
+
pass: results.filter((r) => r.status === 'PASS').length,
|
|
124
|
+
warn: results.filter((r) => r.status === 'WARN').length,
|
|
125
|
+
fail: results.filter((r) => r.status === 'FAIL').length,
|
|
126
|
+
info: results.filter((r) => r.status === 'INFO').length,
|
|
127
|
+
};
|
|
78
128
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
129
|
+
const output = {
|
|
130
|
+
version: DOCTOR_VERSION,
|
|
131
|
+
timestamp: new Date().toISOString(),
|
|
132
|
+
summary,
|
|
133
|
+
checks: results,
|
|
134
|
+
fixResults,
|
|
135
|
+
internalError: null,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Format output
|
|
139
|
+
if (json) {
|
|
140
|
+
return { formatted: formatJson(output), data: output };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return { formatted: formatText(output, { quiet }), data: output };
|
|
144
|
+
} catch (runnerError) {
|
|
145
|
+
// Runner itself crashed (not a check throwing). Surface as exit code 3.
|
|
146
|
+
const summary = { pass: 0, warn: 0, fail: 0, info: 0 };
|
|
147
|
+
const errorPayload = {
|
|
148
|
+
message: runnerError.message,
|
|
149
|
+
stack: runnerError.stack,
|
|
150
|
+
};
|
|
151
|
+
const output = {
|
|
152
|
+
version: DOCTOR_VERSION,
|
|
153
|
+
timestamp: new Date().toISOString(),
|
|
154
|
+
summary,
|
|
155
|
+
checks: [],
|
|
156
|
+
fixResults: null,
|
|
157
|
+
internalError: errorPayload,
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const formatted = json
|
|
161
|
+
? formatJson(output)
|
|
162
|
+
: `SINAPSE Doctor v${DOCTOR_VERSION} — internal error: ${runnerError.message}`;
|
|
86
163
|
|
|
87
|
-
|
|
88
|
-
if (json) {
|
|
89
|
-
return { formatted: formatJson(output), data: output };
|
|
164
|
+
return { formatted, data: output };
|
|
90
165
|
}
|
|
166
|
+
}
|
|
91
167
|
|
|
92
|
-
|
|
168
|
+
/**
|
|
169
|
+
* Resolve a doctor result object into a canonical exit code.
|
|
170
|
+
*
|
|
171
|
+
* Story A.3 exit code mapping:
|
|
172
|
+
* 0 — PASS (no FAILs, no WARNs)
|
|
173
|
+
* 1 — WARN only (no FAILs)
|
|
174
|
+
* 2 — at least one FAIL
|
|
175
|
+
* 3 — internal runner error (runDoctorChecks itself crashed)
|
|
176
|
+
*
|
|
177
|
+
* @param {Object} result - Return value from runDoctorChecks()
|
|
178
|
+
* @returns {0 | 1 | 2 | 3}
|
|
179
|
+
*/
|
|
180
|
+
function resolveExitCode(result) {
|
|
181
|
+
if (!result || !result.data) {
|
|
182
|
+
return 3;
|
|
183
|
+
}
|
|
184
|
+
if (result.data.internalError) {
|
|
185
|
+
return 3;
|
|
186
|
+
}
|
|
187
|
+
const summary = result.data.summary || {};
|
|
188
|
+
if ((summary.fail || 0) > 0) {
|
|
189
|
+
return 2;
|
|
190
|
+
}
|
|
191
|
+
if ((summary.warn || 0) > 0) {
|
|
192
|
+
return 1;
|
|
193
|
+
}
|
|
194
|
+
return 0;
|
|
93
195
|
}
|
|
94
196
|
|
|
95
|
-
module.exports = {
|
|
197
|
+
module.exports = {
|
|
198
|
+
runDoctorChecks,
|
|
199
|
+
resolveExitCode,
|
|
200
|
+
resolveOnError,
|
|
201
|
+
DOCTOR_VERSION,
|
|
202
|
+
};
|
|
@@ -483,10 +483,15 @@ class RegistryUpdater {
|
|
|
483
483
|
}
|
|
484
484
|
|
|
485
485
|
_writeRegistry(registryData) {
|
|
486
|
+
// Story 10.24 — sortKeys: true makes the YAML output deterministic.
|
|
487
|
+
// Without it, key order follows JS object insertion order, which means
|
|
488
|
+
// semantically-identical writes can produce textually-different files
|
|
489
|
+
// and cause endless `M entity-registry.yaml` churn in `git status`.
|
|
490
|
+
// The registry is machine-managed so alphabetical key order is fine.
|
|
486
491
|
const yamlStr = yaml.dump(registryData, {
|
|
487
492
|
lineWidth: 120,
|
|
488
493
|
noRefs: true,
|
|
489
|
-
sortKeys:
|
|
494
|
+
sortKeys: true,
|
|
490
495
|
});
|
|
491
496
|
|
|
492
497
|
const dir = path.dirname(this._registryPath);
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SINAPSE Logger — unified logging abstraction
|
|
5
|
+
* @story A.2 - Logger & Verbose Flag Refactor
|
|
6
|
+
*
|
|
7
|
+
* Levels:
|
|
8
|
+
* error = 0 (always shown, except nothing is shown in --json mode until flush)
|
|
9
|
+
* warn = 1 (default floor — shown unless --quiet)
|
|
10
|
+
* info = 2 (shown on --verbose)
|
|
11
|
+
* debug = 3 (shown on --debug)
|
|
12
|
+
*
|
|
13
|
+
* Flag resolution priority (highest wins):
|
|
14
|
+
* --quiet > --debug > --verbose > default(warn)
|
|
15
|
+
*
|
|
16
|
+
* Extra modes:
|
|
17
|
+
* --json Structured output: all human text is suppressed; logger accumulates a
|
|
18
|
+
* JSON summary which is flushed at process exit (flush() also callable).
|
|
19
|
+
*
|
|
20
|
+
* First-run detection:
|
|
21
|
+
* ASCII art header is gated by level (info+) OR the absence of
|
|
22
|
+
* ~/.sinapse/.first-run-done. The first run creates this flag file.
|
|
23
|
+
*
|
|
24
|
+
* Design constraints (from story Dev Notes):
|
|
25
|
+
* - Zero external deps (pure Node stdlib).
|
|
26
|
+
* - Safe on repeated require() from bin/cli.js and bin/sinapse.js in same process.
|
|
27
|
+
* - Tests can call createLogger({ level, json }) to build isolated instances.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
const fs = require('fs');
|
|
31
|
+
const os = require('os');
|
|
32
|
+
const path = require('path');
|
|
33
|
+
|
|
34
|
+
const LEVELS = Object.freeze({
|
|
35
|
+
error: 0,
|
|
36
|
+
warn: 1,
|
|
37
|
+
info: 2,
|
|
38
|
+
debug: 3,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const LEVEL_NAMES = Object.freeze(['error', 'warn', 'info', 'debug']);
|
|
42
|
+
|
|
43
|
+
const DEFAULT_LEVEL = 'warn';
|
|
44
|
+
|
|
45
|
+
const SINAPSE_HOME = path.join(os.homedir(), '.sinapse');
|
|
46
|
+
const FIRST_RUN_FLAG = path.join(SINAPSE_HOME, '.first-run-done');
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Resolve level from parsed flags. Higher verbosity wins unless --quiet is set.
|
|
50
|
+
* --quiet beats everything else (error only).
|
|
51
|
+
* @param {{ quiet?: boolean, debug?: boolean, verbose?: boolean }} flags
|
|
52
|
+
* @returns {'error'|'warn'|'info'|'debug'}
|
|
53
|
+
*/
|
|
54
|
+
function resolveLevel(flags = {}) {
|
|
55
|
+
if (flags.quiet) return 'error';
|
|
56
|
+
if (flags.debug) return 'debug';
|
|
57
|
+
if (flags.verbose) return 'info';
|
|
58
|
+
return DEFAULT_LEVEL;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Parse verbosity/output flags from an argv-like array (process.argv.slice(2)).
|
|
63
|
+
* Non-destructive — returns a plain object, does not mutate the input.
|
|
64
|
+
* @param {string[]} argv
|
|
65
|
+
*/
|
|
66
|
+
function parseFlags(argv) {
|
|
67
|
+
const a = Array.isArray(argv) ? argv : [];
|
|
68
|
+
const has = (name) => a.includes(name);
|
|
69
|
+
return {
|
|
70
|
+
quiet: has('--quiet') || has('-q'),
|
|
71
|
+
verbose: has('--verbose') || has('-v'),
|
|
72
|
+
debug: has('--debug'),
|
|
73
|
+
json: has('--json'),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Detect whether this is a first run. True when the flag file does NOT exist.
|
|
79
|
+
* Any filesystem error is treated as "not first run" to avoid breaking headless
|
|
80
|
+
* environments (safer default: stay quiet).
|
|
81
|
+
*/
|
|
82
|
+
function isFirstRun() {
|
|
83
|
+
try {
|
|
84
|
+
return !fs.existsSync(FIRST_RUN_FLAG);
|
|
85
|
+
} catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Mark first run as done by touching the flag file. Idempotent and failure-tolerant.
|
|
92
|
+
*/
|
|
93
|
+
function markFirstRunDone() {
|
|
94
|
+
try {
|
|
95
|
+
if (!fs.existsSync(SINAPSE_HOME)) {
|
|
96
|
+
fs.mkdirSync(SINAPSE_HOME, { recursive: true });
|
|
97
|
+
}
|
|
98
|
+
if (!fs.existsSync(FIRST_RUN_FLAG)) {
|
|
99
|
+
fs.writeFileSync(FIRST_RUN_FLAG, `${new Date().toISOString()}\n`, 'utf8');
|
|
100
|
+
}
|
|
101
|
+
} catch {
|
|
102
|
+
/* non-fatal — first-run detection will just keep asking */
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Build a logger instance.
|
|
108
|
+
* @param {object} [opts]
|
|
109
|
+
* @param {'error'|'warn'|'info'|'debug'} [opts.level] explicit level (overrides flags)
|
|
110
|
+
* @param {boolean} [opts.json] json mode
|
|
111
|
+
* @param {NodeJS.WritableStream} [opts.stdout] stdout sink (testable)
|
|
112
|
+
* @param {NodeJS.WritableStream} [opts.stderr] stderr sink (testable)
|
|
113
|
+
*/
|
|
114
|
+
function createLogger(opts = {}) {
|
|
115
|
+
const level = opts.level && LEVELS[opts.level] !== undefined ? opts.level : DEFAULT_LEVEL;
|
|
116
|
+
const threshold = LEVELS[level];
|
|
117
|
+
const json = Boolean(opts.json);
|
|
118
|
+
const stdout = opts.stdout || process.stdout;
|
|
119
|
+
const stderr = opts.stderr || process.stderr;
|
|
120
|
+
|
|
121
|
+
// JSON-mode accumulator. Flushed as a single JSON object on flush() or process exit.
|
|
122
|
+
const jsonState = {
|
|
123
|
+
status: 'ok',
|
|
124
|
+
version: null,
|
|
125
|
+
agents: [],
|
|
126
|
+
warnings: [],
|
|
127
|
+
errors: [],
|
|
128
|
+
messages: [],
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
function emit(channel, lvl, args) {
|
|
132
|
+
if (json) {
|
|
133
|
+
const text = args
|
|
134
|
+
.map((a) => (a instanceof Error ? a.stack || a.message : typeof a === 'object' ? safeStringify(a) : String(a)))
|
|
135
|
+
.join(' ');
|
|
136
|
+
if (lvl === 'error') jsonState.errors.push(text);
|
|
137
|
+
else if (lvl === 'warn') jsonState.warnings.push(text);
|
|
138
|
+
else jsonState.messages.push({ level: lvl, text });
|
|
139
|
+
if (lvl === 'error') jsonState.status = 'error';
|
|
140
|
+
else if (lvl === 'warn' && jsonState.status === 'ok') jsonState.status = 'warn';
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const stream = channel === 'stderr' ? stderr : stdout;
|
|
144
|
+
try {
|
|
145
|
+
stream.write(`${formatArgs(args)}\n`);
|
|
146
|
+
} catch {
|
|
147
|
+
/* broken pipe / closed stream — swallow */
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function formatArgs(args) {
|
|
152
|
+
return args
|
|
153
|
+
.map((a) => {
|
|
154
|
+
if (a instanceof Error) return a.stack || a.message;
|
|
155
|
+
if (typeof a === 'object' && a !== null) return safeStringify(a);
|
|
156
|
+
return String(a);
|
|
157
|
+
})
|
|
158
|
+
.join(' ');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const api = {
|
|
162
|
+
level,
|
|
163
|
+
threshold,
|
|
164
|
+
json,
|
|
165
|
+
|
|
166
|
+
isEnabled(lvl) {
|
|
167
|
+
return LEVELS[lvl] !== undefined && LEVELS[lvl] <= threshold;
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
error(...args) {
|
|
171
|
+
// error is always captured (level 0)
|
|
172
|
+
emit('stderr', 'error', args);
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
warn(...args) {
|
|
176
|
+
if (threshold >= LEVELS.warn) emit('stderr', 'warn', args);
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
info(...args) {
|
|
180
|
+
if (threshold >= LEVELS.info) emit('stdout', 'info', args);
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
debug(...args) {
|
|
184
|
+
if (threshold >= LEVELS.debug) emit('stdout', 'debug', args);
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Write raw text to stdout at info-or-higher. Used by commands that need
|
|
189
|
+
* to render tables / long output that should NOT appear on default runs.
|
|
190
|
+
*/
|
|
191
|
+
print(...args) {
|
|
192
|
+
if (json) {
|
|
193
|
+
jsonState.messages.push({ level: 'info', text: formatArgs(args) });
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (threshold >= LEVELS.info) {
|
|
197
|
+
try {
|
|
198
|
+
stdout.write(`${formatArgs(args)}\n`);
|
|
199
|
+
} catch { /* ignore */ }
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Always-on stdout write. For output that MUST appear at default level
|
|
205
|
+
* (e.g. one-line status: "SINAPSE ready."). Respects --json and --quiet.
|
|
206
|
+
* --quiet: suppressed unless this is a direct error.
|
|
207
|
+
*/
|
|
208
|
+
always(...args) {
|
|
209
|
+
if (json) {
|
|
210
|
+
jsonState.messages.push({ level: 'always', text: formatArgs(args) });
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (threshold === LEVELS.error) return; // --quiet
|
|
214
|
+
try {
|
|
215
|
+
stdout.write(`${formatArgs(args)}\n`);
|
|
216
|
+
} catch { /* ignore */ }
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Set the package version on the JSON state. Harmless in non-json mode.
|
|
221
|
+
*/
|
|
222
|
+
setVersion(version) {
|
|
223
|
+
jsonState.version = version;
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Push an agent entry into the JSON state. Harmless in non-json mode.
|
|
228
|
+
*/
|
|
229
|
+
addAgent(name, meta = {}) {
|
|
230
|
+
jsonState.agents.push({ name, ...meta });
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Flush the JSON state to stdout as a single structured object.
|
|
235
|
+
* Safe to call multiple times — no-op after the first call.
|
|
236
|
+
*/
|
|
237
|
+
flush() {
|
|
238
|
+
if (!json || api._flushed) return;
|
|
239
|
+
api._flushed = true;
|
|
240
|
+
try {
|
|
241
|
+
stdout.write(`${JSON.stringify(jsonState)}\n`);
|
|
242
|
+
} catch { /* ignore */ }
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
_jsonState: jsonState,
|
|
246
|
+
_flushed: false,
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
return api;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Build the process-wide logger from process.argv. Cached: repeated calls return
|
|
254
|
+
* the same instance so `bin/cli.js` and `bin/sinapse.js` share state in a single run.
|
|
255
|
+
*/
|
|
256
|
+
let _singleton = null;
|
|
257
|
+
|
|
258
|
+
function getLogger(argvOverride) {
|
|
259
|
+
if (_singleton) return _singleton;
|
|
260
|
+
const argv = argvOverride || process.argv.slice(2);
|
|
261
|
+
const flags = parseFlags(argv);
|
|
262
|
+
_singleton = createLogger({
|
|
263
|
+
level: resolveLevel(flags),
|
|
264
|
+
json: flags.json,
|
|
265
|
+
});
|
|
266
|
+
_singleton._flags = flags;
|
|
267
|
+
|
|
268
|
+
// Ensure JSON state is flushed on process exit so --json is reliable.
|
|
269
|
+
if (flags.json) {
|
|
270
|
+
const flush = () => { try { _singleton.flush(); } catch { /* noop */ } };
|
|
271
|
+
process.on('exit', flush);
|
|
272
|
+
process.on('beforeExit', flush);
|
|
273
|
+
}
|
|
274
|
+
return _singleton;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** Reset the singleton (tests only). */
|
|
278
|
+
function _resetLogger() {
|
|
279
|
+
_singleton = null;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Decide whether the ASCII art header should be shown.
|
|
284
|
+
*
|
|
285
|
+
* show if: level >= info (i.e. --verbose or --debug)
|
|
286
|
+
* OR first run (no flag file)
|
|
287
|
+
*
|
|
288
|
+
* never show in --json mode or --quiet mode.
|
|
289
|
+
*/
|
|
290
|
+
function shouldShowHeader(logger) {
|
|
291
|
+
if (!logger) return false;
|
|
292
|
+
if (logger.json) return false;
|
|
293
|
+
if (logger.threshold === LEVELS.error) return false; // --quiet
|
|
294
|
+
if (logger.threshold >= LEVELS.info) return true; // --verbose / --debug
|
|
295
|
+
return isFirstRun();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function safeStringify(value) {
|
|
299
|
+
try {
|
|
300
|
+
return JSON.stringify(value);
|
|
301
|
+
} catch {
|
|
302
|
+
return '[unserializable]';
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
module.exports = {
|
|
307
|
+
LEVELS,
|
|
308
|
+
LEVEL_NAMES,
|
|
309
|
+
DEFAULT_LEVEL,
|
|
310
|
+
FIRST_RUN_FLAG,
|
|
311
|
+
createLogger,
|
|
312
|
+
getLogger,
|
|
313
|
+
parseFlags,
|
|
314
|
+
resolveLevel,
|
|
315
|
+
isFirstRun,
|
|
316
|
+
markFirstRunDone,
|
|
317
|
+
shouldShowHeader,
|
|
318
|
+
_resetLogger,
|
|
319
|
+
};
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const { spawn, execSync } = require('child_process');
|
|
15
|
+
const { spawn, execSync, execFileSync } = require('child_process');
|
|
16
16
|
const fs = require('fs').promises;
|
|
17
17
|
const fsSync = require('fs');
|
|
18
18
|
const path = require('path');
|
|
@@ -554,7 +554,7 @@ async function spawnAgent(agent, task, options = {}) {
|
|
|
554
554
|
SINAPSE_OUTPUT_DIR: opts.outputDir,
|
|
555
555
|
};
|
|
556
556
|
|
|
557
|
-
const result =
|
|
557
|
+
const result = execFileSync('bash', [scriptPath, ...args], {
|
|
558
558
|
encoding: 'utf8',
|
|
559
559
|
timeout: opts.timeout,
|
|
560
560
|
env,
|