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
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SINAPSE Telemetry — STUB (opt-in, disabled by default)
|
|
5
|
+
* @story C.1 — Exit Codes, Auto-Doctor & Opt-in Telemetry
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT (contributors):
|
|
8
|
+
* This is a STUB implementation. It does NOT make real network requests.
|
|
9
|
+
* Calling `send(event)` when telemetry is enabled logs the payload at debug
|
|
10
|
+
* level and stops there.
|
|
11
|
+
*
|
|
12
|
+
* TODO(follow-up-story): wire a real HTTPS endpoint once the privacy policy
|
|
13
|
+
* at docs/TELEMETRY.md has been reviewed by legal and the endpoint URL is
|
|
14
|
+
* confirmed. Until then, NO real data leaves the user's machine.
|
|
15
|
+
*
|
|
16
|
+
* Contract (see Story C.1 ACs):
|
|
17
|
+
* AC 4 — Exported methods: enable(), disable(), isEnabled(), send(event).
|
|
18
|
+
* AC 5 — Disabled by default. `send()` is a no-op when disabled.
|
|
19
|
+
* AC 6 — `enable()` persists a flag to ~/.sinapse/config.json. CLI wrapper
|
|
20
|
+
* shows the confirmation message to the user.
|
|
21
|
+
* AC 7 — `SINAPSE_TELEMETRY=1` env var overrides the config file.
|
|
22
|
+
* AC 8 — Payload is anonymized: only { category, platform, version, timestamp }.
|
|
23
|
+
* NO user paths, NO usernames, NO file names, NO PII.
|
|
24
|
+
* AC 9 — send() logs at debug level only. No HTTP.
|
|
25
|
+
*
|
|
26
|
+
* Zero external deps (pure Node stdlib). Safe to require() anywhere.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
const fs = require('fs');
|
|
30
|
+
const os = require('os');
|
|
31
|
+
const path = require('path');
|
|
32
|
+
|
|
33
|
+
// ─── Config file location ────────────────────────────────────────────────────
|
|
34
|
+
// Stored under ~/.sinapse/config.json so it is per-user (not per-project) and
|
|
35
|
+
// does not pollute the project directory.
|
|
36
|
+
|
|
37
|
+
function sinapseHome() {
|
|
38
|
+
return path.join(os.homedir(), '.sinapse');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function configPath() {
|
|
42
|
+
return path.join(sinapseHome(), 'config.json');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ─── Predefined failure categories (AC 8) ────────────────────────────────────
|
|
46
|
+
// Adding a new category? Add it here AND in docs/TELEMETRY.md so the privacy
|
|
47
|
+
// policy stays in sync with the code.
|
|
48
|
+
|
|
49
|
+
const FAILURE_CATEGORIES = Object.freeze([
|
|
50
|
+
'doctor-fail',
|
|
51
|
+
'sync-ide-fail',
|
|
52
|
+
'permission-error',
|
|
53
|
+
'runtime-dir-fail',
|
|
54
|
+
'unknown',
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
// ─── Allowed platforms (AC 8) ────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
const ALLOWED_PLATFORMS = Object.freeze(['win32', 'darwin', 'linux']);
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Normalize process.platform to one of the allowed values. Any exotic platform
|
|
63
|
+
* (aix, freebsd, openbsd, sunos, ...) is coerced to 'linux' to avoid leaking a
|
|
64
|
+
* fingerprint. NEVER returns the raw platform string.
|
|
65
|
+
* @returns {'win32'|'darwin'|'linux'}
|
|
66
|
+
*/
|
|
67
|
+
function normalizePlatform() {
|
|
68
|
+
const p = process.platform;
|
|
69
|
+
if (p === 'win32' || p === 'darwin' || p === 'linux') return p;
|
|
70
|
+
return 'linux';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ─── Version reading ─────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
let _cachedVersion = null;
|
|
76
|
+
function readVersion() {
|
|
77
|
+
if (_cachedVersion) return _cachedVersion;
|
|
78
|
+
try {
|
|
79
|
+
const pkg = require(path.resolve(__dirname, '..', '..', '..', 'package.json'));
|
|
80
|
+
_cachedVersion = pkg && pkg.version ? String(pkg.version) : 'unknown';
|
|
81
|
+
} catch {
|
|
82
|
+
_cachedVersion = 'unknown';
|
|
83
|
+
}
|
|
84
|
+
return _cachedVersion;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ─── Config file read / write ────────────────────────────────────────────────
|
|
88
|
+
// All filesystem calls are fail-safe: a corrupt or missing config.json MUST
|
|
89
|
+
// NEVER crash the caller. Telemetry is best-effort.
|
|
90
|
+
|
|
91
|
+
function readConfig() {
|
|
92
|
+
try {
|
|
93
|
+
const p = configPath();
|
|
94
|
+
if (!fs.existsSync(p)) return {};
|
|
95
|
+
const raw = fs.readFileSync(p, 'utf8');
|
|
96
|
+
const parsed = JSON.parse(raw);
|
|
97
|
+
return (parsed && typeof parsed === 'object') ? parsed : {};
|
|
98
|
+
} catch {
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function writeConfig(cfg) {
|
|
104
|
+
try {
|
|
105
|
+
const home = sinapseHome();
|
|
106
|
+
if (!fs.existsSync(home)) {
|
|
107
|
+
fs.mkdirSync(home, { recursive: true });
|
|
108
|
+
}
|
|
109
|
+
fs.writeFileSync(configPath(), `${JSON.stringify(cfg, null, 2)}\n`, 'utf8');
|
|
110
|
+
return true;
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* AC 5 + AC 7 — Is telemetry currently enabled?
|
|
120
|
+
*
|
|
121
|
+
* Resolution order (highest priority first):
|
|
122
|
+
* 1. SINAPSE_TELEMETRY=1 env var → TRUE (overrides config file)
|
|
123
|
+
* 2. SINAPSE_TELEMETRY=0 env var → FALSE (explicit opt-out wins too)
|
|
124
|
+
* 3. ~/.sinapse/config.json { "telemetry": true|false }
|
|
125
|
+
* 4. Default → FALSE
|
|
126
|
+
*
|
|
127
|
+
* @returns {boolean}
|
|
128
|
+
*/
|
|
129
|
+
function isEnabled() {
|
|
130
|
+
const envVar = process.env.SINAPSE_TELEMETRY;
|
|
131
|
+
if (envVar === '1' || envVar === 'true') return true;
|
|
132
|
+
if (envVar === '0' || envVar === 'false') return false;
|
|
133
|
+
const cfg = readConfig();
|
|
134
|
+
return cfg.telemetry === true;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* AC 6 — Persist opt-in to config file. Returns true on success.
|
|
139
|
+
* Does NOT print any message (CLI layer owns the user-facing copy).
|
|
140
|
+
* @returns {boolean}
|
|
141
|
+
*/
|
|
142
|
+
function enable() {
|
|
143
|
+
const cfg = readConfig();
|
|
144
|
+
cfg.telemetry = true;
|
|
145
|
+
return writeConfig(cfg);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Persist opt-out to config file. Returns true on success.
|
|
150
|
+
* @returns {boolean}
|
|
151
|
+
*/
|
|
152
|
+
function disable() {
|
|
153
|
+
const cfg = readConfig();
|
|
154
|
+
cfg.telemetry = false;
|
|
155
|
+
return writeConfig(cfg);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* AC 8 — Build an anonymized payload from a category.
|
|
160
|
+
* Only { category, platform, version, timestamp } is included.
|
|
161
|
+
* Unknown categories are coerced to 'unknown' to prevent category-sprawl and
|
|
162
|
+
* to keep the schema predictable for the (future) real endpoint.
|
|
163
|
+
*
|
|
164
|
+
* @param {string} category
|
|
165
|
+
* @returns {{category:string,platform:'win32'|'darwin'|'linux',version:string,timestamp:string}}
|
|
166
|
+
*/
|
|
167
|
+
function buildPayload(category) {
|
|
168
|
+
const safeCategory = FAILURE_CATEGORIES.includes(category) ? category : 'unknown';
|
|
169
|
+
return {
|
|
170
|
+
category: safeCategory,
|
|
171
|
+
platform: normalizePlatform(),
|
|
172
|
+
version: readVersion(),
|
|
173
|
+
timestamp: new Date().toISOString(),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* AC 5 + AC 9 — Send a telemetry event.
|
|
179
|
+
*
|
|
180
|
+
* When disabled → no-op (no network call, no log).
|
|
181
|
+
* When enabled → build anonymized payload, log at debug level, and return it.
|
|
182
|
+
*
|
|
183
|
+
* NOTE: This stub does NOT make any HTTP request. A follow-up story will add
|
|
184
|
+
* the real endpoint after legal review of docs/TELEMETRY.md.
|
|
185
|
+
*
|
|
186
|
+
* @param {{category?: string}} event
|
|
187
|
+
* @param {{logger?: object}} [opts] — inject a logger for tests; defaults to
|
|
188
|
+
* the shared SINAPSE logger if available, otherwise console.
|
|
189
|
+
* @returns {null|object} the payload that would have been sent, or null if disabled
|
|
190
|
+
*/
|
|
191
|
+
function send(event = {}, opts = {}) {
|
|
192
|
+
if (!isEnabled()) return null;
|
|
193
|
+
const payload = buildPayload(event && event.category);
|
|
194
|
+
const logger = opts.logger || _getDefaultLogger();
|
|
195
|
+
try {
|
|
196
|
+
if (logger && typeof logger.debug === 'function') {
|
|
197
|
+
logger.debug('[telemetry stub]', JSON.stringify(payload));
|
|
198
|
+
}
|
|
199
|
+
} catch {
|
|
200
|
+
/* never throw from telemetry */
|
|
201
|
+
}
|
|
202
|
+
// TODO(follow-up-story): POST payload to real endpoint here.
|
|
203
|
+
return payload;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ─── Default logger resolution ──────────────────────────────────────────────
|
|
207
|
+
// Try the shared SINAPSE logger first (so telemetry respects --debug/--quiet),
|
|
208
|
+
// but fall back to a console shim if it's unavailable (e.g. during very early
|
|
209
|
+
// bootstrap or in isolated tests).
|
|
210
|
+
|
|
211
|
+
let _defaultLogger = null;
|
|
212
|
+
function _getDefaultLogger() {
|
|
213
|
+
if (_defaultLogger) return _defaultLogger;
|
|
214
|
+
try {
|
|
215
|
+
const { getLogger } = require('../logger');
|
|
216
|
+
_defaultLogger = getLogger();
|
|
217
|
+
} catch {
|
|
218
|
+
_defaultLogger = {
|
|
219
|
+
debug: (...args) => { try { console.debug(...args); } catch { /* ignore */ } },
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
return _defaultLogger;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Test helper — reset internal caches between tests. Not part of the public
|
|
226
|
+
// contract; do not use in production code.
|
|
227
|
+
function _reset() {
|
|
228
|
+
_cachedVersion = null;
|
|
229
|
+
_defaultLogger = null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
module.exports = {
|
|
233
|
+
// Public API (AC 4)
|
|
234
|
+
enable,
|
|
235
|
+
disable,
|
|
236
|
+
isEnabled,
|
|
237
|
+
send,
|
|
238
|
+
// Helpers exposed for tests + CLI command
|
|
239
|
+
buildPayload,
|
|
240
|
+
normalizePlatform,
|
|
241
|
+
readVersion,
|
|
242
|
+
configPath,
|
|
243
|
+
sinapseHome,
|
|
244
|
+
FAILURE_CATEGORIES,
|
|
245
|
+
ALLOWED_PLATFORMS,
|
|
246
|
+
_reset,
|
|
247
|
+
};
|