avorelo 0.1.0 → 0.3.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/LICENSE +23 -16
- package/README.md +90 -51
- package/bin/avorelo.mjs +7 -0
- package/dist/avorelo.mjs +19741 -0
- package/package.json +135 -120
- package/bin/avorelo +0 -9
- package/scripts/README.md +0 -40
- package/scripts/cco-dashboard.js +0 -252
- package/scripts/cco-status.js +0 -430
- package/scripts/lib/activation/account-state.js +0 -37
- package/scripts/lib/activation/activation-runner.js +0 -546
- package/scripts/lib/activation/activation-self-healing.js +0 -480
- package/scripts/lib/activation/activation-state.js +0 -83
- package/scripts/lib/activation/activation-summary.js +0 -191
- package/scripts/lib/activation/adapters/claude-code.js +0 -77
- package/scripts/lib/activation/adapters/codex-cli.js +0 -52
- package/scripts/lib/activation/adapters/cursor.js +0 -37
- package/scripts/lib/activation/adapters/github-agent.js +0 -39
- package/scripts/lib/activation/adapters/terminal.js +0 -42
- package/scripts/lib/activation/adapters/vscode.js +0 -39
- package/scripts/lib/activation/adapters/windsurf.js +0 -37
- package/scripts/lib/activation/ai-surface-detector.js +0 -151
- package/scripts/lib/activation/connect-account.js +0 -145
- package/scripts/lib/activation/detect-environment.js +0 -75
- package/scripts/lib/activation/detect-hosts.js +0 -62
- package/scripts/lib/activation/format-activation-output.js +0 -109
- package/scripts/lib/activation/next-action.js +0 -43
- package/scripts/lib/activation/repair-engine.js +0 -219
- package/scripts/lib/activation-distribution-readiness.js +0 -507
- package/scripts/lib/adapter-conformance.js +0 -176
- package/scripts/lib/adapter-readiness.js +0 -417
- package/scripts/lib/adapter-safety-boundaries.js +0 -335
- package/scripts/lib/adapter-technical-readiness-gate.js +0 -205
- package/scripts/lib/agent-access-governance.js +0 -455
- package/scripts/lib/agent-enforcement.js +0 -765
- package/scripts/lib/agent-policy-profile.js +0 -210
- package/scripts/lib/agent-security/action-evaluator.js +0 -507
- package/scripts/lib/agent-security/adapter-registry.js +0 -98
- package/scripts/lib/agent-security/auto-policy.js +0 -139
- package/scripts/lib/agent-security/bounded-scan.js +0 -93
- package/scripts/lib/agent-security/enforcement-adapter.js +0 -174
- package/scripts/lib/agent-security/enforcement-engine.js +0 -1129
- package/scripts/lib/agent-security/file-write-adapter.js +0 -183
- package/scripts/lib/agent-security/file-write-rules.js +0 -178
- package/scripts/lib/agent-security/index.js +0 -3342
- package/scripts/lib/agent-security/instruction-risk.js +0 -181
- package/scripts/lib/agent-security/mcp-action-adapter.js +0 -185
- package/scripts/lib/agent-security/mcp-action-rules.js +0 -184
- package/scripts/lib/agent-security/package-action-adapter.js +0 -175
- package/scripts/lib/agent-security/package-action-rules.js +0 -233
- package/scripts/lib/agent-security/performance.js +0 -148
- package/scripts/lib/agent-security/permission-minimizer.js +0 -403
- package/scripts/lib/agent-security/scan-cache.js +0 -74
- package/scripts/lib/agent-security/source-trust.js +0 -146
- package/scripts/lib/ai-install-prompt.js +0 -288
- package/scripts/lib/ai-workspace-hygiene.js +0 -1499
- package/scripts/lib/alpha-activation.js +0 -520
- package/scripts/lib/alpha-feedback.js +0 -263
- package/scripts/lib/alpha-readiness-gate.js +0 -332
- package/scripts/lib/anti-gaming.js +0 -169
- package/scripts/lib/artifact-health.js +0 -431
- package/scripts/lib/attribution.js +0 -180
- package/scripts/lib/audit.js +0 -289
- package/scripts/lib/avorelo-skill-registry.js +0 -810
- package/scripts/lib/batch-jobs.js +0 -71
- package/scripts/lib/brain-pack.js +0 -578
- package/scripts/lib/brand-boundary.js +0 -424
- package/scripts/lib/brand.js +0 -74
- package/scripts/lib/browser-capability.js +0 -1048
- package/scripts/lib/browser-proof-preflight.js +0 -321
- package/scripts/lib/cache-readiness.js +0 -187
- package/scripts/lib/canonical-reentry.js +0 -162
- package/scripts/lib/capability-packs.js +0 -314
- package/scripts/lib/capability-recommender.js +0 -512
- package/scripts/lib/capability-registry.js +0 -1059
- package/scripts/lib/carry-forward-surfacing.js +0 -194
- package/scripts/lib/ccusage-adapter.js +0 -188
- package/scripts/lib/company-loop.js +0 -1149
- package/scripts/lib/config.js +0 -637
- package/scripts/lib/context-acquisition-plan.js +0 -287
- package/scripts/lib/context-budget-guard.js +0 -170
- package/scripts/lib/context-budget-scanner.js +0 -257
- package/scripts/lib/context-optimizer.js +0 -715
- package/scripts/lib/context-reduction-plan.js +0 -178
- package/scripts/lib/context-safety.js +0 -88
- package/scripts/lib/context-savings-engine.js +0 -158
- package/scripts/lib/cost-evidence.js +0 -254
- package/scripts/lib/cross-host-install-plan.js +0 -308
- package/scripts/lib/cross-host-install-readiness.js +0 -237
- package/scripts/lib/cross-host-value-flow.js +0 -268
- package/scripts/lib/dashboard.js +0 -900
- package/scripts/lib/design-partner-feedback.js +0 -346
- package/scripts/lib/entitlements.js +0 -100
- package/scripts/lib/execution-packet.js +0 -559
- package/scripts/lib/experimentation-events.js +0 -547
- package/scripts/lib/external-capability-compliance.js +0 -107
- package/scripts/lib/external-user-simulation.js +0 -166
- package/scripts/lib/failure-recovery-readiness.js +0 -81
- package/scripts/lib/failure-recovery.js +0 -419
- package/scripts/lib/feedback-intelligence.js +0 -537
- package/scripts/lib/feedback-signals.js +0 -205
- package/scripts/lib/file-integrity.js +0 -68
- package/scripts/lib/fsx.js +0 -127
- package/scripts/lib/full-readiness-gate.js +0 -451
- package/scripts/lib/guidance-builder.js +0 -174
- package/scripts/lib/hook-apply.js +0 -1019
- package/scripts/lib/hook-baseline.js +0 -310
- package/scripts/lib/hook-config-preview.js +0 -275
- package/scripts/lib/hook-contracts.js +0 -290
- package/scripts/lib/hook-safety-boundary-readiness.js +0 -80
- package/scripts/lib/host-capability-matrix.js +0 -351
- package/scripts/lib/host-support-context.js +0 -254
- package/scripts/lib/http-hook-action.js +0 -538
- package/scripts/lib/install-ai-readiness.js +0 -84
- package/scripts/lib/install-intake-risk.js +0 -1037
- package/scripts/lib/install-journey-intelligence.js +0 -329
- package/scripts/lib/intervention-guidance.js +0 -57
- package/scripts/lib/known-limitations.js +0 -115
- package/scripts/lib/l8-path-truth.js +0 -146
- package/scripts/lib/launch-hardening-gate.js +0 -436
- package/scripts/lib/launch-readiness.js +0 -628
- package/scripts/lib/learning-memory.js +0 -686
- package/scripts/lib/lifecycle-hooks.js +0 -802
- package/scripts/lib/local-package-smoke.js +0 -423
- package/scripts/lib/local-pricing.js +0 -299
- package/scripts/lib/mcp-enforcement.js +0 -311
- package/scripts/lib/mcp-least-privilege-policy.js +0 -303
- package/scripts/lib/mcp-tool-inventory.js +0 -388
- package/scripts/lib/mcp-tool-risk.js +0 -0
- package/scripts/lib/memory.js +0 -335
- package/scripts/lib/metrics.js +0 -699
- package/scripts/lib/micro-proof.js +0 -133
- package/scripts/lib/next-run-context.js +0 -436
- package/scripts/lib/operating-value.js +0 -1648
- package/scripts/lib/optimization-v3.js +0 -122
- package/scripts/lib/orchestration/adapters/_shared.js +0 -49
- package/scripts/lib/orchestration/adapters/aider.js +0 -18
- package/scripts/lib/orchestration/adapters/claude-code.js +0 -35
- package/scripts/lib/orchestration/adapters/codex.js +0 -35
- package/scripts/lib/orchestration/adapters/gemini-cli.js +0 -18
- package/scripts/lib/orchestration/adapters/git.js +0 -25
- package/scripts/lib/orchestration/adapters/index.js +0 -31
- package/scripts/lib/orchestration/adapters/lm-studio.js +0 -18
- package/scripts/lib/orchestration/adapters/ollama.js +0 -18
- package/scripts/lib/orchestration/adapters/opencode.js +0 -18
- package/scripts/lib/orchestration/adapters/openrouter.js +0 -18
- package/scripts/lib/orchestration/adapters/test-runner.js +0 -25
- package/scripts/lib/orchestration/cli.js +0 -438
- package/scripts/lib/orchestration/execution-manager.js +0 -279
- package/scripts/lib/orchestration/handoff.js +0 -314
- package/scripts/lib/orchestration/index.js +0 -456
- package/scripts/lib/orchestration/inventory.js +0 -47
- package/scripts/lib/orchestration/model-discovery.js +0 -498
- package/scripts/lib/orchestration/model-profiler.js +0 -170
- package/scripts/lib/orchestration/model-profiles.js +0 -252
- package/scripts/lib/orchestration/model-refresh-policy.js +0 -72
- package/scripts/lib/orchestration/proof-writer.js +0 -349
- package/scripts/lib/orchestration/provider-discovery/aider.js +0 -49
- package/scripts/lib/orchestration/provider-discovery/claude-code.js +0 -56
- package/scripts/lib/orchestration/provider-discovery/codex.js +0 -49
- package/scripts/lib/orchestration/provider-discovery/common.js +0 -186
- package/scripts/lib/orchestration/provider-discovery/gemini.js +0 -106
- package/scripts/lib/orchestration/provider-discovery/lm-studio.js +0 -118
- package/scripts/lib/orchestration/provider-discovery/models-dev.js +0 -12
- package/scripts/lib/orchestration/provider-discovery/ollama.js +0 -100
- package/scripts/lib/orchestration/provider-discovery/opencode.js +0 -47
- package/scripts/lib/orchestration/provider-discovery/openrouter.js +0 -44
- package/scripts/lib/orchestration/risk-classifier.js +0 -130
- package/scripts/lib/orchestration/routing-policy.js +0 -486
- package/scripts/lib/orchestration/settings.js +0 -112
- package/scripts/lib/orchestration/state.js +0 -165
- package/scripts/lib/orchestration/verification-manager.js +0 -138
- package/scripts/lib/output-profiles.js +0 -146
- package/scripts/lib/package-content-audit.js +0 -368
- package/scripts/lib/package-runtime.js +0 -278
- package/scripts/lib/plan-surface.js +0 -53
- package/scripts/lib/plans.js +0 -2318
- package/scripts/lib/policy-provider.js +0 -27
- package/scripts/lib/prelaunch-activation-readiness.js +0 -409
- package/scripts/lib/prelaunch-evidence-store.js +0 -816
- package/scripts/lib/prelaunch-intelligence.js +0 -869
- package/scripts/lib/pricing-experiment.js +0 -118
- package/scripts/lib/pro-moment-events.js +0 -77
- package/scripts/lib/pro-moment-state.js +0 -227
- package/scripts/lib/pro-moments.js +0 -1216
- package/scripts/lib/product-learning-events.js +0 -629
- package/scripts/lib/project-profile.js +0 -555
- package/scripts/lib/prompt-compiler.js +0 -280
- package/scripts/lib/prompt-lint.js +0 -32
- package/scripts/lib/prompt-suggestions.js +0 -52
- package/scripts/lib/proof-canonical.js +0 -398
- package/scripts/lib/proof-drilldown.js +0 -383
- package/scripts/lib/proof-events.js +0 -342
- package/scripts/lib/proof-history.js +0 -243
- package/scripts/lib/proof-metrics.js +0 -296
- package/scripts/lib/proof-outcome-evidence.js +0 -134
- package/scripts/lib/proof-receipt.js +0 -335
- package/scripts/lib/proof-record.js +0 -461
- package/scripts/lib/public-activation-distribution-gate.js +0 -258
- package/scripts/lib/public-cli.js +0 -3891
- package/scripts/lib/public-distribution-truth.js +0 -211
- package/scripts/lib/public-install-claim-checker.js +0 -294
- package/scripts/lib/publish-provenance-readiness.js +0 -283
- package/scripts/lib/readiness-delta.js +0 -218
- package/scripts/lib/readiness-evidence-closure.js +0 -196
- package/scripts/lib/reentry-memory-capture.js +0 -241
- package/scripts/lib/reentry-memory-retrieval.js +0 -302
- package/scripts/lib/reentry-memory-status.js +0 -146
- package/scripts/lib/reentry-memory-store.js +0 -178
- package/scripts/lib/reentry-state.js +0 -66
- package/scripts/lib/release-candidate-bundle.js +0 -166
- package/scripts/lib/remediation.js +0 -81
- package/scripts/lib/repo-map.js +0 -391
- package/scripts/lib/run-improvements-lifecycle.js +0 -330
- package/scripts/lib/run-improvements.js +0 -789
- package/scripts/lib/runtime-decision-policy.js +0 -387
- package/scripts/lib/safe-path-engine.js +0 -705
- package/scripts/lib/safe-run-controller.js +0 -887
- package/scripts/lib/score.js +0 -262
- package/scripts/lib/seamless-enforcement.js +0 -329
- package/scripts/lib/seamless-outcome.js +0 -689
- package/scripts/lib/seamless-reality-gate.js +0 -5043
- package/scripts/lib/security-risk-classifier.js +0 -511
- package/scripts/lib/security-scan.js +0 -384
- package/scripts/lib/session-context-optimizer.js +0 -1211
- package/scripts/lib/session-timing.js +0 -315
- package/scripts/lib/skill-hygiene.js +0 -805
- package/scripts/lib/skill-packs.js +0 -161
- package/scripts/lib/skills-operating-layer.js +0 -580
- package/scripts/lib/smart-work-routing.js +0 -768
- package/scripts/lib/source-catalog.js +0 -700
- package/scripts/lib/status-value-summary.js +0 -32
- package/scripts/lib/support-bundle.js +0 -578
- package/scripts/lib/task-continuation.js +0 -440
- package/scripts/lib/test-helpers.js +0 -15
- package/scripts/lib/tier.js +0 -38
- package/scripts/lib/token-context-quality-gate.js +0 -370
- package/scripts/lib/token-cost-capture.js +0 -187
- package/scripts/lib/token-cost-intelligence.js +0 -358
- package/scripts/lib/token-efficiency-evidence.js +0 -213
- package/scripts/lib/token-evidence.js +0 -699
- package/scripts/lib/tokenish.js +0 -17
- package/scripts/lib/tool-output-sandbox.js +0 -304
- package/scripts/lib/trust-audit.js +0 -136
- package/scripts/lib/unified-events.js +0 -396
- package/scripts/lib/upgrade-interruption-recovery.js +0 -407
- package/scripts/lib/usage-ledger.js +0 -201
- package/scripts/lib/value-ledger.js +0 -130
- package/scripts/lib/value-proof-calibration.js +0 -531
- package/scripts/lib/visual-qa.js +0 -231
- package/scripts/lib/voice-alpha.js +0 -29
- package/scripts/lib/work-aware-orchestration.js +0 -976
- package/scripts/lib/work-control-receipts.js +0 -577
- package/scripts/lib/work-ledger.js +0 -1123
- package/scripts/lib/work-panel-preview.js +0 -352
- package/scripts/lib/workflow-discipline.js +0 -280
- package/scripts/lib/workflow-signals.js +0 -419
- package/scripts/lib/workspace-map.js +0 -281
- package/scripts/lib/workspace-registry.js +0 -1367
- package/scripts/lib/workspace-resolver.js +0 -480
|
@@ -1,547 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const { nowIso } = require("./fsx");
|
|
4
|
-
const {
|
|
5
|
-
appendProductLearningEvent,
|
|
6
|
-
redactPayload,
|
|
7
|
-
redactString,
|
|
8
|
-
sha256,
|
|
9
|
-
validateProductLearningEvent,
|
|
10
|
-
} = require("./product-learning-events");
|
|
11
|
-
|
|
12
|
-
const EXPERIMENTATION_EVENT_GROUPS = Object.freeze({
|
|
13
|
-
experiment: Object.freeze([
|
|
14
|
-
"experiment_assigned",
|
|
15
|
-
"experiment_exposed",
|
|
16
|
-
"experiment_variant_rendered",
|
|
17
|
-
"experiment_goal_completed",
|
|
18
|
-
"experiment_guardrail_triggered",
|
|
19
|
-
"experiment_result_reviewed",
|
|
20
|
-
"experiment_decision_made",
|
|
21
|
-
]),
|
|
22
|
-
website: Object.freeze([
|
|
23
|
-
"page_viewed",
|
|
24
|
-
"hero_viewed",
|
|
25
|
-
"hero_cta_clicked",
|
|
26
|
-
"secondary_cta_clicked",
|
|
27
|
-
"install_command_copied",
|
|
28
|
-
"docs_clicked",
|
|
29
|
-
"demo_started",
|
|
30
|
-
"demo_completed",
|
|
31
|
-
"teams_interest_clicked",
|
|
32
|
-
"faq_opened",
|
|
33
|
-
"security_section_viewed",
|
|
34
|
-
"value_section_viewed",
|
|
35
|
-
"trust_page_viewed",
|
|
36
|
-
]),
|
|
37
|
-
comprehension: Object.freeze([
|
|
38
|
-
"comprehension_survey_shown",
|
|
39
|
-
"comprehension_survey_answered",
|
|
40
|
-
"message_recall_answered",
|
|
41
|
-
"objection_selected",
|
|
42
|
-
"confusion_signal_detected",
|
|
43
|
-
]),
|
|
44
|
-
activation: Object.freeze([
|
|
45
|
-
"activation_started",
|
|
46
|
-
"activation_completed",
|
|
47
|
-
"activation_failed",
|
|
48
|
-
"activation_safe_repair_attempted",
|
|
49
|
-
"activation_safe_repair_completed",
|
|
50
|
-
"activation_next_action_shown",
|
|
51
|
-
"activation_account_skipped",
|
|
52
|
-
"activation_account_connected",
|
|
53
|
-
"first_value_shown",
|
|
54
|
-
"first_value_acknowledged",
|
|
55
|
-
]),
|
|
56
|
-
product_value: Object.freeze([
|
|
57
|
-
"prompt_shaped",
|
|
58
|
-
"context_pack_created",
|
|
59
|
-
"context_reduction_applied",
|
|
60
|
-
"workspace_map_created",
|
|
61
|
-
"workspace_map_used",
|
|
62
|
-
"skill_risk_scan_completed",
|
|
63
|
-
"risky_instruction_detected",
|
|
64
|
-
"guard_decision_made",
|
|
65
|
-
"unsafe_action_blocked",
|
|
66
|
-
"safe_path_suggested",
|
|
67
|
-
"safe_path_applied",
|
|
68
|
-
"route_recommended",
|
|
69
|
-
"route_applied",
|
|
70
|
-
"proof_generated",
|
|
71
|
-
"handoff_created",
|
|
72
|
-
"reentry_used",
|
|
73
|
-
"proof_history_requested",
|
|
74
|
-
"proof_export_requested",
|
|
75
|
-
"visual_qa_started",
|
|
76
|
-
"visual_qa_completed",
|
|
77
|
-
"visual_qa_finding_detected",
|
|
78
|
-
]),
|
|
79
|
-
pricing_pro_intent: Object.freeze([
|
|
80
|
-
"pricing_viewed",
|
|
81
|
-
"pricing_plan_clicked",
|
|
82
|
-
"free_plan_clicked",
|
|
83
|
-
"pro_plan_clicked",
|
|
84
|
-
"pro_feature_requested",
|
|
85
|
-
"pro_limit_reached",
|
|
86
|
-
"upgrade_page_viewed",
|
|
87
|
-
"checkout_started",
|
|
88
|
-
"checkout_abandoned",
|
|
89
|
-
"upgrade_completed",
|
|
90
|
-
]),
|
|
91
|
-
trust_annoyance: Object.freeze([
|
|
92
|
-
"pricing_confusion_detected",
|
|
93
|
-
"trust_faq_opened",
|
|
94
|
-
"security_concern_clicked",
|
|
95
|
-
"feedback_negative_submitted",
|
|
96
|
-
"disable_avorelo_started",
|
|
97
|
-
"uninstall_started",
|
|
98
|
-
"pro_nudge_dismissed",
|
|
99
|
-
"pro_nudge_suppressed",
|
|
100
|
-
]),
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const EXPERIMENTATION_REQUIRED_EVENTS = Object.freeze([
|
|
104
|
-
"experiment_assigned",
|
|
105
|
-
"experiment_exposed",
|
|
106
|
-
"hero_cta_clicked",
|
|
107
|
-
"install_command_copied",
|
|
108
|
-
"pricing_viewed",
|
|
109
|
-
"activation_started",
|
|
110
|
-
"activation_completed",
|
|
111
|
-
"first_value_shown",
|
|
112
|
-
"comprehension_survey_answered",
|
|
113
|
-
]);
|
|
114
|
-
|
|
115
|
-
const EXPERIMENTATION_EVENT_REGISTRY = Object.freeze(
|
|
116
|
-
Object.entries(EXPERIMENTATION_EVENT_GROUPS)
|
|
117
|
-
.flatMap(([group, eventNames]) => eventNames.map((eventName) => [eventName, Object.freeze({
|
|
118
|
-
eventName,
|
|
119
|
-
group,
|
|
120
|
-
category: group,
|
|
121
|
-
})]))
|
|
122
|
-
.reduce((acc, [eventName, definition]) => {
|
|
123
|
-
acc[eventName] = definition;
|
|
124
|
-
return acc;
|
|
125
|
-
}, {})
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
const EXPERIMENTATION_SOURCE_KEYS = Object.freeze([
|
|
129
|
-
"utm_source",
|
|
130
|
-
"utm_campaign",
|
|
131
|
-
"utm_medium",
|
|
132
|
-
"utm_term",
|
|
133
|
-
"utm_content",
|
|
134
|
-
"referrer",
|
|
135
|
-
]);
|
|
136
|
-
|
|
137
|
-
const EXPERIMENTATION_METADATA_KEYS = Object.freeze([
|
|
138
|
-
"experimentId",
|
|
139
|
-
"variantId",
|
|
140
|
-
"heroVariant",
|
|
141
|
-
"pricingVariant",
|
|
142
|
-
"securityVariant",
|
|
143
|
-
"demoVisualVariant",
|
|
144
|
-
"ctaVariant",
|
|
145
|
-
"assignmentSource",
|
|
146
|
-
]);
|
|
147
|
-
|
|
148
|
-
const SAFE_TOP_LEVEL_FIELDS = new Set([
|
|
149
|
-
"anonymousId",
|
|
150
|
-
"accountId",
|
|
151
|
-
"projectId",
|
|
152
|
-
"localRunId",
|
|
153
|
-
"surface",
|
|
154
|
-
"source",
|
|
155
|
-
"experiment",
|
|
156
|
-
"properties",
|
|
157
|
-
"timestamp",
|
|
158
|
-
"occurredAt",
|
|
159
|
-
"status",
|
|
160
|
-
]);
|
|
161
|
-
|
|
162
|
-
const SAFE_LABEL_RE = /^[A-Za-z0-9][A-Za-z0-9 _.:/-]{0,119}$/;
|
|
163
|
-
const SAFE_CODE_RE = /^[A-Za-z0-9_.:-]{1,120}$/;
|
|
164
|
-
const WINDOWS_PATH_RE = /[A-Za-z]:[\\/](?:[^\\/\r\n\t]+[\\/])*[^\\/\r\n\t]*/;
|
|
165
|
-
const UNIX_PATH_RE = /(?:^|[\s(])\/(?:Users|home|mnt|var|tmp|etc|opt|srv|usr|repos?|workspace|workspaces|projects?|app|src|tests|scripts|docs|vendor|artifacts|bin|node_modules)(?:\/[^\s)]+)+/;
|
|
166
|
-
const REPO_PATH_RE = /(?:^|[\s(])(?:src|scripts|tests|docs|apps|vendor|artifacts|bin|package\.json|AGENTS\.md|\.claude)(?:[\\/][^\s)]+)*/i;
|
|
167
|
-
const ENV_PATH_RE = /(?:^|[\s(])(?:[A-Za-z]:[\\/])?[^"'`\r\n]*\.env(?:\.[A-Za-z0-9_-]+)?(?:$|[\s)])/i;
|
|
168
|
-
const URL_RE = /^https?:\/\/[^/\s?#]+/i;
|
|
169
|
-
const SECRET_RE = /sk-[A-Za-z0-9]{16,}|ghp_[A-Za-z0-9]{20,}|AKIA[0-9A-Z]{16}|(?:api[_ -]?key|token|password|secret|authorization)\s*[:=]\s*[^\s'"]+/i;
|
|
170
|
-
const FREE_TEXT_KEY_RE = /(answer|message|text|notes|recall|objection|feedback|comment|response|transcript|prompt|code|content|body)/i;
|
|
171
|
-
const COMMAND_OUTPUT_KEY_RE = /(stdout|stderr|output|stack|trace|terminal|console|command)/i;
|
|
172
|
-
|
|
173
|
-
function isRawContentKey(key) {
|
|
174
|
-
const lowerKey = String(key || "").toLowerCase();
|
|
175
|
-
if (!lowerKey) return false;
|
|
176
|
-
if (lowerKey.startsWith("raw")) return true;
|
|
177
|
-
if (lowerKey === "prompt" || lowerKey.startsWith("prompt") || lowerKey.endsWith("prompt")) return true;
|
|
178
|
-
if (lowerKey === "code" || lowerKey.startsWith("code") || lowerKey.endsWith("code")) return true;
|
|
179
|
-
if (lowerKey.includes("secret") || lowerKey.includes("token") || lowerKey.includes("credential")) return true;
|
|
180
|
-
if (lowerKey.includes("apikey") || lowerKey.includes("api_key") || lowerKey.includes("api-key")) return true;
|
|
181
|
-
return false;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function isExperimentationEventName(eventName) {
|
|
185
|
-
return Boolean(EXPERIMENTATION_EVENT_REGISTRY[eventName]);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function listExperimentationEventNames() {
|
|
189
|
-
return Object.keys(EXPERIMENTATION_EVENT_REGISTRY).sort();
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function getExperimentationEventDefinition(eventName) {
|
|
193
|
-
return EXPERIMENTATION_EVENT_REGISTRY[eventName] || null;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function normalizeSafeCode(value) {
|
|
197
|
-
const text = String(value || "").trim();
|
|
198
|
-
if (!text) return null;
|
|
199
|
-
if (SAFE_CODE_RE.test(text)) return text;
|
|
200
|
-
return sha256(text);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
function normalizeSafeLabel(value) {
|
|
204
|
-
const text = String(value || "").trim();
|
|
205
|
-
if (!text) return null;
|
|
206
|
-
if (SAFE_LABEL_RE.test(text) && !looksPathLikeString(text)) {
|
|
207
|
-
return redactString(text).slice(0, 120);
|
|
208
|
-
}
|
|
209
|
-
return sha256(text);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function normalizeReferrer(value) {
|
|
213
|
-
const text = String(value || "").trim();
|
|
214
|
-
if (!text) return null;
|
|
215
|
-
if (URL_RE.test(text)) {
|
|
216
|
-
try {
|
|
217
|
-
const url = new URL(text);
|
|
218
|
-
return url.origin;
|
|
219
|
-
} catch {
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
return normalizeSafeLabel(text);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function hashIdentifier(value) {
|
|
227
|
-
const text = String(value || "").trim();
|
|
228
|
-
if (!text) return null;
|
|
229
|
-
return sha256(text);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function looksPathLikeString(value) {
|
|
233
|
-
const text = String(value || "");
|
|
234
|
-
if (!text || URL_RE.test(text)) return false;
|
|
235
|
-
return WINDOWS_PATH_RE.test(text)
|
|
236
|
-
|| UNIX_PATH_RE.test(text)
|
|
237
|
-
|| REPO_PATH_RE.test(text)
|
|
238
|
-
|| ENV_PATH_RE.test(text);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function looksLikeCommandOutput(value) {
|
|
242
|
-
const text = String(value || "");
|
|
243
|
-
if (!text) return false;
|
|
244
|
-
if (text.includes("\n")) {
|
|
245
|
-
return /error:|traceback|exception|^\s*at\s+|PS [A-Za-z]:\\|^\$ |npm ERR!/im.test(text);
|
|
246
|
-
}
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function hashAndMeasure(target, key, value) {
|
|
251
|
-
const raw = typeof value === "string" ? value : JSON.stringify(value);
|
|
252
|
-
target[`${key}Hash`] = sha256(raw);
|
|
253
|
-
target[`${key}Length`] = String(raw || "").length;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function sanitizeSource(source, flags) {
|
|
257
|
-
const sanitized = {};
|
|
258
|
-
const input = source && typeof source === "object" ? source : {};
|
|
259
|
-
for (const key of EXPERIMENTATION_SOURCE_KEYS) {
|
|
260
|
-
if (!Object.prototype.hasOwnProperty.call(input, key)) continue;
|
|
261
|
-
if (key === "referrer") {
|
|
262
|
-
sanitized.referrer = normalizeReferrer(input.referrer);
|
|
263
|
-
continue;
|
|
264
|
-
}
|
|
265
|
-
sanitized[key] = normalizeSafeLabel(input[key]);
|
|
266
|
-
}
|
|
267
|
-
return sanitized;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function sanitizeExperimentMetadata(experiment, flags) {
|
|
271
|
-
const sanitized = {};
|
|
272
|
-
const input = experiment && typeof experiment === "object" ? experiment : {};
|
|
273
|
-
for (const key of EXPERIMENTATION_METADATA_KEYS) {
|
|
274
|
-
if (!Object.prototype.hasOwnProperty.call(input, key)) continue;
|
|
275
|
-
sanitized[key] = normalizeSafeCode(input[key]);
|
|
276
|
-
}
|
|
277
|
-
return sanitized;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function sanitizeStringValue(target, key, value, flags) {
|
|
281
|
-
const text = String(value || "");
|
|
282
|
-
if (!text) {
|
|
283
|
-
target[key] = "";
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
if (isRawContentKey(key)) {
|
|
287
|
-
if (/prompt/i.test(key)) flags.containsPrompt = true;
|
|
288
|
-
if (/code/i.test(key)) flags.containsCode = true;
|
|
289
|
-
if (/secret|token|credential|apikey|api_key/i.test(key)) flags.containsSecret = true;
|
|
290
|
-
hashAndMeasure(target, key, text);
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
if (COMMAND_OUTPUT_KEY_RE.test(key) || looksLikeCommandOutput(text)) {
|
|
294
|
-
flags.containsSensitivePath = flags.containsSensitivePath || looksPathLikeString(text);
|
|
295
|
-
hashAndMeasure(target, key, text);
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
if (looksPathLikeString(text)) {
|
|
299
|
-
flags.containsSensitivePath = true;
|
|
300
|
-
target[key] = "[redacted-path]";
|
|
301
|
-
target[`${key}Hash`] = sha256(text);
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
if (SECRET_RE.test(text)) {
|
|
305
|
-
flags.containsSecret = true;
|
|
306
|
-
target[key] = redactString(text).slice(0, 120);
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
if (FREE_TEXT_KEY_RE.test(key) || text.length > 160 || text.includes("\n")) {
|
|
310
|
-
hashAndMeasure(target, key, text);
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
target[key] = normalizeSafeLabel(text);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
function sanitizePropertiesValue(key, value, flags) {
|
|
317
|
-
if (value === null || value === undefined) return value ?? null;
|
|
318
|
-
if (typeof value === "number") {
|
|
319
|
-
return Number.isFinite(value) ? value : null;
|
|
320
|
-
}
|
|
321
|
-
if (typeof value === "boolean") {
|
|
322
|
-
return value;
|
|
323
|
-
}
|
|
324
|
-
if (Array.isArray(value)) {
|
|
325
|
-
return value.slice(0, 20).map((entry) => {
|
|
326
|
-
if (entry === null || entry === undefined) return null;
|
|
327
|
-
if (typeof entry === "number") return Number.isFinite(entry) ? entry : null;
|
|
328
|
-
if (typeof entry === "boolean") return entry;
|
|
329
|
-
if (typeof entry === "string") {
|
|
330
|
-
if (looksPathLikeString(entry)) {
|
|
331
|
-
flags.containsSensitivePath = true;
|
|
332
|
-
return "[redacted-path]";
|
|
333
|
-
}
|
|
334
|
-
if (SECRET_RE.test(entry)) {
|
|
335
|
-
flags.containsSecret = true;
|
|
336
|
-
return redactString(entry).slice(0, 120);
|
|
337
|
-
}
|
|
338
|
-
if (entry.length > 120 || entry.includes("\n")) {
|
|
339
|
-
return sha256(entry);
|
|
340
|
-
}
|
|
341
|
-
return normalizeSafeLabel(entry);
|
|
342
|
-
}
|
|
343
|
-
if (typeof entry === "object") {
|
|
344
|
-
return sanitizeProperties(entry, flags);
|
|
345
|
-
}
|
|
346
|
-
return null;
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
if (typeof value === "object") {
|
|
350
|
-
return sanitizeProperties(value, flags);
|
|
351
|
-
}
|
|
352
|
-
return null;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function sanitizeProperties(properties, flags) {
|
|
356
|
-
const sanitized = {};
|
|
357
|
-
const input = properties && typeof properties === "object" ? properties : {};
|
|
358
|
-
Object.keys(input).forEach((key) => {
|
|
359
|
-
const lowerKey = key.toLowerCase();
|
|
360
|
-
const value = input[key];
|
|
361
|
-
if (isRawContentKey(lowerKey)) {
|
|
362
|
-
if (/prompt/.test(lowerKey)) flags.containsPrompt = true;
|
|
363
|
-
if (/code/.test(lowerKey)) flags.containsCode = true;
|
|
364
|
-
if (/secret|token|credential|apikey|api_key/.test(lowerKey)) flags.containsSecret = true;
|
|
365
|
-
hashAndMeasure(sanitized, key, value);
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
if (lowerKey.includes("path") || lowerKey.includes("file")) {
|
|
369
|
-
flags.containsSensitivePath = true;
|
|
370
|
-
sanitized[key] = "[redacted-path]";
|
|
371
|
-
hashAndMeasure(sanitized, key, value);
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
if (COMMAND_OUTPUT_KEY_RE.test(lowerKey)) {
|
|
375
|
-
flags.containsSensitivePath = flags.containsSensitivePath || looksPathLikeString(value);
|
|
376
|
-
hashAndMeasure(sanitized, key, value);
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
if (typeof value === "string") {
|
|
380
|
-
const holder = {};
|
|
381
|
-
sanitizeStringValue(holder, key, value, flags);
|
|
382
|
-
if (Object.prototype.hasOwnProperty.call(holder, key)) {
|
|
383
|
-
sanitized[key] = holder[key];
|
|
384
|
-
}
|
|
385
|
-
Object.keys(holder)
|
|
386
|
-
.filter((holderKey) => holderKey !== key)
|
|
387
|
-
.forEach((holderKey) => {
|
|
388
|
-
sanitized[holderKey] = holder[holderKey];
|
|
389
|
-
});
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
sanitized[key] = sanitizePropertiesValue(key, value, flags);
|
|
393
|
-
});
|
|
394
|
-
return redactPayload(sanitized);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function sanitizeLearningPayload(input = {}) {
|
|
398
|
-
const flags = {
|
|
399
|
-
containsPrompt: false,
|
|
400
|
-
containsCode: false,
|
|
401
|
-
containsSecret: false,
|
|
402
|
-
containsSensitivePath: false,
|
|
403
|
-
};
|
|
404
|
-
|
|
405
|
-
const topLevelProperties = input.properties && typeof input.properties === "object"
|
|
406
|
-
? input.properties
|
|
407
|
-
: Object.keys(input)
|
|
408
|
-
.filter((key) => !SAFE_TOP_LEVEL_FIELDS.has(key))
|
|
409
|
-
.reduce((acc, key) => {
|
|
410
|
-
acc[key] = input[key];
|
|
411
|
-
return acc;
|
|
412
|
-
}, {});
|
|
413
|
-
|
|
414
|
-
return {
|
|
415
|
-
schemaVersion: 1,
|
|
416
|
-
anonymousIdHash: hashIdentifier(input.anonymousId),
|
|
417
|
-
accountIdHash: hashIdentifier(input.accountId),
|
|
418
|
-
projectIdHash: hashIdentifier(input.projectId),
|
|
419
|
-
localRunIdHash: hashIdentifier(input.localRunId),
|
|
420
|
-
surface: normalizeSafeCode(input.surface) || "local",
|
|
421
|
-
source: sanitizeSource(input.source, flags),
|
|
422
|
-
experiment: sanitizeExperimentMetadata(input.experiment, flags),
|
|
423
|
-
properties: sanitizeProperties(topLevelProperties, flags),
|
|
424
|
-
privacy: flags,
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
function buildLearningEvent(eventName, input = {}) {
|
|
429
|
-
const definition = getExperimentationEventDefinition(eventName);
|
|
430
|
-
const occurredAt = input.timestamp || input.occurredAt || nowIso();
|
|
431
|
-
const payload = sanitizeLearningPayload(input);
|
|
432
|
-
payload.timestamp = occurredAt;
|
|
433
|
-
return {
|
|
434
|
-
eventName,
|
|
435
|
-
category: definition ? definition.category : null,
|
|
436
|
-
occurredAt,
|
|
437
|
-
surface: payload.surface || "local",
|
|
438
|
-
status: input.status ? normalizeSafeCode(input.status) || "observed" : "observed",
|
|
439
|
-
payload,
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
function validateLearningEvent(event) {
|
|
444
|
-
const errors = [];
|
|
445
|
-
if (!event || typeof event !== "object") {
|
|
446
|
-
return { valid: false, errors: ["Event must be an object"] };
|
|
447
|
-
}
|
|
448
|
-
if (!isExperimentationEventName(event.eventName)) {
|
|
449
|
-
errors.push(`Unknown experimentation event: ${event.eventName}`);
|
|
450
|
-
}
|
|
451
|
-
const definition = getExperimentationEventDefinition(event.eventName);
|
|
452
|
-
if (definition && event.category !== definition.category) {
|
|
453
|
-
errors.push(`Event category mismatch for ${event.eventName}`);
|
|
454
|
-
}
|
|
455
|
-
const baseValidation = event.category
|
|
456
|
-
? validateProductLearningEvent(event)
|
|
457
|
-
: { valid: false, errors: ["Event category is required"] };
|
|
458
|
-
errors.push(...baseValidation.errors);
|
|
459
|
-
return { valid: errors.length === 0, errors };
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
function maybeThrowStrict(result, options = {}) {
|
|
463
|
-
if (options.strict && !result.ok) {
|
|
464
|
-
const error = new Error(result.errors.join("; "));
|
|
465
|
-
error.result = result;
|
|
466
|
-
throw error;
|
|
467
|
-
}
|
|
468
|
-
return result;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
function trackLearningEvent(cwd, eventName, input = {}, options = {}) {
|
|
472
|
-
const event = buildLearningEvent(eventName, input);
|
|
473
|
-
const validation = validateLearningEvent(event);
|
|
474
|
-
if (!validation.valid) {
|
|
475
|
-
return maybeThrowStrict({
|
|
476
|
-
ok: false,
|
|
477
|
-
errors: validation.errors,
|
|
478
|
-
event,
|
|
479
|
-
}, options);
|
|
480
|
-
}
|
|
481
|
-
const result = appendProductLearningEvent(cwd, event);
|
|
482
|
-
return maybeThrowStrict({
|
|
483
|
-
...result,
|
|
484
|
-
event: result.event || event,
|
|
485
|
-
}, options);
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
function trackExperimentEvent(cwd, eventName, input = {}, options = {}) {
|
|
489
|
-
const definition = getExperimentationEventDefinition(eventName);
|
|
490
|
-
if (!definition || definition.group !== "experiment") {
|
|
491
|
-
return maybeThrowStrict({
|
|
492
|
-
ok: false,
|
|
493
|
-
errors: [`${eventName} is not an experiment-group event`],
|
|
494
|
-
event: null,
|
|
495
|
-
}, options);
|
|
496
|
-
}
|
|
497
|
-
return trackLearningEvent(cwd, eventName, input, options);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
function validateExperimentationTaxonomy() {
|
|
501
|
-
const errors = [];
|
|
502
|
-
const seen = new Set();
|
|
503
|
-
Object.entries(EXPERIMENTATION_EVENT_GROUPS).forEach(([group, eventNames]) => {
|
|
504
|
-
if (!Array.isArray(eventNames) || eventNames.length === 0) {
|
|
505
|
-
errors.push(`Group ${group} is empty`);
|
|
506
|
-
return;
|
|
507
|
-
}
|
|
508
|
-
eventNames.forEach((eventName) => {
|
|
509
|
-
if (seen.has(eventName)) {
|
|
510
|
-
errors.push(`Duplicate event name: ${eventName}`);
|
|
511
|
-
}
|
|
512
|
-
seen.add(eventName);
|
|
513
|
-
const definition = getExperimentationEventDefinition(eventName);
|
|
514
|
-
if (!definition) {
|
|
515
|
-
errors.push(`Missing registry definition: ${eventName}`);
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
|
-
if (definition.group !== group) {
|
|
519
|
-
errors.push(`Registry group mismatch for ${eventName}`);
|
|
520
|
-
}
|
|
521
|
-
});
|
|
522
|
-
});
|
|
523
|
-
EXPERIMENTATION_REQUIRED_EVENTS.forEach((eventName) => {
|
|
524
|
-
if (!seen.has(eventName)) {
|
|
525
|
-
errors.push(`Missing required experimentation event: ${eventName}`);
|
|
526
|
-
}
|
|
527
|
-
});
|
|
528
|
-
return {
|
|
529
|
-
valid: errors.length === 0,
|
|
530
|
-
errors,
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
module.exports = {
|
|
535
|
-
EXPERIMENTATION_EVENT_GROUPS,
|
|
536
|
-
EXPERIMENTATION_EVENT_REGISTRY,
|
|
537
|
-
EXPERIMENTATION_REQUIRED_EVENTS,
|
|
538
|
-
isExperimentationEventName,
|
|
539
|
-
listExperimentationEventNames,
|
|
540
|
-
getExperimentationEventDefinition,
|
|
541
|
-
sanitizeLearningPayload,
|
|
542
|
-
buildLearningEvent,
|
|
543
|
-
validateLearningEvent,
|
|
544
|
-
validateExperimentationTaxonomy,
|
|
545
|
-
trackLearningEvent,
|
|
546
|
-
trackExperimentEvent,
|
|
547
|
-
};
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const { listSources } = require("./source-catalog");
|
|
4
|
-
|
|
5
|
-
function toComplianceEntry(source) {
|
|
6
|
-
return {
|
|
7
|
-
projectName: source.name,
|
|
8
|
-
sourceUrl: source.sourceUrl,
|
|
9
|
-
licenseUrl: source.licenseUrl || null,
|
|
10
|
-
license: source.license,
|
|
11
|
-
attributionRequired: Boolean(source.attributionRequired),
|
|
12
|
-
attributionText: source.attributionText || "",
|
|
13
|
-
noticeRequired: Boolean(source.noticeRequired),
|
|
14
|
-
bundledCode: false,
|
|
15
|
-
modifiedCode: false,
|
|
16
|
-
allowedUseMode: source.defaultUseMode,
|
|
17
|
-
reviewStatus: source.sourceReviewStatus,
|
|
18
|
-
lastReviewedAt: source.lastReviewedAt || null,
|
|
19
|
-
commercialUseMetadata: source.commercialUseMetadata || "",
|
|
20
|
-
complianceNotes: [
|
|
21
|
-
...(source.licenseNotes || []),
|
|
22
|
-
...(source.securityNotes || []),
|
|
23
|
-
...(source.knownRisks || []),
|
|
24
|
-
],
|
|
25
|
-
avorelo: {
|
|
26
|
-
integrationPattern: source.productDecision,
|
|
27
|
-
productNote: (source.adaptationCandidates || []).join(", ") || "reference only",
|
|
28
|
-
currentStatus: source.productDecision,
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function listCompliance() {
|
|
34
|
-
return listSources().map(toComplianceEntry);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const EXTERNAL_CAPABILITY_COMPLIANCE = Object.freeze(listCompliance());
|
|
38
|
-
const COMPLIANCE_MAP = new Map(EXTERNAL_CAPABILITY_COMPLIANCE.map((entry) => [entry.projectName, entry]));
|
|
39
|
-
|
|
40
|
-
const REQUIRED_COMPLIANCE_FIELDS = [
|
|
41
|
-
"projectName",
|
|
42
|
-
"license",
|
|
43
|
-
"attributionRequired",
|
|
44
|
-
"attributionText",
|
|
45
|
-
"noticeRequired",
|
|
46
|
-
"bundledCode",
|
|
47
|
-
"modifiedCode",
|
|
48
|
-
"allowedUseMode",
|
|
49
|
-
"reviewStatus",
|
|
50
|
-
"commercialUseMetadata",
|
|
51
|
-
"complianceNotes",
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
function validateComplianceEntry(entry) {
|
|
55
|
-
const errors = [];
|
|
56
|
-
for (const field of REQUIRED_COMPLIANCE_FIELDS) {
|
|
57
|
-
if (entry[field] === undefined || entry[field] === null) {
|
|
58
|
-
errors.push(`Missing required field: ${field}`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (entry.license === "unknown") {
|
|
62
|
-
if (entry.reviewStatus === "trusted") {
|
|
63
|
-
errors.push("Unknown license cannot have reviewStatus=trusted");
|
|
64
|
-
}
|
|
65
|
-
if (!["reference_only", "blocked"].includes(entry.allowedUseMode)) {
|
|
66
|
-
errors.push("Unknown license must have allowedUseMode=reference_only or blocked");
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (entry.reviewStatus === "unreviewed" && entry.allowedUseMode === "internal") {
|
|
70
|
-
errors.push("Unreviewed external capability cannot have allowedUseMode=internal");
|
|
71
|
-
}
|
|
72
|
-
if (entry.bundledCode === true) {
|
|
73
|
-
errors.push("bundledCode must remain false for external references in this PR");
|
|
74
|
-
}
|
|
75
|
-
if (entry.modifiedCode === true) {
|
|
76
|
-
errors.push("modifiedCode must remain false for external references in this PR");
|
|
77
|
-
}
|
|
78
|
-
return { valid: errors.length === 0, errors };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function validateAllCompliance() {
|
|
82
|
-
const errors = [];
|
|
83
|
-
for (const entry of EXTERNAL_CAPABILITY_COMPLIANCE) {
|
|
84
|
-
const result = validateComplianceEntry(entry);
|
|
85
|
-
result.errors.forEach((error) => errors.push(`[${entry.projectName}] ${error}`));
|
|
86
|
-
}
|
|
87
|
-
return { valid: errors.length === 0, errors };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function getCompliance(projectName) {
|
|
91
|
-
return COMPLIANCE_MAP.get(String(projectName || "").trim()) || null;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function isSafeToReference(projectName) {
|
|
95
|
-
const entry = getCompliance(projectName);
|
|
96
|
-
if (!entry) return false;
|
|
97
|
-
return entry.allowedUseMode === "reference_only" || entry.allowedUseMode === "adapted_internal";
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
module.exports = {
|
|
101
|
-
EXTERNAL_CAPABILITY_COMPLIANCE,
|
|
102
|
-
validateComplianceEntry,
|
|
103
|
-
validateAllCompliance,
|
|
104
|
-
getCompliance,
|
|
105
|
-
listCompliance,
|
|
106
|
-
isSafeToReference,
|
|
107
|
-
};
|