@scheduler-systems/gal-run 0.0.408 → 0.0.411
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/dist/index.cjs +1344 -10
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3970,7 +3970,7 @@ var cliVersion, defaultApiUrl, BUILD_CONSTANTS, constants_default;
|
|
|
3970
3970
|
var init_constants = __esm({
|
|
3971
3971
|
"src/constants.ts"() {
|
|
3972
3972
|
"use strict";
|
|
3973
|
-
cliVersion = true ? "0.0.
|
|
3973
|
+
cliVersion = true ? "0.0.411" : "0.0.0-dev";
|
|
3974
3974
|
defaultApiUrl = true ? "https://api.gal.run" : "http://localhost:3000";
|
|
3975
3975
|
BUILD_CONSTANTS = Object.freeze([cliVersion, defaultApiUrl]);
|
|
3976
3976
|
constants_default = BUILD_CONSTANTS;
|
|
@@ -4880,7 +4880,7 @@ function detectEnvironment() {
|
|
|
4880
4880
|
return "dev";
|
|
4881
4881
|
}
|
|
4882
4882
|
try {
|
|
4883
|
-
const version2 = true ? "0.0.
|
|
4883
|
+
const version2 = true ? "0.0.411" : void 0;
|
|
4884
4884
|
if (version2 && version2.includes("-local")) {
|
|
4885
4885
|
return "dev";
|
|
4886
4886
|
}
|
|
@@ -5249,7 +5249,7 @@ function getId() {
|
|
|
5249
5249
|
}
|
|
5250
5250
|
function getCliVersion() {
|
|
5251
5251
|
try {
|
|
5252
|
-
return true ? "0.0.
|
|
5252
|
+
return true ? "0.0.411" : "0.0.0-dev";
|
|
5253
5253
|
} catch {
|
|
5254
5254
|
return "0.0.0-dev";
|
|
5255
5255
|
}
|
|
@@ -5663,9 +5663,38 @@ var init_llm_analysis = __esm({
|
|
|
5663
5663
|
});
|
|
5664
5664
|
|
|
5665
5665
|
// ../../packages/types/dist/feature-flags.js
|
|
5666
|
+
var ALL_PAGE_IDS;
|
|
5666
5667
|
var init_feature_flags = __esm({
|
|
5667
5668
|
"../../packages/types/dist/feature-flags.js"() {
|
|
5668
5669
|
"use strict";
|
|
5670
|
+
ALL_PAGE_IDS = [
|
|
5671
|
+
"dashboard",
|
|
5672
|
+
"discovery",
|
|
5673
|
+
"proposals",
|
|
5674
|
+
"team",
|
|
5675
|
+
"background-agents",
|
|
5676
|
+
"cli",
|
|
5677
|
+
"vscode",
|
|
5678
|
+
"docs",
|
|
5679
|
+
"billing",
|
|
5680
|
+
"settings",
|
|
5681
|
+
"workflow-testing",
|
|
5682
|
+
"project-scope-configs",
|
|
5683
|
+
"enforcement-overrides",
|
|
5684
|
+
"domain-compliance",
|
|
5685
|
+
"tool-compliance",
|
|
5686
|
+
"audit-logs",
|
|
5687
|
+
"enforcement-policies",
|
|
5688
|
+
"enforcement-compliance",
|
|
5689
|
+
"enforcement-audit",
|
|
5690
|
+
"enforcement-domains",
|
|
5691
|
+
"enforcement-hooks",
|
|
5692
|
+
"enforcement-sdlc",
|
|
5693
|
+
"enforcement-security",
|
|
5694
|
+
"enforcement-tools",
|
|
5695
|
+
"enforcement-system",
|
|
5696
|
+
"browser-profiles"
|
|
5697
|
+
];
|
|
5669
5698
|
}
|
|
5670
5699
|
});
|
|
5671
5700
|
|
|
@@ -5677,6 +5706,49 @@ var init_billing = __esm({
|
|
|
5677
5706
|
});
|
|
5678
5707
|
|
|
5679
5708
|
// ../../packages/types/dist/telemetry.js
|
|
5709
|
+
function isEnhancedEvent(event) {
|
|
5710
|
+
return "resource" in event && "severity" in event;
|
|
5711
|
+
}
|
|
5712
|
+
function upgradeToEnhancedEvent(legacy) {
|
|
5713
|
+
return {
|
|
5714
|
+
id: legacy.id,
|
|
5715
|
+
timestamp: legacy.timestamp,
|
|
5716
|
+
severity: legacy.payload.success === false ? "ERROR" : "INFO",
|
|
5717
|
+
resource: {
|
|
5718
|
+
"service.name": "gal-cli",
|
|
5719
|
+
"service.version": legacy.payload.cliVersion || "unknown",
|
|
5720
|
+
"host.os": legacy.payload.platform || "linux",
|
|
5721
|
+
"host.arch": "x64",
|
|
5722
|
+
// Default, not available in legacy
|
|
5723
|
+
"process.runtime.version": legacy.payload.nodeVersion
|
|
5724
|
+
},
|
|
5725
|
+
eventType: legacy.eventType,
|
|
5726
|
+
attributes: {
|
|
5727
|
+
command: legacy.payload.command ?? null,
|
|
5728
|
+
success: legacy.payload.success ?? null,
|
|
5729
|
+
error_type: legacy.payload.errorType ?? null,
|
|
5730
|
+
duration_ms: legacy.payload.durationMs ?? null,
|
|
5731
|
+
notification_type: legacy.payload.notificationType ?? null,
|
|
5732
|
+
rate_limit_hit: legacy.payload.rateLimitHit ?? null,
|
|
5733
|
+
sync_age_hours: legacy.payload.syncAgeHours ?? null,
|
|
5734
|
+
files_synced: legacy.payload.filesTracked ?? null
|
|
5735
|
+
},
|
|
5736
|
+
installationId: legacy.installationId
|
|
5737
|
+
};
|
|
5738
|
+
}
|
|
5739
|
+
function severityToNumber(severity) {
|
|
5740
|
+
const levels = {
|
|
5741
|
+
DEBUG: 100,
|
|
5742
|
+
INFO: 200,
|
|
5743
|
+
NOTICE: 300,
|
|
5744
|
+
WARNING: 400,
|
|
5745
|
+
ERROR: 500,
|
|
5746
|
+
CRITICAL: 600,
|
|
5747
|
+
ALERT: 700,
|
|
5748
|
+
EMERGENCY: 800
|
|
5749
|
+
};
|
|
5750
|
+
return levels[severity];
|
|
5751
|
+
}
|
|
5680
5752
|
var init_telemetry2 = __esm({
|
|
5681
5753
|
"../../packages/types/dist/telemetry.js"() {
|
|
5682
5754
|
"use strict";
|
|
@@ -5729,16 +5801,27 @@ function normalizeBackgroundAgentRunnerLabel(value) {
|
|
|
5729
5801
|
return value;
|
|
5730
5802
|
return RETIRED_BACKGROUND_AGENT_RUNNER_LABELS[value];
|
|
5731
5803
|
}
|
|
5732
|
-
var ACTIVE_BACKGROUND_AGENT_RUNNER_LABELS, RETIRED_BACKGROUND_AGENT_RUNNER_LABELS, DEFAULT_RUNNER_LABEL;
|
|
5804
|
+
var SESSION_AGENTS, DEFAULT_SESSION_AGENT, ACTIVE_BACKGROUND_AGENT_RUNNER_LABELS, SECURITY_GATED_RUNNER_LABELS, RETIRED_BACKGROUND_AGENT_RUNNER_LABELS, DEFAULT_RUNNER_LABEL;
|
|
5733
5805
|
var init_session = __esm({
|
|
5734
5806
|
"../../packages/types/dist/session.js"() {
|
|
5735
5807
|
"use strict";
|
|
5808
|
+
SESSION_AGENTS = [
|
|
5809
|
+
{ id: "claude", displayName: "Claude Code", icon: "\u{1F916}", description: "Anthropic Claude Code CLI" },
|
|
5810
|
+
{ id: "codex", displayName: "Codex CLI", icon: "\u{1F31F}", description: "OpenAI Codex CLI" },
|
|
5811
|
+
{ id: "gemini", displayName: "Gemini CLI", icon: "\u{1F48E}", description: "Google Gemini CLI" },
|
|
5812
|
+
{ id: "cursor-agent", displayName: "Cursor Agent", icon: "\u{1F3AF}", description: "Cursor AI Agent" },
|
|
5813
|
+
{ id: "copilot", displayName: "GitHub Copilot", icon: "\u{1F680}", description: "GitHub Copilot CLI" }
|
|
5814
|
+
];
|
|
5815
|
+
DEFAULT_SESSION_AGENT = "claude";
|
|
5736
5816
|
ACTIVE_BACKGROUND_AGENT_RUNNER_LABELS = [
|
|
5737
5817
|
"agents-standard-runc-x64",
|
|
5738
5818
|
"agents-medium-runc-x64",
|
|
5739
5819
|
"agents-high-runc-x64",
|
|
5740
5820
|
"agents-kali-runc"
|
|
5741
5821
|
];
|
|
5822
|
+
SECURITY_GATED_RUNNER_LABELS = /* @__PURE__ */ new Set([
|
|
5823
|
+
"agents-kali-runc"
|
|
5824
|
+
]);
|
|
5742
5825
|
RETIRED_BACKGROUND_AGENT_RUNNER_LABELS = {
|
|
5743
5826
|
"arc-linux-agents": "agents-standard-runc-x64",
|
|
5744
5827
|
"arc-linux-agents-runc": "agents-standard-runc-x64",
|
|
@@ -5761,9 +5844,198 @@ var init_workflow = __esm({
|
|
|
5761
5844
|
});
|
|
5762
5845
|
|
|
5763
5846
|
// ../../packages/types/dist/work-item.js
|
|
5847
|
+
function normalizeStringList(values) {
|
|
5848
|
+
if (!values)
|
|
5849
|
+
return values;
|
|
5850
|
+
const normalized = values.map((value) => typeof value === "string" ? value.trim() : "").filter((value) => value.length > 0);
|
|
5851
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
5852
|
+
}
|
|
5853
|
+
function isProcessExecutionMode(value) {
|
|
5854
|
+
return typeof value === "string" && PROCESS_EXECUTION_MODES.includes(value);
|
|
5855
|
+
}
|
|
5856
|
+
function normalizeOperationsProcessStep(raw) {
|
|
5857
|
+
if (!raw)
|
|
5858
|
+
return void 0;
|
|
5859
|
+
const executionPath = typeof raw.executionPath === "string" ? raw.executionPath.trim() : raw.executionPath;
|
|
5860
|
+
const result = {
|
|
5861
|
+
...raw,
|
|
5862
|
+
processKey: String(raw.processKey ?? "").trim(),
|
|
5863
|
+
title: String(raw.title ?? "").trim(),
|
|
5864
|
+
executionPath
|
|
5865
|
+
};
|
|
5866
|
+
if (raw.updatedBy) {
|
|
5867
|
+
result.updatedBy = raw.updatedBy.trim();
|
|
5868
|
+
}
|
|
5869
|
+
if (raw.source) {
|
|
5870
|
+
result.source = raw.source;
|
|
5871
|
+
}
|
|
5872
|
+
if (raw.approvalGate) {
|
|
5873
|
+
const approvers = normalizeStringList(raw.approvalGate.approvers);
|
|
5874
|
+
result.approvalGate = {
|
|
5875
|
+
...raw.approvalGate,
|
|
5876
|
+
approvers
|
|
5877
|
+
};
|
|
5878
|
+
}
|
|
5879
|
+
if (raw.automationScope) {
|
|
5880
|
+
const allowedProfiles = normalizeStringList(raw.automationScope.allowedProfiles);
|
|
5881
|
+
result.automationScope = {
|
|
5882
|
+
...raw.automationScope,
|
|
5883
|
+
allowedProfiles
|
|
5884
|
+
};
|
|
5885
|
+
}
|
|
5886
|
+
if (raw.matchCriteria) {
|
|
5887
|
+
const repositoryPatterns = normalizeStringList(raw.matchCriteria.repositoryPatterns);
|
|
5888
|
+
const commandPatterns = normalizeStringList(raw.matchCriteria.commandPatterns);
|
|
5889
|
+
result.matchCriteria = {
|
|
5890
|
+
...raw.matchCriteria,
|
|
5891
|
+
repositoryPatterns,
|
|
5892
|
+
commandPatterns
|
|
5893
|
+
};
|
|
5894
|
+
}
|
|
5895
|
+
return result;
|
|
5896
|
+
}
|
|
5897
|
+
function resolveOperationsBoundaryDecision(params) {
|
|
5898
|
+
const processKey = params.processKey?.trim();
|
|
5899
|
+
const boundary = normalizeOperationsProcessStep(params.boundary ?? void 0);
|
|
5900
|
+
if (!boundary) {
|
|
5901
|
+
if (!processKey) {
|
|
5902
|
+
return {
|
|
5903
|
+
canExecute: true,
|
|
5904
|
+
requiresReview: false,
|
|
5905
|
+
boundaryState: "missing"
|
|
5906
|
+
};
|
|
5907
|
+
}
|
|
5908
|
+
return {
|
|
5909
|
+
canExecute: false,
|
|
5910
|
+
requiresReview: false,
|
|
5911
|
+
boundaryState: "missing",
|
|
5912
|
+
processKey,
|
|
5913
|
+
reason: `Missing Operations boundary contract for process "${processKey}". Treating as manual-only and refusing autonomous dispatch.`
|
|
5914
|
+
};
|
|
5915
|
+
}
|
|
5916
|
+
const executionPath = boundary.executionPath;
|
|
5917
|
+
const hasValidExecutionPath = isProcessExecutionMode(executionPath);
|
|
5918
|
+
if (!boundary.processKey || !boundary.title || !hasValidExecutionPath) {
|
|
5919
|
+
const malformedPath = typeof executionPath === "string" && executionPath.length > 0 ? executionPath : "(missing)";
|
|
5920
|
+
const malformedReason = !hasValidExecutionPath ? `Operations boundary contract for process "${processKey || boundary.processKey || "(unknown)"}" has invalid executionPath "${malformedPath}". Treating as manual-only and refusing autonomous dispatch.` : "Operations boundary contract is incomplete or malformed. Treating as manual-only and refusing autonomous dispatch.";
|
|
5921
|
+
return {
|
|
5922
|
+
canExecute: false,
|
|
5923
|
+
requiresReview: false,
|
|
5924
|
+
boundaryState: "invalid",
|
|
5925
|
+
processKey: processKey || boundary.processKey || void 0,
|
|
5926
|
+
reason: malformedReason
|
|
5927
|
+
};
|
|
5928
|
+
}
|
|
5929
|
+
const resolvedProcessKey = boundary.processKey.trim();
|
|
5930
|
+
if (processKey && processKey !== resolvedProcessKey) {
|
|
5931
|
+
return {
|
|
5932
|
+
canExecute: false,
|
|
5933
|
+
requiresReview: false,
|
|
5934
|
+
boundaryState: "mismatch",
|
|
5935
|
+
processKey,
|
|
5936
|
+
executionPath,
|
|
5937
|
+
reason: `Process key "${processKey}" does not match Operations boundary "${resolvedProcessKey}". Refusing dispatch until the contract is aligned.`
|
|
5938
|
+
};
|
|
5939
|
+
}
|
|
5940
|
+
if (!boundary.enabled) {
|
|
5941
|
+
return {
|
|
5942
|
+
canExecute: false,
|
|
5943
|
+
requiresReview: false,
|
|
5944
|
+
boundaryState: "disabled",
|
|
5945
|
+
processKey: resolvedProcessKey,
|
|
5946
|
+
executionPath,
|
|
5947
|
+
reason: `Operations boundary "${resolvedProcessKey}" is disabled.`
|
|
5948
|
+
};
|
|
5949
|
+
}
|
|
5950
|
+
if (executionPath === "manual" || executionPath === "workforce") {
|
|
5951
|
+
return {
|
|
5952
|
+
canExecute: false,
|
|
5953
|
+
requiresReview: false,
|
|
5954
|
+
boundaryState: executionPath,
|
|
5955
|
+
processKey: resolvedProcessKey,
|
|
5956
|
+
executionPath,
|
|
5957
|
+
reason: `Operations boundary "${resolvedProcessKey}" is ${executionPath}-only and cannot be dispatched to a background agent.`
|
|
5958
|
+
};
|
|
5959
|
+
}
|
|
5960
|
+
if (executionPath === "hybrid") {
|
|
5961
|
+
return {
|
|
5962
|
+
canExecute: true,
|
|
5963
|
+
requiresReview: true,
|
|
5964
|
+
boundaryState: "hybrid",
|
|
5965
|
+
processKey: resolvedProcessKey,
|
|
5966
|
+
executionPath,
|
|
5967
|
+
reason: `Operations boundary "${resolvedProcessKey}" allows agent execution but requires human review checkpoints.`
|
|
5968
|
+
};
|
|
5969
|
+
}
|
|
5970
|
+
return {
|
|
5971
|
+
canExecute: true,
|
|
5972
|
+
requiresReview: false,
|
|
5973
|
+
boundaryState: "agent",
|
|
5974
|
+
processKey: resolvedProcessKey,
|
|
5975
|
+
executionPath
|
|
5976
|
+
};
|
|
5977
|
+
}
|
|
5978
|
+
function validateExecutionIdentityEnvelope(envelope) {
|
|
5979
|
+
if (!envelope || typeof envelope !== "object") {
|
|
5980
|
+
return "ExecutionIdentityEnvelope is missing or not an object";
|
|
5981
|
+
}
|
|
5982
|
+
const e = envelope;
|
|
5983
|
+
const requiredStringFields = [
|
|
5984
|
+
"requesterId",
|
|
5985
|
+
"credentialOwnerId",
|
|
5986
|
+
"executionOwnerId",
|
|
5987
|
+
"credentialResolutionMethod",
|
|
5988
|
+
"resolvedAt"
|
|
5989
|
+
];
|
|
5990
|
+
for (const field of requiredStringFields) {
|
|
5991
|
+
if (typeof e[field] !== "string" || e[field].trim().length === 0) {
|
|
5992
|
+
return `ExecutionIdentityEnvelope.${field} is missing or empty`;
|
|
5993
|
+
}
|
|
5994
|
+
}
|
|
5995
|
+
const validMethods = [
|
|
5996
|
+
"explicit-credential-user",
|
|
5997
|
+
"caller-identity",
|
|
5998
|
+
"token-label",
|
|
5999
|
+
"org-credential-owner",
|
|
6000
|
+
"provider-credential-owner"
|
|
6001
|
+
];
|
|
6002
|
+
if (!validMethods.includes(e.credentialResolutionMethod)) {
|
|
6003
|
+
return `ExecutionIdentityEnvelope.credentialResolutionMethod "${e.credentialResolutionMethod}" is not a valid resolution method`;
|
|
6004
|
+
}
|
|
6005
|
+
return null;
|
|
6006
|
+
}
|
|
6007
|
+
function normalizeWorkItemExecutionContext(raw) {
|
|
6008
|
+
const result = { ...raw };
|
|
6009
|
+
if (result.relatedProcessKeys) {
|
|
6010
|
+
result.relatedProcessKeys = result.relatedProcessKeys.filter((k) => typeof k === "string" && k.trim().length > 0);
|
|
6011
|
+
}
|
|
6012
|
+
if (result.operationsBoundary) {
|
|
6013
|
+
result.operationsBoundary = normalizeOperationsProcessStep(result.operationsBoundary);
|
|
6014
|
+
}
|
|
6015
|
+
return result;
|
|
6016
|
+
}
|
|
6017
|
+
function serializeWorkItemExecutionContext(ctx) {
|
|
6018
|
+
return JSON.stringify(normalizeWorkItemExecutionContext(ctx));
|
|
6019
|
+
}
|
|
6020
|
+
function parseWorkItemExecutionContext(raw) {
|
|
6021
|
+
if (!raw || raw.trim().length === 0) {
|
|
6022
|
+
return {};
|
|
6023
|
+
}
|
|
6024
|
+
try {
|
|
6025
|
+
const parsed = JSON.parse(raw);
|
|
6026
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
6027
|
+
return { context: normalizeWorkItemExecutionContext(parsed) };
|
|
6028
|
+
}
|
|
6029
|
+
return { legacyText: raw };
|
|
6030
|
+
} catch {
|
|
6031
|
+
return { legacyText: raw };
|
|
6032
|
+
}
|
|
6033
|
+
}
|
|
6034
|
+
var PROCESS_EXECUTION_MODES;
|
|
5764
6035
|
var init_work_item = __esm({
|
|
5765
6036
|
"../../packages/types/dist/work-item.js"() {
|
|
5766
6037
|
"use strict";
|
|
6038
|
+
PROCESS_EXECUTION_MODES = ["agent", "hybrid", "manual", "workforce"];
|
|
5767
6039
|
}
|
|
5768
6040
|
});
|
|
5769
6041
|
|
|
@@ -5796,10 +6068,17 @@ var init_config_governance = __esm({
|
|
|
5796
6068
|
});
|
|
5797
6069
|
|
|
5798
6070
|
// ../../packages/types/dist/credentials.js
|
|
5799
|
-
|
|
6071
|
+
function getCredentialProviderConfig(provider) {
|
|
6072
|
+
return CREDENTIAL_PROVIDER_CONFIGS.find((c) => c.id === provider);
|
|
6073
|
+
}
|
|
6074
|
+
function isValidCredentialProvider(value) {
|
|
6075
|
+
return CREDENTIAL_PROVIDERS.includes(value);
|
|
6076
|
+
}
|
|
6077
|
+
var CREDENTIAL_PROVIDERS, CREDENTIAL_PROVIDER_CONFIGS;
|
|
5800
6078
|
var init_credentials = __esm({
|
|
5801
6079
|
"../../packages/types/dist/credentials.js"() {
|
|
5802
6080
|
"use strict";
|
|
6081
|
+
CREDENTIAL_PROVIDERS = ["claude", "codex", "gemini", "cursor"];
|
|
5803
6082
|
CREDENTIAL_PROVIDER_CONFIGS = [
|
|
5804
6083
|
{
|
|
5805
6084
|
id: "claude",
|
|
@@ -5895,9 +6174,33 @@ var init_orchestrator_brain = __esm({
|
|
|
5895
6174
|
});
|
|
5896
6175
|
|
|
5897
6176
|
// ../../packages/types/dist/provider-usage.js
|
|
6177
|
+
function calculateHealthState(usagePercent, thresholds = DEFAULT_USAGE_THRESHOLDS) {
|
|
6178
|
+
if (usagePercent === null)
|
|
6179
|
+
return "ok";
|
|
6180
|
+
if (usagePercent >= thresholds.criticalThreshold)
|
|
6181
|
+
return "critical";
|
|
6182
|
+
if (usagePercent >= thresholds.warningThreshold)
|
|
6183
|
+
return "warning";
|
|
6184
|
+
return "ok";
|
|
6185
|
+
}
|
|
6186
|
+
function calculateHeadroom(currentUsage, limit) {
|
|
6187
|
+
if (limit === null)
|
|
6188
|
+
return null;
|
|
6189
|
+
return Math.max(0, limit - currentUsage);
|
|
6190
|
+
}
|
|
6191
|
+
function calculateUsagePercent(currentUsage, limit) {
|
|
6192
|
+
if (limit === null || limit === 0)
|
|
6193
|
+
return null;
|
|
6194
|
+
return Math.min(100, currentUsage / limit * 100);
|
|
6195
|
+
}
|
|
6196
|
+
var DEFAULT_USAGE_THRESHOLDS;
|
|
5898
6197
|
var init_provider_usage = __esm({
|
|
5899
6198
|
"../../packages/types/dist/provider-usage.js"() {
|
|
5900
6199
|
"use strict";
|
|
6200
|
+
DEFAULT_USAGE_THRESHOLDS = {
|
|
6201
|
+
warningThreshold: 70,
|
|
6202
|
+
criticalThreshold: 90
|
|
6203
|
+
};
|
|
5901
6204
|
}
|
|
5902
6205
|
});
|
|
5903
6206
|
|
|
@@ -5909,9 +6212,47 @@ var init_worker_pool = __esm({
|
|
|
5909
6212
|
});
|
|
5910
6213
|
|
|
5911
6214
|
// ../../packages/types/dist/provider-precedence.js
|
|
6215
|
+
function mapAgentToProvider(agent) {
|
|
6216
|
+
const mapping = {
|
|
6217
|
+
claude: "claude",
|
|
6218
|
+
codex: "codex",
|
|
6219
|
+
gemini: "gemini"
|
|
6220
|
+
};
|
|
6221
|
+
return mapping[agent] ?? "claude";
|
|
6222
|
+
}
|
|
6223
|
+
function mapProviderToAgent(provider) {
|
|
6224
|
+
const mapping = {
|
|
6225
|
+
claude: "claude",
|
|
6226
|
+
codex: "codex",
|
|
6227
|
+
gemini: "gemini"
|
|
6228
|
+
};
|
|
6229
|
+
return mapping[provider];
|
|
6230
|
+
}
|
|
6231
|
+
function determineFallbackReason(requestedChecks, fallbackChecks) {
|
|
6232
|
+
if (!requestedChecks.credentials)
|
|
6233
|
+
return "fallback_credentials";
|
|
6234
|
+
if (!requestedChecks.capacity)
|
|
6235
|
+
return "fallback_capacity";
|
|
6236
|
+
if (!requestedChecks.quota)
|
|
6237
|
+
return "fallback_quota";
|
|
6238
|
+
if (!requestedChecks.health)
|
|
6239
|
+
return "fallback_health";
|
|
6240
|
+
if (!requestedChecks.policy)
|
|
6241
|
+
return "fallback_policy";
|
|
6242
|
+
return "fallback_capacity";
|
|
6243
|
+
}
|
|
6244
|
+
function formatProviderSelection(result) {
|
|
6245
|
+
if (result.reason === "requested") {
|
|
6246
|
+
return `Selected ${result.provider} (requested)`;
|
|
6247
|
+
}
|
|
6248
|
+
const requested = result.requestedProvider ?? "claude";
|
|
6249
|
+
return `Selected ${result.provider} (fallback from ${requested}: ${result.reason})`;
|
|
6250
|
+
}
|
|
6251
|
+
var DEFAULT_PROVIDER_PRECEDENCE;
|
|
5912
6252
|
var init_provider_precedence = __esm({
|
|
5913
6253
|
"../../packages/types/dist/provider-precedence.js"() {
|
|
5914
6254
|
"use strict";
|
|
6255
|
+
DEFAULT_PROVIDER_PRECEDENCE = ["codex", "claude", "gemini"];
|
|
5915
6256
|
}
|
|
5916
6257
|
});
|
|
5917
6258
|
|
|
@@ -5923,23 +6264,78 @@ var init_sdlc_enforcement = __esm({
|
|
|
5923
6264
|
});
|
|
5924
6265
|
|
|
5925
6266
|
// ../../packages/types/dist/supervisor-directive.js
|
|
6267
|
+
var DEFAULT_DIRECTIVE_POLICY;
|
|
5926
6268
|
var init_supervisor_directive = __esm({
|
|
5927
6269
|
"../../packages/types/dist/supervisor-directive.js"() {
|
|
5928
6270
|
"use strict";
|
|
6271
|
+
DEFAULT_DIRECTIVE_POLICY = {
|
|
6272
|
+
maxCapacityPerOrg: 10,
|
|
6273
|
+
maxRetryAttempts: 3,
|
|
6274
|
+
minRetryDelayMs: 5e3,
|
|
6275
|
+
// 5 seconds
|
|
6276
|
+
allowedAgents: ["claude", "codex", "gemini", "any"],
|
|
6277
|
+
enforceIdempotency: true,
|
|
6278
|
+
idempotencyWindowMs: 3e5
|
|
6279
|
+
// 5 minutes
|
|
6280
|
+
};
|
|
5929
6281
|
}
|
|
5930
6282
|
});
|
|
5931
6283
|
|
|
5932
6284
|
// ../../packages/types/dist/browser-automation.js
|
|
6285
|
+
var BROWSER_BACKEND_FALLBACK_ORDER, BROWSER_BACKEND_CONFIGS, FAILURE_REMEDIATIONS;
|
|
5933
6286
|
var init_browser_automation = __esm({
|
|
5934
6287
|
"../../packages/types/dist/browser-automation.js"() {
|
|
5935
6288
|
"use strict";
|
|
6289
|
+
BROWSER_BACKEND_FALLBACK_ORDER = [
|
|
6290
|
+
"chrome-devtools",
|
|
6291
|
+
"playwright",
|
|
6292
|
+
"claude-chrome"
|
|
6293
|
+
];
|
|
6294
|
+
BROWSER_BACKEND_CONFIGS = {
|
|
6295
|
+
"chrome-devtools": {
|
|
6296
|
+
displayName: "Chrome DevTools MCP",
|
|
6297
|
+
mcpServerName: "chrome-devtools",
|
|
6298
|
+
description: "Direct Chrome DevTools Protocol via chrome-devtools-mcp"
|
|
6299
|
+
},
|
|
6300
|
+
"playwright": {
|
|
6301
|
+
displayName: "Playwright MCP",
|
|
6302
|
+
mcpServerName: "playwright",
|
|
6303
|
+
description: "Playwright browser automation via @anthropic/playwright-mcp"
|
|
6304
|
+
},
|
|
6305
|
+
"claude-chrome": {
|
|
6306
|
+
displayName: "Claude Chrome",
|
|
6307
|
+
mcpServerName: "claude-in-chrome",
|
|
6308
|
+
description: "Claude built-in Chrome automation via Claude-in-Chrome MCP"
|
|
6309
|
+
}
|
|
6310
|
+
};
|
|
6311
|
+
FAILURE_REMEDIATIONS = {
|
|
6312
|
+
BACKEND_NOT_AVAILABLE: "No browser automation backend is available. Ensure at least one MCP server (chrome-devtools, playwright, or claude-chrome) is configured in approved config or user MCP config.",
|
|
6313
|
+
BACKEND_CONNECTION_FAILED: "Browser backend was detected but connection failed. Check that the MCP server process is running and the browser is accessible.",
|
|
6314
|
+
PERMISSION_DENIED: "Insufficient permissions for this browser action. Check MCP server configuration and ensure the agent has browser automation permissions.",
|
|
6315
|
+
AUTH_REQUIRED: "The target page requires authentication. Navigate to the login page first or provide credentials via environment variables.",
|
|
6316
|
+
BROWSER_NOT_FOUND: "Browser binary not found. Install Chrome/Chromium or set the CHROME_PATH environment variable.",
|
|
6317
|
+
ELEMENT_NOT_FOUND: "Target element not found in the DOM. Verify the selector/UID and ensure the page has fully loaded.",
|
|
6318
|
+
PAGE_TIMEOUT: "Page operation timed out. Check network connectivity, increase timeout, or verify the target URL is reachable.",
|
|
6319
|
+
SCREENSHOT_FAILED: "Screenshot capture failed. Try a different capture mode (viewport instead of full_page) or check browser state.",
|
|
6320
|
+
INVALID_SELECTOR: "The provided CSS/XPath selector is malformed. Verify the selector syntax and try again.",
|
|
6321
|
+
MCP_SERVER_ERROR: "The MCP server returned an error. Check MCP server logs for details and ensure the server version is up to date."
|
|
6322
|
+
};
|
|
5936
6323
|
}
|
|
5937
6324
|
});
|
|
5938
6325
|
|
|
5939
6326
|
// ../../packages/types/dist/team-assignment.js
|
|
6327
|
+
var DEFAULT_TEAM_ASSIGNMENT_CONFIG;
|
|
5940
6328
|
var init_team_assignment = __esm({
|
|
5941
6329
|
"../../packages/types/dist/team-assignment.js"() {
|
|
5942
6330
|
"use strict";
|
|
6331
|
+
DEFAULT_TEAM_ASSIGNMENT_CONFIG = {
|
|
6332
|
+
supervisorWorkerRatio: 3,
|
|
6333
|
+
maxTotalWorkers: 12,
|
|
6334
|
+
providerCaps: { claude: 6, codex: 4, gemini: 4 },
|
|
6335
|
+
maxPendingAssignments: 20,
|
|
6336
|
+
maxWorkersPerRepo: 4,
|
|
6337
|
+
fairnessWeight: 0.5
|
|
6338
|
+
};
|
|
5943
6339
|
}
|
|
5944
6340
|
});
|
|
5945
6341
|
|
|
@@ -6111,8 +6507,310 @@ var init_learning = __esm({
|
|
|
6111
6507
|
}
|
|
6112
6508
|
});
|
|
6113
6509
|
|
|
6510
|
+
// ../../packages/types/dist/enforcement-mode.js
|
|
6511
|
+
function checkEnforcement(toolName, toolInput, settings, sessionRole, userLogin) {
|
|
6512
|
+
if (!settings.enabled || settings.mode === "off") {
|
|
6513
|
+
return {
|
|
6514
|
+
allowed: true,
|
|
6515
|
+
mode: settings.mode,
|
|
6516
|
+
sessionRole,
|
|
6517
|
+
isWarning: false
|
|
6518
|
+
};
|
|
6519
|
+
}
|
|
6520
|
+
if (sessionRole === "worker") {
|
|
6521
|
+
return {
|
|
6522
|
+
allowed: true,
|
|
6523
|
+
mode: settings.mode,
|
|
6524
|
+
sessionRole,
|
|
6525
|
+
isWarning: false
|
|
6526
|
+
};
|
|
6527
|
+
}
|
|
6528
|
+
if (userLogin && settings.exemptUsers && settings.exemptUsers.includes(userLogin)) {
|
|
6529
|
+
return {
|
|
6530
|
+
allowed: true,
|
|
6531
|
+
mode: settings.mode,
|
|
6532
|
+
sessionRole,
|
|
6533
|
+
isWarning: false
|
|
6534
|
+
};
|
|
6535
|
+
}
|
|
6536
|
+
if (ALWAYS_ALLOWED_TOOLS.includes(toolName)) {
|
|
6537
|
+
return {
|
|
6538
|
+
allowed: true,
|
|
6539
|
+
mode: settings.mode,
|
|
6540
|
+
sessionRole,
|
|
6541
|
+
isWarning: false
|
|
6542
|
+
};
|
|
6543
|
+
}
|
|
6544
|
+
const blockedTools = settings.blockedTools && settings.blockedTools.length > 0 ? settings.blockedTools : DEFAULT_BLOCKED_TOOLS;
|
|
6545
|
+
const isBlockedTool = blockedTools.includes(toolName);
|
|
6546
|
+
let isBlockedBash = false;
|
|
6547
|
+
if (toolName === "Bash") {
|
|
6548
|
+
const command = String(toolInput?.command || "");
|
|
6549
|
+
isBlockedBash = BLOCKED_BASH_PATTERNS.some((pattern) => command.includes(pattern));
|
|
6550
|
+
}
|
|
6551
|
+
const isBlocked = isBlockedTool || isBlockedBash;
|
|
6552
|
+
if (!isBlocked) {
|
|
6553
|
+
return {
|
|
6554
|
+
allowed: true,
|
|
6555
|
+
mode: settings.mode,
|
|
6556
|
+
sessionRole,
|
|
6557
|
+
isWarning: false
|
|
6558
|
+
};
|
|
6559
|
+
}
|
|
6560
|
+
const org = "your organization";
|
|
6561
|
+
const blockMessage = (settings.blockMessage || DEFAULT_BLOCK_MESSAGE).replace(/\{tool\}/g, toolName).replace(/\{org\}/g, org);
|
|
6562
|
+
if (settings.mode === "warn") {
|
|
6563
|
+
return {
|
|
6564
|
+
allowed: true,
|
|
6565
|
+
mode: settings.mode,
|
|
6566
|
+
sessionRole,
|
|
6567
|
+
reason: `\u26A0\uFE0F WARNING: ${blockMessage}`,
|
|
6568
|
+
isWarning: true
|
|
6569
|
+
};
|
|
6570
|
+
}
|
|
6571
|
+
return {
|
|
6572
|
+
allowed: false,
|
|
6573
|
+
mode: settings.mode,
|
|
6574
|
+
sessionRole,
|
|
6575
|
+
reason: blockMessage,
|
|
6576
|
+
isWarning: false
|
|
6577
|
+
};
|
|
6578
|
+
}
|
|
6579
|
+
var DEFAULT_BLOCKED_TOOLS, BLOCKED_BASH_PATTERNS, ALWAYS_ALLOWED_TOOLS, DEFAULT_ENFORCEMENT_MODE_SETTINGS, DEFAULT_BLOCK_MESSAGE;
|
|
6580
|
+
var init_enforcement_mode = __esm({
|
|
6581
|
+
"../../packages/types/dist/enforcement-mode.js"() {
|
|
6582
|
+
"use strict";
|
|
6583
|
+
DEFAULT_BLOCKED_TOOLS = [
|
|
6584
|
+
"Edit",
|
|
6585
|
+
"Write",
|
|
6586
|
+
"MultiEdit",
|
|
6587
|
+
"NotebookEdit"
|
|
6588
|
+
];
|
|
6589
|
+
BLOCKED_BASH_PATTERNS = [
|
|
6590
|
+
"git push",
|
|
6591
|
+
"git commit",
|
|
6592
|
+
"git add",
|
|
6593
|
+
"git stash",
|
|
6594
|
+
"git rebase",
|
|
6595
|
+
"git merge",
|
|
6596
|
+
"git cherry-pick",
|
|
6597
|
+
"npm publish",
|
|
6598
|
+
"pnpm publish",
|
|
6599
|
+
"make deploy",
|
|
6600
|
+
"make release"
|
|
6601
|
+
];
|
|
6602
|
+
ALWAYS_ALLOWED_TOOLS = [
|
|
6603
|
+
"Read",
|
|
6604
|
+
"Glob",
|
|
6605
|
+
"Grep",
|
|
6606
|
+
"LSP",
|
|
6607
|
+
"WebFetch",
|
|
6608
|
+
"WebSearch",
|
|
6609
|
+
"AskUserQuestion",
|
|
6610
|
+
"TodoWrite",
|
|
6611
|
+
"Task",
|
|
6612
|
+
"Skill",
|
|
6613
|
+
"EnterPlanMode",
|
|
6614
|
+
"ExitPlanMode"
|
|
6615
|
+
];
|
|
6616
|
+
DEFAULT_ENFORCEMENT_MODE_SETTINGS = {
|
|
6617
|
+
mode: "off",
|
|
6618
|
+
enabled: false
|
|
6619
|
+
};
|
|
6620
|
+
DEFAULT_BLOCK_MESSAGE = "\u{1F6AB} This action is blocked by your organization's enforcement policy.\nYour org ({org}) requires all implementation work to go through the background agent queue.\n\nTo proceed:\n 1. Create a GitHub issue describing the work\n 2. Use `gal dispatch` or the dashboard to queue a background agent\n 3. Monitor and review the agent's output\n\nBlocked tool: {tool}";
|
|
6621
|
+
}
|
|
6622
|
+
});
|
|
6623
|
+
|
|
6624
|
+
// ../../packages/types/dist/sdlc-evaluation.js
|
|
6625
|
+
var init_sdlc_evaluation = __esm({
|
|
6626
|
+
"../../packages/types/dist/sdlc-evaluation.js"() {
|
|
6627
|
+
"use strict";
|
|
6628
|
+
}
|
|
6629
|
+
});
|
|
6630
|
+
|
|
6631
|
+
// ../../packages/types/dist/oss-model-eval.js
|
|
6632
|
+
var OSS_EVAL_SCHEMA_VERSION, OSS_EVAL_DATASET_PATH, OSS_EVAL_TASK_SET_MODES, OSS_EVAL_CANONICAL_PROVIDERS, OSS_EVAL_METRIC_IDS, DEFAULT_OSS_EVAL_THRESHOLDS, DEFAULT_OSS_EVAL_WEIGHTS, DEFAULT_OSS_EVAL_WIN_CRITERIA, OSS_EVAL_METRICS, DEFAULT_OSS_EVAL_SPEC;
|
|
6633
|
+
var init_oss_model_eval = __esm({
|
|
6634
|
+
"../../packages/types/dist/oss-model-eval.js"() {
|
|
6635
|
+
"use strict";
|
|
6636
|
+
OSS_EVAL_SCHEMA_VERSION = "v1";
|
|
6637
|
+
OSS_EVAL_DATASET_PATH = "/sessions";
|
|
6638
|
+
OSS_EVAL_TASK_SET_MODES = ["intersection", "all"];
|
|
6639
|
+
OSS_EVAL_CANONICAL_PROVIDERS = ["claude", "codex", "oss"];
|
|
6640
|
+
OSS_EVAL_METRIC_IDS = [
|
|
6641
|
+
"pr_merge_rate",
|
|
6642
|
+
"ci_pass_rate_first_attempt",
|
|
6643
|
+
"task_completion_rate",
|
|
6644
|
+
"review_score"
|
|
6645
|
+
];
|
|
6646
|
+
DEFAULT_OSS_EVAL_THRESHOLDS = {
|
|
6647
|
+
prMergeRate: 0.75,
|
|
6648
|
+
ciPassRateFirstAttempt: 0.65,
|
|
6649
|
+
taskCompletionRate: 0.8,
|
|
6650
|
+
reviewScore: 0.85
|
|
6651
|
+
};
|
|
6652
|
+
DEFAULT_OSS_EVAL_WEIGHTS = {
|
|
6653
|
+
prMergeRate: 0.3,
|
|
6654
|
+
ciPassRateFirstAttempt: 0.2,
|
|
6655
|
+
taskCompletionRate: 0.35,
|
|
6656
|
+
reviewScore: 0.15
|
|
6657
|
+
};
|
|
6658
|
+
DEFAULT_OSS_EVAL_WIN_CRITERIA = {
|
|
6659
|
+
minimumSharedTasks: 20,
|
|
6660
|
+
minimumCompositeScore: 0.75,
|
|
6661
|
+
requireAllMetricThresholds: true
|
|
6662
|
+
};
|
|
6663
|
+
OSS_EVAL_METRICS = {
|
|
6664
|
+
pr_merge_rate: {
|
|
6665
|
+
id: "pr_merge_rate",
|
|
6666
|
+
label: "PR Merge Rate",
|
|
6667
|
+
numeratorDefinition: "PR merged",
|
|
6668
|
+
denominatorDefinition: "Session has mapped PR",
|
|
6669
|
+
thresholdKey: "prMergeRate",
|
|
6670
|
+
weightKey: "prMergeRate"
|
|
6671
|
+
},
|
|
6672
|
+
ci_pass_rate_first_attempt: {
|
|
6673
|
+
id: "ci_pass_rate_first_attempt",
|
|
6674
|
+
label: "CI Pass Rate (First Attempt)",
|
|
6675
|
+
numeratorDefinition: "PR CI passed on first attempt",
|
|
6676
|
+
denominatorDefinition: "Session has mapped PR with CI evidence",
|
|
6677
|
+
thresholdKey: "ciPassRateFirstAttempt",
|
|
6678
|
+
weightKey: "ciPassRateFirstAttempt"
|
|
6679
|
+
},
|
|
6680
|
+
task_completion_rate: {
|
|
6681
|
+
id: "task_completion_rate",
|
|
6682
|
+
label: "Task Completion Rate",
|
|
6683
|
+
numeratorDefinition: "Issue closed with no human reopen",
|
|
6684
|
+
denominatorDefinition: "Session has mapped issue",
|
|
6685
|
+
thresholdKey: "taskCompletionRate",
|
|
6686
|
+
weightKey: "taskCompletionRate"
|
|
6687
|
+
},
|
|
6688
|
+
review_score: {
|
|
6689
|
+
id: "review_score",
|
|
6690
|
+
label: "Review Score",
|
|
6691
|
+
numeratorDefinition: "PR had no requested changes",
|
|
6692
|
+
denominatorDefinition: "Session has mapped PR with review evidence",
|
|
6693
|
+
thresholdKey: "reviewScore",
|
|
6694
|
+
weightKey: "reviewScore"
|
|
6695
|
+
}
|
|
6696
|
+
};
|
|
6697
|
+
DEFAULT_OSS_EVAL_SPEC = {
|
|
6698
|
+
schemaVersion: OSS_EVAL_SCHEMA_VERSION,
|
|
6699
|
+
datasetPath: OSS_EVAL_DATASET_PATH,
|
|
6700
|
+
defaultTaskSetMode: "intersection",
|
|
6701
|
+
metrics: OSS_EVAL_METRICS,
|
|
6702
|
+
thresholds: DEFAULT_OSS_EVAL_THRESHOLDS,
|
|
6703
|
+
weights: DEFAULT_OSS_EVAL_WEIGHTS,
|
|
6704
|
+
winCriteria: DEFAULT_OSS_EVAL_WIN_CRITERIA
|
|
6705
|
+
};
|
|
6706
|
+
}
|
|
6707
|
+
});
|
|
6708
|
+
|
|
6709
|
+
// ../../packages/types/dist/ab-routing.js
|
|
6710
|
+
function laneToEvalProvider(lane, vendorProvider) {
|
|
6711
|
+
if (lane === "oss")
|
|
6712
|
+
return "oss";
|
|
6713
|
+
if (vendorProvider === "codex")
|
|
6714
|
+
return "codex";
|
|
6715
|
+
return "claude";
|
|
6716
|
+
}
|
|
6717
|
+
var DEFAULT_AB_ROUTING_CONFIG, AB_ROUTING_MODES;
|
|
6718
|
+
var init_ab_routing = __esm({
|
|
6719
|
+
"../../packages/types/dist/ab-routing.js"() {
|
|
6720
|
+
"use strict";
|
|
6721
|
+
DEFAULT_AB_ROUTING_CONFIG = {
|
|
6722
|
+
enabled: false,
|
|
6723
|
+
mode: "vendor_only"
|
|
6724
|
+
};
|
|
6725
|
+
AB_ROUTING_MODES = [
|
|
6726
|
+
"vendor_only",
|
|
6727
|
+
"oss_only",
|
|
6728
|
+
"percentage",
|
|
6729
|
+
"round_robin",
|
|
6730
|
+
"conditional"
|
|
6731
|
+
];
|
|
6732
|
+
}
|
|
6733
|
+
});
|
|
6734
|
+
|
|
6114
6735
|
// ../../packages/types/dist/index.js
|
|
6115
|
-
var
|
|
6736
|
+
var dist_exports = {};
|
|
6737
|
+
__export(dist_exports, {
|
|
6738
|
+
AB_ROUTING_MODES: () => AB_ROUTING_MODES,
|
|
6739
|
+
ACTIVE_BACKGROUND_AGENT_RUNNER_LABELS: () => ACTIVE_BACKGROUND_AGENT_RUNNER_LABELS,
|
|
6740
|
+
ALL_PAGE_IDS: () => ALL_PAGE_IDS,
|
|
6741
|
+
ALL_PLATFORM_IDS: () => ALL_PLATFORM_IDS,
|
|
6742
|
+
ALWAYS_ALLOWED_TOOLS: () => ALWAYS_ALLOWED_TOOLS,
|
|
6743
|
+
BLOCKED_BASH_PATTERNS: () => BLOCKED_BASH_PATTERNS,
|
|
6744
|
+
BROWSER_BACKEND_CONFIGS: () => BROWSER_BACKEND_CONFIGS,
|
|
6745
|
+
BROWSER_BACKEND_FALLBACK_ORDER: () => BROWSER_BACKEND_FALLBACK_ORDER,
|
|
6746
|
+
CREDENTIAL_PROVIDERS: () => CREDENTIAL_PROVIDERS,
|
|
6747
|
+
CREDENTIAL_PROVIDER_CONFIGS: () => CREDENTIAL_PROVIDER_CONFIGS,
|
|
6748
|
+
CREDENTIAL_SYNC_PLATFORMS: () => CREDENTIAL_SYNC_PLATFORMS,
|
|
6749
|
+
DEFAULT_AB_ROUTING_CONFIG: () => DEFAULT_AB_ROUTING_CONFIG,
|
|
6750
|
+
DEFAULT_BLOCKED_TOOLS: () => DEFAULT_BLOCKED_TOOLS,
|
|
6751
|
+
DEFAULT_BLOCK_MESSAGE: () => DEFAULT_BLOCK_MESSAGE,
|
|
6752
|
+
DEFAULT_DIRECTIVE_POLICY: () => DEFAULT_DIRECTIVE_POLICY,
|
|
6753
|
+
DEFAULT_DISPATCH_CATEGORIES: () => DEFAULT_DISPATCH_CATEGORIES,
|
|
6754
|
+
DEFAULT_ENFORCEMENT_MODE_SETTINGS: () => DEFAULT_ENFORCEMENT_MODE_SETTINGS,
|
|
6755
|
+
DEFAULT_ENFORCEMENT_SETTINGS: () => DEFAULT_ENFORCEMENT_SETTINGS,
|
|
6756
|
+
DEFAULT_OSS_EVAL_SPEC: () => DEFAULT_OSS_EVAL_SPEC,
|
|
6757
|
+
DEFAULT_OSS_EVAL_THRESHOLDS: () => DEFAULT_OSS_EVAL_THRESHOLDS,
|
|
6758
|
+
DEFAULT_OSS_EVAL_WEIGHTS: () => DEFAULT_OSS_EVAL_WEIGHTS,
|
|
6759
|
+
DEFAULT_OSS_EVAL_WIN_CRITERIA: () => DEFAULT_OSS_EVAL_WIN_CRITERIA,
|
|
6760
|
+
DEFAULT_PROVIDER_PRECEDENCE: () => DEFAULT_PROVIDER_PRECEDENCE,
|
|
6761
|
+
DEFAULT_RUNNER_LABEL: () => DEFAULT_RUNNER_LABEL,
|
|
6762
|
+
DEFAULT_SESSION_AGENT: () => DEFAULT_SESSION_AGENT,
|
|
6763
|
+
DEFAULT_TEAM_ASSIGNMENT_CONFIG: () => DEFAULT_TEAM_ASSIGNMENT_CONFIG,
|
|
6764
|
+
DEFAULT_USAGE_THRESHOLDS: () => DEFAULT_USAGE_THRESHOLDS,
|
|
6765
|
+
ERROR_CODE_CATEGORIES: () => ERROR_CODE_CATEGORIES,
|
|
6766
|
+
ErrorCategory: () => ErrorCategory,
|
|
6767
|
+
FAILURE_REMEDIATIONS: () => FAILURE_REMEDIATIONS,
|
|
6768
|
+
GAL_PRIVACY_URL: () => GAL_PRIVACY_URL,
|
|
6769
|
+
GAL_TERMS_URL: () => GAL_TERMS_URL,
|
|
6770
|
+
HOOKABLE_PLATFORMS: () => HOOKABLE_PLATFORMS,
|
|
6771
|
+
OSS_EVAL_CANONICAL_PROVIDERS: () => OSS_EVAL_CANONICAL_PROVIDERS,
|
|
6772
|
+
OSS_EVAL_DATASET_PATH: () => OSS_EVAL_DATASET_PATH,
|
|
6773
|
+
OSS_EVAL_METRICS: () => OSS_EVAL_METRICS,
|
|
6774
|
+
OSS_EVAL_METRIC_IDS: () => OSS_EVAL_METRIC_IDS,
|
|
6775
|
+
OSS_EVAL_SCHEMA_VERSION: () => OSS_EVAL_SCHEMA_VERSION,
|
|
6776
|
+
OSS_EVAL_TASK_SET_MODES: () => OSS_EVAL_TASK_SET_MODES,
|
|
6777
|
+
PLATFORM_DIRECTORIES: () => PLATFORM_DIRECTORIES,
|
|
6778
|
+
PLATFORM_DIRECTORY_MAP: () => PLATFORM_DIRECTORY_MAP,
|
|
6779
|
+
PLATFORM_DISPLAY_MAP: () => PLATFORM_DISPLAY_MAP,
|
|
6780
|
+
PLATFORM_INSTRUCTION_FILE_MAP: () => PLATFORM_INSTRUCTION_FILE_MAP,
|
|
6781
|
+
PLATFORM_PATTERNS: () => PLATFORM_PATTERNS,
|
|
6782
|
+
PLATFORM_REGISTRY: () => PLATFORM_REGISTRY,
|
|
6783
|
+
RETIRED_BACKGROUND_AGENT_RUNNER_LABELS: () => RETIRED_BACKGROUND_AGENT_RUNNER_LABELS,
|
|
6784
|
+
SECURITY_GATED_RUNNER_LABELS: () => SECURITY_GATED_RUNNER_LABELS,
|
|
6785
|
+
SESSION_AGENTS: () => SESSION_AGENTS,
|
|
6786
|
+
SESSION_RUNNER_PLATFORMS: () => SESSION_RUNNER_PLATFORMS,
|
|
6787
|
+
STABLE_PLATFORM_IDS: () => STABLE_PLATFORM_IDS,
|
|
6788
|
+
SessionErrorCode: () => SessionErrorCode,
|
|
6789
|
+
calculateHeadroom: () => calculateHeadroom,
|
|
6790
|
+
calculateHealthState: () => calculateHealthState,
|
|
6791
|
+
calculateUsagePercent: () => calculateUsagePercent,
|
|
6792
|
+
checkEnforcement: () => checkEnforcement,
|
|
6793
|
+
determineFallbackReason: () => determineFallbackReason,
|
|
6794
|
+
formatProviderSelection: () => formatProviderSelection,
|
|
6795
|
+
getCredentialProviderConfig: () => getCredentialProviderConfig,
|
|
6796
|
+
isActiveBackgroundAgentRunnerLabel: () => isActiveBackgroundAgentRunnerLabel,
|
|
6797
|
+
isEnhancedEvent: () => isEnhancedEvent,
|
|
6798
|
+
isValidCredentialProvider: () => isValidCredentialProvider,
|
|
6799
|
+
laneToEvalProvider: () => laneToEvalProvider,
|
|
6800
|
+
mapAgentToProvider: () => mapAgentToProvider,
|
|
6801
|
+
mapProviderToAgent: () => mapProviderToAgent,
|
|
6802
|
+
normalizeBackgroundAgentRunnerLabel: () => normalizeBackgroundAgentRunnerLabel,
|
|
6803
|
+
normalizeOperationsProcessStep: () => normalizeOperationsProcessStep,
|
|
6804
|
+
normalizeWorkItemExecutionContext: () => normalizeWorkItemExecutionContext,
|
|
6805
|
+
parseWorkItemExecutionContext: () => parseWorkItemExecutionContext,
|
|
6806
|
+
platformsWithCapability: () => platformsWithCapability,
|
|
6807
|
+
resolveOperationsBoundaryDecision: () => resolveOperationsBoundaryDecision,
|
|
6808
|
+
serializeWorkItemExecutionContext: () => serializeWorkItemExecutionContext,
|
|
6809
|
+
severityToNumber: () => severityToNumber,
|
|
6810
|
+
upgradeToEnhancedEvent: () => upgradeToEnhancedEvent,
|
|
6811
|
+
validateExecutionIdentityEnvelope: () => validateExecutionIdentityEnvelope
|
|
6812
|
+
});
|
|
6813
|
+
var GAL_TERMS_URL, GAL_PRIVACY_URL, PLATFORM_DIRECTORIES, PLATFORM_PATTERNS, DEFAULT_ENFORCEMENT_SETTINGS, DEFAULT_DISPATCH_CATEGORIES;
|
|
6116
6814
|
var init_dist2 = __esm({
|
|
6117
6815
|
"../../packages/types/dist/index.js"() {
|
|
6118
6816
|
"use strict";
|
|
@@ -6169,8 +6867,13 @@ var init_dist2 = __esm({
|
|
|
6169
6867
|
init_memory();
|
|
6170
6868
|
init_secrets();
|
|
6171
6869
|
init_learning();
|
|
6870
|
+
init_enforcement_mode();
|
|
6871
|
+
init_sdlc_evaluation();
|
|
6872
|
+
init_oss_model_eval();
|
|
6873
|
+
init_ab_routing();
|
|
6172
6874
|
GAL_TERMS_URL = "https://scheduler-systems.com/legal/en/gal-terms.pdf";
|
|
6173
6875
|
GAL_PRIVACY_URL = "https://scheduler-systems.com/legal/en/gal-privacy.pdf";
|
|
6876
|
+
PLATFORM_DIRECTORIES = PLATFORM_DIRECTORY_MAP;
|
|
6174
6877
|
PLATFORM_PATTERNS = {
|
|
6175
6878
|
claude: {
|
|
6176
6879
|
platform: "claude",
|
|
@@ -6349,6 +7052,24 @@ var init_dist2 = __esm({
|
|
|
6349
7052
|
ruleExtensions: []
|
|
6350
7053
|
}
|
|
6351
7054
|
};
|
|
7055
|
+
DEFAULT_ENFORCEMENT_SETTINGS = {
|
|
7056
|
+
enabled: false,
|
|
7057
|
+
level: "warn",
|
|
7058
|
+
blockOnMismatch: false,
|
|
7059
|
+
requireSync: false,
|
|
7060
|
+
allowOverrides: true,
|
|
7061
|
+
notifyOnViolation: false
|
|
7062
|
+
};
|
|
7063
|
+
DEFAULT_DISPATCH_CATEGORIES = [
|
|
7064
|
+
{ id: "bug-fixes", name: "Bug Fixes", description: "Fix bugs with clear reproduction steps and specific file locations", enabled: true },
|
|
7065
|
+
{ id: "test-writing", name: "Test Writing", description: "Write or update tests for existing code", enabled: true },
|
|
7066
|
+
{ id: "documentation", name: "Documentation", description: "Update docs, README files, code comments", enabled: true },
|
|
7067
|
+
{ id: "ci-fixes", name: "CI/Lint Fixes", description: "Fix CI failures, lint errors, type errors", enabled: true },
|
|
7068
|
+
{ id: "refactoring", name: "Code Refactoring", description: "Refactor code patterns across multiple files", enabled: false },
|
|
7069
|
+
{ id: "new-features", name: "New Features", description: "Implement new features from specs", enabled: false },
|
|
7070
|
+
{ id: "security-fixes", name: "Security Patches", description: "Fix security vulnerabilities", enabled: false },
|
|
7071
|
+
{ id: "migrations", name: "Migrations", description: "Database or dependency migrations", enabled: false }
|
|
7072
|
+
];
|
|
6352
7073
|
}
|
|
6353
7074
|
});
|
|
6354
7075
|
|
|
@@ -13937,7 +14658,8 @@ var init_HttpWorkItemRepository = __esm({
|
|
|
13937
14658
|
priority: request.priority,
|
|
13938
14659
|
source: request.source,
|
|
13939
14660
|
context: request.context,
|
|
13940
|
-
preferredAgent: request.preferredAgent
|
|
14661
|
+
preferredAgent: request.preferredAgent,
|
|
14662
|
+
...request.runnerLabel ? { runnerLabel: request.runnerLabel } : {}
|
|
13941
14663
|
};
|
|
13942
14664
|
const response = await this.fetchJson("/api/work-items", {
|
|
13943
14665
|
method: "POST",
|
|
@@ -46579,7 +47301,17 @@ function rememberSessionStart(inputData) {
|
|
|
46579
47301
|
}),
|
|
46580
47302
|
'utf-8',
|
|
46581
47303
|
);
|
|
46582
|
-
} catch {
|
|
47304
|
+
} catch (startError) {
|
|
47305
|
+
// Log so session-start tracking failures are diagnosable (#4970)
|
|
47306
|
+
try {
|
|
47307
|
+
const logDir = path.join(os.homedir(), '.gal', 'logs');
|
|
47308
|
+
if (!fs.existsSync(logDir)) fs.mkdirSync(logDir, { recursive: true });
|
|
47309
|
+
fs.appendFileSync(
|
|
47310
|
+
path.join(logDir, 'usage-hook.log'),
|
|
47311
|
+
\`[\${new Date().toISOString()}] rememberSessionStart failed: \${startError.message || startError}\\n\`,
|
|
47312
|
+
);
|
|
47313
|
+
} catch {}
|
|
47314
|
+
}
|
|
46583
47315
|
}
|
|
46584
47316
|
|
|
46585
47317
|
function selfClean() {
|
|
@@ -46951,7 +47683,17 @@ try {
|
|
|
46951
47683
|
\`gal report-usage --provider claude --seconds \${durationSeconds} --org \${JSON.stringify(orgName)} --json\`,
|
|
46952
47684
|
{ stdio: 'pipe', timeout: 15000, shell: true },
|
|
46953
47685
|
);
|
|
46954
|
-
} catch {
|
|
47686
|
+
} catch (reportError) {
|
|
47687
|
+
// Log to a file so usage-reporting failures are diagnosable (#4970)
|
|
47688
|
+
try {
|
|
47689
|
+
const logDir = path.join(os.homedir(), '.gal', 'logs');
|
|
47690
|
+
if (!fs.existsSync(logDir)) fs.mkdirSync(logDir, { recursive: true });
|
|
47691
|
+
const stderr = reportError && reportError.stderr ? reportError.stderr.toString() : '';
|
|
47692
|
+
const stdout = reportError && reportError.stdout ? reportError.stdout.toString() : '';
|
|
47693
|
+
const entry = \`[\${new Date().toISOString()}] report-usage failed (org=\${orgName}, seconds=\${durationSeconds})\\n exit=\${reportError.status || 'unknown'}\\n stderr: \${stderr.trim() || '(none)'}\\n stdout: \${stdout.trim() || '(none)'}\\n\\n\`;
|
|
47694
|
+
fs.appendFileSync(path.join(logDir, 'usage-hook.log'), entry);
|
|
47695
|
+
} catch {}
|
|
47696
|
+
}
|
|
46955
47697
|
|
|
46956
47698
|
process.exit(0);
|
|
46957
47699
|
`;
|
|
@@ -55608,6 +56350,382 @@ var init_system_enforcer = __esm({
|
|
|
55608
56350
|
}
|
|
55609
56351
|
});
|
|
55610
56352
|
|
|
56353
|
+
// src/enforcement/workflow-enforcement-hook.ts
|
|
56354
|
+
var workflow_enforcement_hook_exports = {};
|
|
56355
|
+
__export(workflow_enforcement_hook_exports, {
|
|
56356
|
+
generateWorkflowEnforcementHook: () => generateWorkflowEnforcementHook,
|
|
56357
|
+
generateWorkflowEnforcementHookNode: () => generateWorkflowEnforcementHookNode
|
|
56358
|
+
});
|
|
56359
|
+
function generateWorkflowEnforcementHook(options) {
|
|
56360
|
+
const { apiUrl, orgName, sessionRole } = options;
|
|
56361
|
+
const hookScript = `#!/usr/bin/env python3
|
|
56362
|
+
"""
|
|
56363
|
+
GAL Workflow Enforcement Hook - Background Agents Only Mode
|
|
56364
|
+
Generated by GAL CLI for org: ${orgName}
|
|
56365
|
+
API: ${apiUrl}
|
|
56366
|
+
|
|
56367
|
+
Enforces the organization's workflow policy:
|
|
56368
|
+
- 'background-only': Blocks implementation tools in local sessions
|
|
56369
|
+
- 'warn': Warns but allows implementation tools in local sessions
|
|
56370
|
+
- 'off': No restrictions
|
|
56371
|
+
|
|
56372
|
+
Fail-open: If GAL API is unreachable, all tools are allowed.
|
|
56373
|
+
"""
|
|
56374
|
+
import json
|
|
56375
|
+
import os
|
|
56376
|
+
import sys
|
|
56377
|
+
import time
|
|
56378
|
+
|
|
56379
|
+
try:
|
|
56380
|
+
from urllib.request import Request, urlopen
|
|
56381
|
+
from urllib.error import URLError
|
|
56382
|
+
except ImportError:
|
|
56383
|
+
# Fallback: if urllib is unavailable, fail open
|
|
56384
|
+
def main():
|
|
56385
|
+
print(json.dumps({"decision": "allow"}))
|
|
56386
|
+
sys.exit(0)
|
|
56387
|
+
if __name__ == "__main__":
|
|
56388
|
+
main()
|
|
56389
|
+
sys.exit(0)
|
|
56390
|
+
|
|
56391
|
+
# Configuration
|
|
56392
|
+
API_URL = "${apiUrl}"
|
|
56393
|
+
ORG_NAME = "${orgName}"
|
|
56394
|
+
CACHE_TTL_SECONDS = 300 # 5 minutes
|
|
56395
|
+
CACHE_FILE = os.path.join(os.path.expanduser("~"), ".gal", "enforcement-cache.json")
|
|
56396
|
+
|
|
56397
|
+
# Tool classifications
|
|
56398
|
+
BLOCKED_TOOLS = ${JSON.stringify(DEFAULT_BLOCKED_TOOLS)}
|
|
56399
|
+
BLOCKED_BASH_PATTERNS = ${JSON.stringify(BLOCKED_BASH_PATTERNS)}
|
|
56400
|
+
ALWAYS_ALLOWED = ${JSON.stringify(ALWAYS_ALLOWED_TOOLS)}
|
|
56401
|
+
|
|
56402
|
+
${sessionRole === "worker" ? `
|
|
56403
|
+
# This session is a worker (background agent) \u2014 skip all enforcement
|
|
56404
|
+
def main():
|
|
56405
|
+
print(json.dumps({"decision": "allow"}))
|
|
56406
|
+
|
|
56407
|
+
if __name__ == "__main__":
|
|
56408
|
+
main()
|
|
56409
|
+
sys.exit(0)
|
|
56410
|
+
` : ""}
|
|
56411
|
+
|
|
56412
|
+
def load_cached_settings():
|
|
56413
|
+
"""Load enforcement settings from local cache if still fresh."""
|
|
56414
|
+
try:
|
|
56415
|
+
if not os.path.exists(CACHE_FILE):
|
|
56416
|
+
return None
|
|
56417
|
+
with open(CACHE_FILE, "r") as f:
|
|
56418
|
+
cache = json.load(f)
|
|
56419
|
+
if cache.get("orgName") != ORG_NAME:
|
|
56420
|
+
return None
|
|
56421
|
+
cached_at = cache.get("cachedAt", 0)
|
|
56422
|
+
if time.time() - cached_at > CACHE_TTL_SECONDS:
|
|
56423
|
+
return None
|
|
56424
|
+
return cache.get("settings")
|
|
56425
|
+
except Exception:
|
|
56426
|
+
return None
|
|
56427
|
+
|
|
56428
|
+
|
|
56429
|
+
def save_cached_settings(settings):
|
|
56430
|
+
"""Save enforcement settings to local cache."""
|
|
56431
|
+
try:
|
|
56432
|
+
cache_dir = os.path.dirname(CACHE_FILE)
|
|
56433
|
+
os.makedirs(cache_dir, exist_ok=True)
|
|
56434
|
+
with open(CACHE_FILE, "w") as f:
|
|
56435
|
+
json.dump({
|
|
56436
|
+
"orgName": ORG_NAME,
|
|
56437
|
+
"settings": settings,
|
|
56438
|
+
"cachedAt": time.time(),
|
|
56439
|
+
}, f)
|
|
56440
|
+
except Exception:
|
|
56441
|
+
pass # Non-critical \u2014 next call will re-fetch
|
|
56442
|
+
|
|
56443
|
+
|
|
56444
|
+
def fetch_enforcement_settings():
|
|
56445
|
+
"""Fetch enforcement settings from GAL API. Returns None on failure (fail-open)."""
|
|
56446
|
+
# Try cache first
|
|
56447
|
+
cached = load_cached_settings()
|
|
56448
|
+
if cached is not None:
|
|
56449
|
+
return cached
|
|
56450
|
+
|
|
56451
|
+
# Fetch from API
|
|
56452
|
+
url = f"{API_URL}/organizations/{ORG_NAME}/workflow-enforcement"
|
|
56453
|
+
try:
|
|
56454
|
+
# Use GAL auth token if available
|
|
56455
|
+
token = os.environ.get("GAL_AUTH_TOKEN") or os.environ.get("GAL_API_KEY")
|
|
56456
|
+
headers = {"Content-Type": "application/json"}
|
|
56457
|
+
if token:
|
|
56458
|
+
headers["Authorization"] = f"Bearer {token}"
|
|
56459
|
+
|
|
56460
|
+
req = Request(url, headers=headers)
|
|
56461
|
+
with urlopen(req, timeout=5) as resp:
|
|
56462
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
56463
|
+
save_cached_settings(data)
|
|
56464
|
+
return data
|
|
56465
|
+
except Exception:
|
|
56466
|
+
# Fail open \u2014 if API is unreachable, allow everything
|
|
56467
|
+
return None
|
|
56468
|
+
|
|
56469
|
+
|
|
56470
|
+
def is_worker_session():
|
|
56471
|
+
"""Check if this is a background agent (worker) session."""
|
|
56472
|
+
# Background agents set these env vars
|
|
56473
|
+
if os.environ.get("GAL_SESSION_ROLE") == "worker":
|
|
56474
|
+
return True
|
|
56475
|
+
if os.environ.get("GAL_BACKGROUND_AGENT") == "true":
|
|
56476
|
+
return True
|
|
56477
|
+
if os.environ.get("GITHUB_ACTIONS") == "true" and os.environ.get("GAL_SESSION_ID"):
|
|
56478
|
+
return True
|
|
56479
|
+
return False
|
|
56480
|
+
|
|
56481
|
+
|
|
56482
|
+
def check_tool(tool_name, tool_input, settings):
|
|
56483
|
+
"""Check if a tool call should be allowed based on enforcement settings."""
|
|
56484
|
+
mode = settings.get("mode", "off")
|
|
56485
|
+
enabled = settings.get("enabled", False)
|
|
56486
|
+
|
|
56487
|
+
if not enabled or mode == "off":
|
|
56488
|
+
return {"decision": "allow"}
|
|
56489
|
+
|
|
56490
|
+
# Always-allowed tools pass through
|
|
56491
|
+
if tool_name in ALWAYS_ALLOWED:
|
|
56492
|
+
return {"decision": "allow"}
|
|
56493
|
+
|
|
56494
|
+
# Check if user is exempt
|
|
56495
|
+
user_login = os.environ.get("GAL_USER_LOGIN", "")
|
|
56496
|
+
exempt_users = settings.get("exemptUsers", [])
|
|
56497
|
+
if user_login and user_login in exempt_users:
|
|
56498
|
+
return {"decision": "allow"}
|
|
56499
|
+
|
|
56500
|
+
# Check blocked tools
|
|
56501
|
+
custom_blocked = settings.get("blockedTools") or BLOCKED_TOOLS
|
|
56502
|
+
is_blocked_tool = tool_name in custom_blocked
|
|
56503
|
+
|
|
56504
|
+
# Check Bash command patterns
|
|
56505
|
+
is_blocked_bash = False
|
|
56506
|
+
if tool_name == "Bash":
|
|
56507
|
+
command = str(tool_input.get("command", ""))
|
|
56508
|
+
is_blocked_bash = any(p in command for p in BLOCKED_BASH_PATTERNS)
|
|
56509
|
+
|
|
56510
|
+
if not is_blocked_tool and not is_blocked_bash:
|
|
56511
|
+
return {"decision": "allow"}
|
|
56512
|
+
|
|
56513
|
+
# Build message
|
|
56514
|
+
block_msg = settings.get("blockMessage") or ${JSON.stringify(DEFAULT_BLOCK_MESSAGE)}
|
|
56515
|
+
block_msg = block_msg.replace("{tool}", tool_name).replace("{org}", ORG_NAME)
|
|
56516
|
+
|
|
56517
|
+
if mode == "warn":
|
|
56518
|
+
# Warn mode: allow but print warning to stderr
|
|
56519
|
+
sys.stderr.write(f"\\n\\033[33m[GAL] WARNING: {block_msg}\\033[0m\\n\\n")
|
|
56520
|
+
return {"decision": "allow"}
|
|
56521
|
+
|
|
56522
|
+
# background-only mode: block
|
|
56523
|
+
return {
|
|
56524
|
+
"decision": "block",
|
|
56525
|
+
"reason": block_msg,
|
|
56526
|
+
}
|
|
56527
|
+
|
|
56528
|
+
|
|
56529
|
+
def main():
|
|
56530
|
+
# Workers (background agents) are never restricted
|
|
56531
|
+
if is_worker_session():
|
|
56532
|
+
print(json.dumps({"decision": "allow"}))
|
|
56533
|
+
return
|
|
56534
|
+
|
|
56535
|
+
# Read hook input
|
|
56536
|
+
try:
|
|
56537
|
+
hook_input = json.load(sys.stdin)
|
|
56538
|
+
except (json.JSONDecodeError, Exception):
|
|
56539
|
+
print(json.dumps({"decision": "allow"}))
|
|
56540
|
+
return
|
|
56541
|
+
|
|
56542
|
+
tool_name = hook_input.get("tool_name", "")
|
|
56543
|
+
tool_input = hook_input.get("tool_input", {}) or {}
|
|
56544
|
+
|
|
56545
|
+
# Fetch enforcement settings (cached)
|
|
56546
|
+
settings = fetch_enforcement_settings()
|
|
56547
|
+
if settings is None:
|
|
56548
|
+
# Fail open
|
|
56549
|
+
print(json.dumps({"decision": "allow"}))
|
|
56550
|
+
return
|
|
56551
|
+
|
|
56552
|
+
result = check_tool(tool_name, tool_input, settings)
|
|
56553
|
+
print(json.dumps(result))
|
|
56554
|
+
|
|
56555
|
+
|
|
56556
|
+
if __name__ == "__main__":
|
|
56557
|
+
main()
|
|
56558
|
+
`;
|
|
56559
|
+
return {
|
|
56560
|
+
platform: "claude",
|
|
56561
|
+
hookType: "pre_tool_use",
|
|
56562
|
+
filename: "gal-workflow-enforcement.py",
|
|
56563
|
+
content: hookScript,
|
|
56564
|
+
settingsSnippet: {
|
|
56565
|
+
hooks: {
|
|
56566
|
+
pre_tool_use: [{
|
|
56567
|
+
command: "python3 .claude/hooks/gal-workflow-enforcement.py",
|
|
56568
|
+
timeout: 1e4
|
|
56569
|
+
}]
|
|
56570
|
+
}
|
|
56571
|
+
}
|
|
56572
|
+
};
|
|
56573
|
+
}
|
|
56574
|
+
function generateWorkflowEnforcementHookNode(options) {
|
|
56575
|
+
const { apiUrl, orgName, sessionRole } = options;
|
|
56576
|
+
const hookScript = `#!/usr/bin/env node
|
|
56577
|
+
/**
|
|
56578
|
+
* GAL Workflow Enforcement Hook - Background Agents Only Mode
|
|
56579
|
+
* Generated by GAL CLI for org: ${orgName}
|
|
56580
|
+
* API: ${apiUrl}
|
|
56581
|
+
*
|
|
56582
|
+
* Enforces the organization's workflow policy for Cursor/Windsurf.
|
|
56583
|
+
* Fail-open: If GAL API is unreachable, all tools are allowed.
|
|
56584
|
+
*/
|
|
56585
|
+
const fs = require('fs');
|
|
56586
|
+
const path = require('path');
|
|
56587
|
+
const readline = require('readline');
|
|
56588
|
+
|
|
56589
|
+
const API_URL = '${apiUrl}';
|
|
56590
|
+
const ORG_NAME = '${orgName}';
|
|
56591
|
+
const CACHE_TTL_MS = 300000; // 5 minutes
|
|
56592
|
+
const CACHE_FILE = path.join(require('os').homedir(), '.gal', 'enforcement-cache.json');
|
|
56593
|
+
|
|
56594
|
+
const BLOCKED_TOOLS = ${JSON.stringify(DEFAULT_BLOCKED_TOOLS)};
|
|
56595
|
+
const BLOCKED_BASH_PATTERNS = ${JSON.stringify(BLOCKED_BASH_PATTERNS)};
|
|
56596
|
+
const ALWAYS_ALLOWED = ${JSON.stringify(ALWAYS_ALLOWED_TOOLS)};
|
|
56597
|
+
|
|
56598
|
+
${sessionRole === "worker" ? `
|
|
56599
|
+
// Worker session \u2014 skip enforcement
|
|
56600
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
56601
|
+
process.exit(0);
|
|
56602
|
+
` : ""}
|
|
56603
|
+
|
|
56604
|
+
function isWorkerSession() {
|
|
56605
|
+
return (
|
|
56606
|
+
process.env.GAL_SESSION_ROLE === 'worker' ||
|
|
56607
|
+
process.env.GAL_BACKGROUND_AGENT === 'true' ||
|
|
56608
|
+
(process.env.GITHUB_ACTIONS === 'true' && process.env.GAL_SESSION_ID)
|
|
56609
|
+
);
|
|
56610
|
+
}
|
|
56611
|
+
|
|
56612
|
+
function loadCachedSettings() {
|
|
56613
|
+
try {
|
|
56614
|
+
if (!fs.existsSync(CACHE_FILE)) return null;
|
|
56615
|
+
const cache = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'));
|
|
56616
|
+
if (cache.orgName !== ORG_NAME) return null;
|
|
56617
|
+
if (Date.now() - (cache.cachedAt || 0) > CACHE_TTL_MS) return null;
|
|
56618
|
+
return cache.settings;
|
|
56619
|
+
} catch { return null; }
|
|
56620
|
+
}
|
|
56621
|
+
|
|
56622
|
+
function saveCachedSettings(settings) {
|
|
56623
|
+
try {
|
|
56624
|
+
const dir = path.dirname(CACHE_FILE);
|
|
56625
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
56626
|
+
fs.writeFileSync(CACHE_FILE, JSON.stringify({
|
|
56627
|
+
orgName: ORG_NAME,
|
|
56628
|
+
settings,
|
|
56629
|
+
cachedAt: Date.now(),
|
|
56630
|
+
}));
|
|
56631
|
+
} catch { /* non-critical */ }
|
|
56632
|
+
}
|
|
56633
|
+
|
|
56634
|
+
async function fetchSettings() {
|
|
56635
|
+
const cached = loadCachedSettings();
|
|
56636
|
+
if (cached) return cached;
|
|
56637
|
+
|
|
56638
|
+
try {
|
|
56639
|
+
const url = \`\${API_URL}/organizations/\${ORG_NAME}/workflow-enforcement\`;
|
|
56640
|
+
const token = process.env.GAL_AUTH_TOKEN || process.env.GAL_API_KEY;
|
|
56641
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
56642
|
+
if (token) headers['Authorization'] = \`Bearer \${token}\`;
|
|
56643
|
+
|
|
56644
|
+
const resp = await fetch(url, { headers, signal: AbortSignal.timeout(5000) });
|
|
56645
|
+
if (!resp.ok) return null;
|
|
56646
|
+
const data = await resp.json();
|
|
56647
|
+
saveCachedSettings(data);
|
|
56648
|
+
return data;
|
|
56649
|
+
} catch { return null; }
|
|
56650
|
+
}
|
|
56651
|
+
|
|
56652
|
+
const rl = readline.createInterface({ input: process.stdin });
|
|
56653
|
+
let input = '';
|
|
56654
|
+
rl.on('line', (line) => { input += line; });
|
|
56655
|
+
rl.on('close', async () => {
|
|
56656
|
+
if (isWorkerSession()) {
|
|
56657
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
56658
|
+
return;
|
|
56659
|
+
}
|
|
56660
|
+
|
|
56661
|
+
let hookInput;
|
|
56662
|
+
try { hookInput = JSON.parse(input); } catch {
|
|
56663
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
56664
|
+
return;
|
|
56665
|
+
}
|
|
56666
|
+
|
|
56667
|
+
const toolName = hookInput.tool_name || '';
|
|
56668
|
+
const toolInput = hookInput.tool_input || {};
|
|
56669
|
+
|
|
56670
|
+
const settings = await fetchSettings();
|
|
56671
|
+
if (!settings || !settings.enabled || settings.mode === 'off') {
|
|
56672
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
56673
|
+
return;
|
|
56674
|
+
}
|
|
56675
|
+
|
|
56676
|
+
if (ALWAYS_ALLOWED.includes(toolName)) {
|
|
56677
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
56678
|
+
return;
|
|
56679
|
+
}
|
|
56680
|
+
|
|
56681
|
+
const customBlocked = settings.blockedTools || BLOCKED_TOOLS;
|
|
56682
|
+
const isBlockedTool = customBlocked.includes(toolName);
|
|
56683
|
+
let isBlockedBash = false;
|
|
56684
|
+
if (toolName === 'Bash') {
|
|
56685
|
+
const cmd = String(toolInput.command || '');
|
|
56686
|
+
isBlockedBash = BLOCKED_BASH_PATTERNS.some((p) => cmd.includes(p));
|
|
56687
|
+
}
|
|
56688
|
+
|
|
56689
|
+
if (!isBlockedTool && !isBlockedBash) {
|
|
56690
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
56691
|
+
return;
|
|
56692
|
+
}
|
|
56693
|
+
|
|
56694
|
+
const msg = (settings.blockMessage || ${JSON.stringify(DEFAULT_BLOCK_MESSAGE)})
|
|
56695
|
+
.replace(/\\{tool\\}/g, toolName)
|
|
56696
|
+
.replace(/\\{org\\}/g, ORG_NAME);
|
|
56697
|
+
|
|
56698
|
+
if (settings.mode === 'warn') {
|
|
56699
|
+
process.stderr.write(\`\\n\\x1b[33m[GAL] WARNING: \${msg}\\x1b[0m\\n\\n\`);
|
|
56700
|
+
console.log(JSON.stringify({ decision: 'allow' }));
|
|
56701
|
+
return;
|
|
56702
|
+
}
|
|
56703
|
+
|
|
56704
|
+
console.log(JSON.stringify({ decision: 'block', reason: msg }));
|
|
56705
|
+
});
|
|
56706
|
+
`;
|
|
56707
|
+
return {
|
|
56708
|
+
platform: "cursor",
|
|
56709
|
+
hookType: "pre_tool_use",
|
|
56710
|
+
filename: "gal-workflow-enforcement.js",
|
|
56711
|
+
content: hookScript,
|
|
56712
|
+
settingsSnippet: {
|
|
56713
|
+
hooks: {
|
|
56714
|
+
pre_tool_use: {
|
|
56715
|
+
command: "node .cursor/hooks/gal-workflow-enforcement.js",
|
|
56716
|
+
timeout: 1e4
|
|
56717
|
+
}
|
|
56718
|
+
}
|
|
56719
|
+
}
|
|
56720
|
+
};
|
|
56721
|
+
}
|
|
56722
|
+
var init_workflow_enforcement_hook = __esm({
|
|
56723
|
+
"src/enforcement/workflow-enforcement-hook.ts"() {
|
|
56724
|
+
"use strict";
|
|
56725
|
+
init_dist2();
|
|
56726
|
+
}
|
|
56727
|
+
});
|
|
56728
|
+
|
|
55611
56729
|
// src/enforcement/index.ts
|
|
55612
56730
|
var init_enforcement = __esm({
|
|
55613
56731
|
"src/enforcement/index.ts"() {
|
|
@@ -55618,6 +56736,7 @@ var init_enforcement = __esm({
|
|
|
55618
56736
|
init_config_validator();
|
|
55619
56737
|
init_hook_generator();
|
|
55620
56738
|
init_system_enforcer();
|
|
56739
|
+
init_workflow_enforcement_hook();
|
|
55621
56740
|
}
|
|
55622
56741
|
});
|
|
55623
56742
|
|
|
@@ -58146,6 +59265,183 @@ Native SDLC enforcement updated to ${level} for ${orgName}.
|
|
|
58146
59265
|
}
|
|
58147
59266
|
});
|
|
58148
59267
|
enforce.addCommand(sdlcCommand);
|
|
59268
|
+
const workflowCommand = new Command("workflow").description("Manage workflow enforcement mode (background agents only)");
|
|
59269
|
+
workflowCommand.command("status").description("Show the current workflow enforcement mode").option("--json", "Output as JSON").action(async (options) => {
|
|
59270
|
+
const { authToken, orgName, apiUrl } = getAuthAndOrg2();
|
|
59271
|
+
const spinner = options.json ? null : ora("Fetching workflow enforcement settings...").start();
|
|
59272
|
+
try {
|
|
59273
|
+
const res = await fetchApi3(
|
|
59274
|
+
`${apiUrl}/organizations/${encodeURIComponent(orgName)}/workflow-enforcement`,
|
|
59275
|
+
authToken
|
|
59276
|
+
);
|
|
59277
|
+
if (!res.ok) {
|
|
59278
|
+
const data2 = await res.json().catch(() => ({}));
|
|
59279
|
+
throw new Error(data2.error || `HTTP ${res.status}`);
|
|
59280
|
+
}
|
|
59281
|
+
const data = await res.json();
|
|
59282
|
+
spinner?.stop();
|
|
59283
|
+
if (options.json) {
|
|
59284
|
+
console.log(JSON.stringify(data, null, 2));
|
|
59285
|
+
return;
|
|
59286
|
+
}
|
|
59287
|
+
const mode = data.mode || "off";
|
|
59288
|
+
const enabled = data.enabled === true;
|
|
59289
|
+
const modeColor = mode === "background-only" ? source_default.red : mode === "warn" ? source_default.yellow : source_default.dim;
|
|
59290
|
+
console.log(source_default.bold("\nWorkflow Enforcement Settings\n"));
|
|
59291
|
+
console.log(` Organization: ${source_default.cyan(orgName)}`);
|
|
59292
|
+
console.log(` Enabled: ${enabled ? source_default.green("yes") : source_default.dim("no")}`);
|
|
59293
|
+
console.log(` Mode: ${modeColor(mode)}`);
|
|
59294
|
+
if (mode === "background-only") {
|
|
59295
|
+
console.log();
|
|
59296
|
+
console.log(source_default.yellow(" Local sessions are restricted to orchestration only."));
|
|
59297
|
+
console.log(source_default.yellow(" All implementation must go through the background agent queue."));
|
|
59298
|
+
} else if (mode === "warn") {
|
|
59299
|
+
console.log();
|
|
59300
|
+
console.log(source_default.dim(" Warnings are shown for local implementation but not blocked."));
|
|
59301
|
+
}
|
|
59302
|
+
if (data.exemptUsers?.length) {
|
|
59303
|
+
console.log(` Exempt Users: ${data.exemptUsers.join(", ")}`);
|
|
59304
|
+
}
|
|
59305
|
+
if (data.updatedBy) {
|
|
59306
|
+
console.log(` Updated By: ${data.updatedBy}`);
|
|
59307
|
+
}
|
|
59308
|
+
if (data.updatedAt) {
|
|
59309
|
+
console.log(` Updated At: ${data.updatedAt}`);
|
|
59310
|
+
}
|
|
59311
|
+
console.log();
|
|
59312
|
+
} catch (error3) {
|
|
59313
|
+
spinner?.stop();
|
|
59314
|
+
const msg = error3 instanceof Error ? error3.message : String(error3);
|
|
59315
|
+
if (options.json) {
|
|
59316
|
+
console.log(JSON.stringify({ error: msg }));
|
|
59317
|
+
} else {
|
|
59318
|
+
console.error(source_default.red("Error fetching workflow enforcement settings:"), msg);
|
|
59319
|
+
}
|
|
59320
|
+
process.exit(1);
|
|
59321
|
+
}
|
|
59322
|
+
});
|
|
59323
|
+
workflowCommand.command("check").description("Check if a tool call would be allowed under current enforcement policy").requiredOption("--tool <toolName>", "Tool name to check (e.g., Edit, Write, Bash)").option("--command <command>", "Bash command to check (when tool is Bash)").option("--json", "Output as JSON").action(async (options) => {
|
|
59324
|
+
const { authToken, orgName, apiUrl } = getAuthAndOrg2();
|
|
59325
|
+
try {
|
|
59326
|
+
const res = await fetchApi3(
|
|
59327
|
+
`${apiUrl}/organizations/${encodeURIComponent(orgName)}/workflow-enforcement`,
|
|
59328
|
+
authToken
|
|
59329
|
+
);
|
|
59330
|
+
if (!res.ok) {
|
|
59331
|
+
if (options.json) {
|
|
59332
|
+
console.log(JSON.stringify({ allowed: true, mode: "off", reason: "API unavailable \u2014 fail open" }));
|
|
59333
|
+
} else {
|
|
59334
|
+
console.log(source_default.green("\u2713 Allowed (API unavailable \u2014 fail open)"));
|
|
59335
|
+
}
|
|
59336
|
+
return;
|
|
59337
|
+
}
|
|
59338
|
+
const settings = await res.json();
|
|
59339
|
+
const { checkEnforcement: checkEnforcement2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
59340
|
+
const toolInput = {};
|
|
59341
|
+
if (options.command) {
|
|
59342
|
+
toolInput.command = options.command;
|
|
59343
|
+
}
|
|
59344
|
+
const result = checkEnforcement2(
|
|
59345
|
+
options.tool,
|
|
59346
|
+
toolInput,
|
|
59347
|
+
settings,
|
|
59348
|
+
"orchestrator"
|
|
59349
|
+
// CLI is always an orchestrator
|
|
59350
|
+
);
|
|
59351
|
+
if (options.json) {
|
|
59352
|
+
console.log(JSON.stringify(result, null, 2));
|
|
59353
|
+
return;
|
|
59354
|
+
}
|
|
59355
|
+
if (result.allowed && !result.isWarning) {
|
|
59356
|
+
console.log(source_default.green(`\u2713 ${options.tool} is allowed`));
|
|
59357
|
+
} else if (result.isWarning) {
|
|
59358
|
+
console.log(source_default.yellow(`\u26A0 ${options.tool} triggers a warning`));
|
|
59359
|
+
if (result.reason) {
|
|
59360
|
+
console.log(source_default.dim(result.reason));
|
|
59361
|
+
}
|
|
59362
|
+
} else {
|
|
59363
|
+
console.log(source_default.red(`\u2717 ${options.tool} is blocked`));
|
|
59364
|
+
if (result.reason) {
|
|
59365
|
+
console.log(result.reason);
|
|
59366
|
+
}
|
|
59367
|
+
}
|
|
59368
|
+
} catch (error3) {
|
|
59369
|
+
const msg = error3 instanceof Error ? error3.message : String(error3);
|
|
59370
|
+
if (options.json) {
|
|
59371
|
+
console.log(JSON.stringify({ error: msg }));
|
|
59372
|
+
} else {
|
|
59373
|
+
console.error(source_default.red("Error checking enforcement:"), msg);
|
|
59374
|
+
}
|
|
59375
|
+
process.exit(1);
|
|
59376
|
+
}
|
|
59377
|
+
});
|
|
59378
|
+
workflowCommand.command("install").description("Install workflow enforcement hook for Claude Code").option("--path <path>", "Base path (default: current directory)").option("--force", "Overwrite existing hook").option("--dry-run", "Show what would be installed without making changes").action(async (options) => {
|
|
59379
|
+
const spinner = ora();
|
|
59380
|
+
const { orgName, apiUrl } = getAuthAndOrg2();
|
|
59381
|
+
const basePath = options.path || process.cwd();
|
|
59382
|
+
try {
|
|
59383
|
+
spinner.start("Generating workflow enforcement hook...");
|
|
59384
|
+
const { generateWorkflowEnforcementHook: generateWorkflowEnforcementHook2 } = await Promise.resolve().then(() => (init_workflow_enforcement_hook(), workflow_enforcement_hook_exports));
|
|
59385
|
+
const hook = generateWorkflowEnforcementHook2({
|
|
59386
|
+
apiUrl,
|
|
59387
|
+
orgName
|
|
59388
|
+
});
|
|
59389
|
+
const claudeHooksDir = (0, import_node_path3.join)(basePath, ".claude", "hooks");
|
|
59390
|
+
const hookPath = (0, import_node_path3.join)(claudeHooksDir, hook.filename);
|
|
59391
|
+
if (options.dryRun) {
|
|
59392
|
+
spinner.info("[DRY RUN] Would install workflow enforcement hook");
|
|
59393
|
+
console.log(source_default.dim(` Path: ${hookPath}`));
|
|
59394
|
+
console.log(source_default.dim(` API: ${apiUrl}`));
|
|
59395
|
+
console.log(source_default.dim(` Org: ${orgName}`));
|
|
59396
|
+
return;
|
|
59397
|
+
}
|
|
59398
|
+
if ((0, import_node_fs2.existsSync)(hookPath) && !options.force) {
|
|
59399
|
+
spinner.fail("Workflow enforcement hook already exists. Use --force to overwrite.");
|
|
59400
|
+
return;
|
|
59401
|
+
}
|
|
59402
|
+
await (0, import_promises4.mkdir)(claudeHooksDir, { recursive: true });
|
|
59403
|
+
await (0, import_promises4.writeFile)(hookPath, hook.content, "utf-8");
|
|
59404
|
+
await (0, import_promises4.chmod)(hookPath, 493);
|
|
59405
|
+
const settingsPath = (0, import_node_path3.join)(basePath, ".claude", "settings.json");
|
|
59406
|
+
let settings = {};
|
|
59407
|
+
try {
|
|
59408
|
+
const existing2 = await (0, import_promises4.readFile)(settingsPath, "utf-8");
|
|
59409
|
+
settings = JSON.parse(existing2);
|
|
59410
|
+
} catch {
|
|
59411
|
+
settings = {};
|
|
59412
|
+
}
|
|
59413
|
+
const hooks = settings.hooks && typeof settings.hooks === "object" ? { ...settings.hooks } : {};
|
|
59414
|
+
const existing = Array.isArray(hooks.PreToolUse) ? [...hooks.PreToolUse] : [];
|
|
59415
|
+
const filtered = existing.filter((entry) => {
|
|
59416
|
+
if (!entry || typeof entry !== "object") return true;
|
|
59417
|
+
return entry.command !== "python3 .claude/hooks/gal-workflow-enforcement.py";
|
|
59418
|
+
});
|
|
59419
|
+
filtered.push({
|
|
59420
|
+
type: "command",
|
|
59421
|
+
command: "python3 .claude/hooks/gal-workflow-enforcement.py",
|
|
59422
|
+
timeout: 1e4
|
|
59423
|
+
});
|
|
59424
|
+
hooks.PreToolUse = filtered;
|
|
59425
|
+
settings.hooks = hooks;
|
|
59426
|
+
await (0, import_promises4.writeFile)(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
59427
|
+
spinner.succeed("Installed workflow enforcement hook");
|
|
59428
|
+
console.log(source_default.dim(` Hook: ${hookPath}`));
|
|
59429
|
+
console.log(source_default.dim(` Settings: ${settingsPath}`));
|
|
59430
|
+
console.log();
|
|
59431
|
+
console.log(source_default.blue("The hook will check your org's enforcement mode before each tool call."));
|
|
59432
|
+
if (orgName) {
|
|
59433
|
+
console.log(source_default.dim(` Organization: ${orgName}`));
|
|
59434
|
+
console.log(source_default.dim(` API: ${apiUrl}`));
|
|
59435
|
+
}
|
|
59436
|
+
} catch (error3) {
|
|
59437
|
+
spinner.fail("Failed to install workflow enforcement hook");
|
|
59438
|
+
if (error3 instanceof Error) {
|
|
59439
|
+
console.error(source_default.red(error3.message));
|
|
59440
|
+
}
|
|
59441
|
+
process.exit(1);
|
|
59442
|
+
}
|
|
59443
|
+
});
|
|
59444
|
+
enforce.addCommand(workflowCommand);
|
|
58149
59445
|
enforce.command("domains").description("Manage domain allowlist and exceptions").option("--json", "Output as JSON").action(async (options) => {
|
|
58150
59446
|
const { authToken, orgName, apiUrl } = getAuthAndOrg2();
|
|
58151
59447
|
const spinner = options.json ? null : ora("Fetching domain exceptions...").start();
|
|
@@ -66817,6 +68113,23 @@ async function reportDriftStatus(result, projectId, apiUrl, authToken) {
|
|
|
66817
68113
|
} catch {
|
|
66818
68114
|
}
|
|
66819
68115
|
}
|
|
68116
|
+
function displayQualityScores(qualityScore) {
|
|
68117
|
+
console.log(source_default.bold("Config Quality:"));
|
|
68118
|
+
console.log();
|
|
68119
|
+
const overallPct = (qualityScore.overall * 100).toFixed(0);
|
|
68120
|
+
const overallColor = qualityScore.overall >= 0.7 ? source_default.green : qualityScore.overall >= 0.4 ? source_default.yellow : source_default.red;
|
|
68121
|
+
console.log(` Overall: ${overallColor(overallPct + "%")} ${source_default.dim(`(${qualityScore.totalEvaluations} evaluations)`)}`);
|
|
68122
|
+
if (qualityScore.byPhase) {
|
|
68123
|
+
const phases = Object.entries(qualityScore.byPhase).sort(([a], [b]) => a.localeCompare(b));
|
|
68124
|
+
for (const [phase, data] of phases) {
|
|
68125
|
+
if (!data) continue;
|
|
68126
|
+
const pct = (data.score * 100).toFixed(0);
|
|
68127
|
+
const color = data.score >= 0.7 ? source_default.green : data.score >= 0.4 ? source_default.yellow : source_default.red;
|
|
68128
|
+
console.log(` ${phase.padEnd(15)} ${color(pct + "%")} ${source_default.dim(`(${data.evaluationCount} evals)`)}`);
|
|
68129
|
+
}
|
|
68130
|
+
}
|
|
68131
|
+
console.log();
|
|
68132
|
+
}
|
|
66820
68133
|
function createStatusCommand3() {
|
|
66821
68134
|
const command = new Command("status").description("Check sync status, drift, and pending proposals").option("--json", "Output as JSON").option("-d, --directory <path>", "Project directory to check", process.cwd()).option("--check-update", "Check for updates from organization (requires network)").option("--no-report", "Skip reporting drift status to API").action(async (options) => {
|
|
66822
68135
|
try {
|
|
@@ -66876,6 +68189,27 @@ function createStatusCommand3() {
|
|
|
66876
68189
|
console.log(source_default.bold(`Config Sync (${source_default.dim(directory)}):`));
|
|
66877
68190
|
displayStatus(result, proposals);
|
|
66878
68191
|
}
|
|
68192
|
+
if (health.allHealthy && config2.defaultOrg && config2.apiUrl && authToken) {
|
|
68193
|
+
try {
|
|
68194
|
+
const qualitySpinner = options.json ? null : ora("Checking config quality...").start();
|
|
68195
|
+
const response = await fetch(
|
|
68196
|
+
`${config2.apiUrl}/organizations/${encodeURIComponent(config2.defaultOrg)}/approved-config?platform=claude`,
|
|
68197
|
+
{
|
|
68198
|
+
headers: { Authorization: `Bearer ${authToken}` },
|
|
68199
|
+
signal: AbortSignal.timeout(5e3)
|
|
68200
|
+
}
|
|
68201
|
+
);
|
|
68202
|
+
qualitySpinner?.stop();
|
|
68203
|
+
if (response.ok) {
|
|
68204
|
+
const configData = await response.json();
|
|
68205
|
+
const qualityScore = configData?.qualityScore;
|
|
68206
|
+
if (qualityScore && !options.json) {
|
|
68207
|
+
displayQualityScores(qualityScore);
|
|
68208
|
+
}
|
|
68209
|
+
}
|
|
68210
|
+
} catch {
|
|
68211
|
+
}
|
|
68212
|
+
}
|
|
66879
68213
|
process.exit(0);
|
|
66880
68214
|
} catch (error3) {
|
|
66881
68215
|
const err = error3 instanceof Error ? error3 : new Error(String(error3));
|
|
@@ -71815,7 +73149,7 @@ var init_index = __esm({
|
|
|
71815
73149
|
});
|
|
71816
73150
|
|
|
71817
73151
|
// src/bootstrap.ts
|
|
71818
|
-
var cliVersion10 = true ? "0.0.
|
|
73152
|
+
var cliVersion10 = true ? "0.0.411" : "0.0.0-dev";
|
|
71819
73153
|
var args = process.argv.slice(2);
|
|
71820
73154
|
var requestedGlobalHelp = args.length === 1 && (args[0] === "--help" || args[0] === "-h");
|
|
71821
73155
|
var requestedVersion = args.length === 1 && (args[0] === "--version" || args[0] === "-V");
|