sneakoscope 6.1.0 → 6.2.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/README.md +35 -11
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/fast-inline.js +18 -9
- package/dist/bin/sks-dispatch.js +2 -2
- package/dist/cli/args.js +2 -0
- package/dist/cli/command-manifest-lite.js +2 -3
- package/dist/cli/command-registry.js +3 -4
- package/dist/cli/help-fast.js +1 -1
- package/dist/cli/install-helpers.js +116 -306
- package/dist/cli/install-tool-helpers.js +287 -0
- package/dist/cli/router.js +40 -4
- package/dist/commands/codex-lb.js +51 -20
- package/dist/commands/codex.js +39 -1
- package/dist/commands/doctor.js +242 -20
- package/dist/commands/tmux.js +5 -1
- package/dist/commands/zellij-monitor-pane.js +2 -0
- package/dist/commands/zellij-viewport-pane.js +3 -1
- package/dist/commands/zellij.js +1 -1
- package/dist/config/skills-manifest.json +59 -59
- package/dist/core/agent-bridge/agent-manifest.js +48 -0
- package/dist/core/agents/agent-command-surface.js +2 -1
- package/dist/core/agents/agent-effort-policy.js +38 -35
- package/dist/core/agents/agent-plan.js +100 -21
- package/dist/core/agents/agent-role-config.js +43 -46
- package/dist/core/agents/agent-runner-codex-exec.js +16 -3
- package/dist/core/agents/agent-schema.js +3 -2
- package/dist/core/agents/native-cli-session-swarm.js +1 -1
- package/dist/core/agents/zellij-right-lane-cockpit.js +2 -2
- package/dist/core/codex/agent-config-file-repair.js +94 -193
- package/dist/core/codex/codex-cli-update.js +723 -0
- package/dist/core/codex/codex-config-guard.js +185 -9
- package/dist/core/codex/codex-config-readability.js +21 -8
- package/dist/core/codex/codex-config-toml.js +14 -11
- package/dist/core/codex/codex-project-config-policy.js +3 -6
- package/dist/core/codex/codex-startup-config-postcheck.js +52 -42
- package/dist/core/codex-adapter.js +35 -22
- package/dist/core/codex-app/codex-agent-role-sync.js +13 -54
- package/dist/core/codex-app/codex-app-launcher.js +48 -17
- package/dist/core/codex-app/codex-app-restart.js +23 -2
- package/dist/core/codex-app/mcp-manager.js +679 -0
- package/dist/core/codex-app/sks-menubar.js +533 -8
- package/dist/core/codex-control/codex-0139-image-path-real-probe.js +15 -4
- package/dist/core/codex-control/codex-0139-web-search-probe.js +17 -6
- package/dist/core/codex-control/codex-lb-launch-recovery.js +293 -0
- package/dist/core/codex-control/codex-reliability-shield.js +89 -29
- package/dist/core/codex-control/codex-sdk-adapter.js +44 -8
- package/dist/core/codex-control/codex-task-runner.js +62 -9
- package/dist/core/codex-control/python-codex-sdk-adapter.js +30 -3
- package/dist/core/codex-exec-output-schema.js +35 -6
- package/dist/core/codex-lb/codex-lb-env.js +1 -1
- package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +291 -0
- package/dist/core/codex-native/codex-native-feature-broker.js +9 -16
- package/dist/core/codex-native/codex-native-repair-transaction.js +1 -1
- package/dist/core/codex-native/core-skill-manifest.js +8 -4
- package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -3
- package/dist/core/commands/agent-bridge-command.js +23 -2
- package/dist/core/commands/agent-command.js +19 -5
- package/dist/core/commands/basic-cli.js +47 -6
- package/dist/core/commands/command-utils.js +1 -1
- package/dist/core/commands/mad-sks-command.js +76 -10
- package/dist/core/commands/menubar-command.js +94 -0
- package/dist/core/commands/naruto-command.js +645 -1156
- package/dist/core/commands/research-command.js +293 -231
- package/dist/core/commands/run-command.js +100 -23
- package/dist/core/commands/team-command.js +2 -3
- package/dist/core/commands/team-legacy-observe-command.js +94 -359
- package/dist/core/commands/wiki-command.js +11 -5
- package/dist/core/db-safety.js +2 -2
- package/dist/core/decision-lattice.js +6 -6
- package/dist/core/doctor/codex-startup-config-repair.js +8 -3
- package/dist/core/doctor/doctor-codex-startup-repair.js +6 -141
- package/dist/core/feature-fixture-executor.js +71 -7
- package/dist/core/feature-fixture-runner.js +53 -12
- package/dist/core/feature-fixtures.js +47 -14
- package/dist/core/feature-registry.js +28 -27
- package/dist/core/fsx.js +1 -0
- package/dist/core/harness-conflicts.js +18 -9
- package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +14 -8
- package/dist/core/hooks-runtime/hook-io.js +8 -4
- package/dist/core/hooks-runtime/light-turn.js +70 -0
- package/dist/core/hooks-runtime/naruto-decision-gate.js +184 -0
- package/dist/core/hooks-runtime/payload-signals.js +270 -0
- package/dist/core/hooks-runtime/stop-repeat-guard.js +89 -0
- package/dist/core/hooks-runtime/team-digest.js +0 -1
- package/dist/core/hooks-runtime/tool-output-quarantine.js +93 -0
- package/dist/core/hooks-runtime.js +438 -354
- package/dist/core/init/skills.js +16 -30
- package/dist/core/init.js +144 -36
- package/dist/core/managed-assets/managed-assets-manifest.js +566 -10
- package/dist/core/mission.js +24 -1
- package/dist/core/pipeline-internals/runtime-core.js +570 -177
- package/dist/core/pipeline-internals/runtime-gates.js +174 -48
- package/dist/core/preflight/parallel-preflight-engine.js +66 -4
- package/dist/core/proof/route-adapter.js +1 -1
- package/dist/core/proof/route-proof-gate.js +7 -2
- package/dist/core/proof/selftest-proof-fixtures.js +3 -5
- package/dist/core/proof-field.js +1 -1
- package/dist/core/provider/model-router.js +42 -31
- package/dist/core/recallpulse/policy.js +12 -28
- package/dist/core/recallpulse.js +11 -6
- package/dist/core/release/npm-pack-proof.js +247 -0
- package/dist/core/release/package-dist-snapshot.js +151 -0
- package/dist/core/release/package-size-budget.js +4 -1
- package/dist/core/release/release-authorization-snapshot.js +115 -0
- package/dist/core/release/release-gate-affected-selector.js +14 -2
- package/dist/core/release/release-gate-cache-v2.js +30 -0
- package/dist/core/release/release-gate-contract.js +161 -0
- package/dist/core/release/release-gate-dag.js +1 -0
- package/dist/core/release/release-real-contract.js +90 -10
- package/dist/core/release-parallel-full-coverage.js +31 -143
- package/dist/core/research/claim-evidence-matrix.js +41 -6
- package/dist/core/research/experiment-plan.js +14 -10
- package/dist/core/research/falsification.js +9 -2
- package/dist/core/research/implementation-blueprint-densifier.js +82 -60
- package/dist/core/research/implementation-blueprint.js +32 -26
- package/dist/core/research/mock-result.js +122 -11
- package/dist/core/research/replication-pack.js +15 -8
- package/dist/core/research/research-adversarial-review.js +1068 -0
- package/dist/core/research/research-claim-builder.js +69 -17
- package/dist/core/research/research-claim-synthesizer.js +343 -0
- package/dist/core/research/research-cycle-runner.js +53 -3
- package/dist/core/research/research-falsification-runner.js +176 -0
- package/dist/core/research/research-final-reviewer.js +44 -125
- package/dist/core/research/research-plan-markdown.js +123 -0
- package/dist/core/research/research-realistic-report.js +14 -6
- package/dist/core/research/research-review-artifact-digest.js +66 -0
- package/dist/core/research/research-source-evidence.js +144 -0
- package/dist/core/research/research-source-layer-catalog.js +68 -0
- package/dist/core/research/research-source-ledger-merge.js +250 -12
- package/dist/core/research/research-source-shards.js +26 -70
- package/dist/core/research/research-stage-runner.js +237 -247
- package/dist/core/research/research-super-search.js +188 -0
- package/dist/core/research/research-synthesis-prompt.js +20 -1
- package/dist/core/research/research-synthesis-writer.js +86 -5
- package/dist/core/research/research-work-graph.js +25 -18
- package/dist/core/research/source-quality-report.js +21 -0
- package/dist/core/research.js +424 -390
- package/dist/core/retention.js +70 -2
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/dollar-manifest-lite.js +11 -11
- package/dist/core/routes.js +149 -69
- package/dist/core/runtime/task-profile.js +66 -0
- package/dist/core/runtime/verification-budget.js +12 -0
- package/dist/core/security/high-risk-contracts.js +6 -6
- package/dist/core/stop-gate/stop-gate-check.js +49 -12
- package/dist/core/subagents/agent-catalog.js +287 -0
- package/dist/core/subagents/model-policy.js +259 -0
- package/dist/core/subagents/naruto-help-contract.js +47 -0
- package/dist/core/subagents/official-subagent-config.js +488 -0
- package/dist/core/subagents/official-subagent-preparation.js +297 -0
- package/dist/core/subagents/official-subagent-prompt.js +159 -0
- package/dist/core/subagents/official-subagent-runner.js +129 -0
- package/dist/core/subagents/subagent-evidence.js +663 -0
- package/dist/core/subagents/terminology.js +16 -0
- package/dist/core/subagents/thread-budget.js +21 -0
- package/dist/core/subagents/triwiki-attention.js +168 -0
- package/dist/core/super-search/runtime-helpers.js +173 -19
- package/dist/core/super-search/runtime.js +140 -15
- package/dist/core/super-search/source-records.js +49 -8
- package/dist/core/team-review-policy.js +15 -0
- package/dist/core/triwiki/code-pack-head-freshness.js +291 -0
- package/dist/core/triwiki/triwiki-module-card.js +1 -1
- package/dist/core/triwiki-wrongness/wrongness-ledger.js +9 -2
- package/dist/core/version-manager.js +51 -1
- package/dist/core/version.js +1 -1
- package/dist/core/work-order-ledger.js +40 -1
- package/dist/core/zellij/zellij-fake-adapter.js +3 -1
- package/dist/core/zellij/zellij-launcher.js +49 -10
- package/dist/core/zellij/zellij-layout-builder.js +14 -5
- package/dist/core/zellij/zellij-official-subagent-activity.js +477 -0
- package/dist/core/zellij/zellij-official-subagent-telemetry.js +264 -0
- package/dist/core/zellij/zellij-pane-proof.js +9 -1
- package/dist/core/zellij/zellij-slot-pane-renderer.js +17 -5
- package/dist/core/zellij/zellij-slot-telemetry.js +15 -3
- package/dist/core/zellij/zellij-ui-mode.js +1 -1
- package/dist/core/zellij/zellij-update.js +14 -1
- package/dist/core/zellij/zellij-viewport-binder.js +3 -0
- package/dist/scripts/agent-role-config-repair-check.js +14 -16
- package/dist/scripts/architecture-guard-check.js +8 -1
- package/dist/scripts/canonical-test-runner.js +7 -1
- package/dist/scripts/check-route-modularity.js +0 -1
- package/dist/scripts/check-ts-contracts.js +1 -1
- package/dist/scripts/codex-control-all-pipelines-check.js +7 -3
- package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +27 -0
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +11 -1
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +9 -2
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +13 -2
- package/dist/scripts/codex-native-agent-role-content-check.js +27 -7
- package/dist/scripts/codex-native-repair-transaction-check.js +3 -1
- package/dist/scripts/codex-sdk-all-pipelines-check.js +7 -4
- package/dist/scripts/codex-sdk-backend-router-check.js +2 -0
- package/dist/scripts/codex-sdk-research-pipeline-check.js +30 -8
- package/dist/scripts/db-route-materialization-check.js +33 -0
- package/dist/scripts/docs-truthfulness-check.js +3 -1
- package/dist/scripts/doctor-codex-startup-repair-check.js +12 -15
- package/dist/scripts/doctor-fix-production-blackbox.js +12 -2
- package/dist/scripts/doctor-startup-config-repair-blackbox.js +8 -2
- package/dist/scripts/doctor-startup-config-repair-check.js +12 -2
- package/dist/scripts/install-update-preserves-config-check.js +6 -1
- package/dist/scripts/lib/codex-sdk-gate-lib.js +4 -0
- package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +0 -1
- package/dist/scripts/managed-role-manifest-parity-check.js +5 -4
- package/dist/scripts/naruto-codex-e2e-check.js +14 -7
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +4 -201
- package/dist/scripts/npm-publish-performance-check.js +20 -12
- package/dist/scripts/official-subagent-workflow-check.js +145 -0
- package/dist/scripts/package-published-contract-check.js +6 -29
- package/dist/scripts/packlist-performance-check.js +18 -21
- package/dist/scripts/parallel-verification-engine-check.js +2 -2
- package/dist/scripts/prepublish-release-check-or-fast.js +23 -86
- package/dist/scripts/python-codex-sdk-all-pipelines-check.js +8 -0
- package/dist/scripts/release-affected-selector-check.js +74 -1
- package/dist/scripts/release-check-stamp.js +153 -248
- package/dist/scripts/release-dag-full-coverage-check.js +7 -15
- package/dist/scripts/release-dynamic-presets-check.js +2 -1
- package/dist/scripts/release-gate-dag-runner-check.js +0 -1
- package/dist/scripts/release-gate-dag-runner.js +12 -1
- package/dist/scripts/release-gate-existence-audit.js +1 -2
- package/dist/scripts/release-parallel-full-coverage-check.js +12 -6
- package/dist/scripts/release-parallel-speed-budget-check.js +18 -2
- package/dist/scripts/release-real-check.js +26 -4
- package/dist/scripts/release-registry-check.js +61 -16
- package/dist/scripts/research-blueprint-densifier-check.js +2 -2
- package/dist/scripts/research-real-cycle-no-legacy-final-md-check.js +11 -7
- package/dist/scripts/sizecheck.js +2 -2
- package/dist/scripts/sks-3-1-4-directive-check-lib.js +8 -2
- package/dist/scripts/sks-3-1-5-directive-check-lib.js +3 -2
- package/dist/scripts/sks-3-1-6-directive-check-lib.js +5 -3
- package/dist/scripts/sks-menubar-install-check.js +14 -1
- package/dist/scripts/super-search-provider-interface-check.js +31 -18
- package/dist/scripts/trust-fixture-check.js +32 -10
- package/dist/scripts/wrongness-fixture-check.js +1 -1
- package/dist/scripts/zellij-layout-valid-check.js +5 -5
- package/dist/scripts/zellij-spawn-on-demand-layout-check.js +3 -3
- package/docs/demo.tape +1 -1
- package/infra-harness-gates.json +1486 -0
- package/package.json +15 -10
- package/release-gates.v2.json +4060 -0
- package/runtime-required-scripts.json +9 -0
- package/dist/commands/db.js +0 -6
- package/dist/core/commands/db-command.js +0 -146
- package/dist/core/research/prompt.js +0 -15
- package/dist/scripts/codex-0139-feature-probes-check.js +0 -30
- package/dist/scripts/codex-0139-marketplace-source-check.js +0 -13
- package/dist/scripts/codex-control-tool-call-sequence-repair-check.js +0 -14
|
@@ -3,8 +3,11 @@ import { ensureDir, nowIso, readJson, sha256, writeJsonAtomic, writeTextAtomic }
|
|
|
3
3
|
import { runCodexWebSearch } from '../codex/codex-web-search-adapter.js';
|
|
4
4
|
import { humanizeBlockers } from '../errors/blocker-humanizer.js';
|
|
5
5
|
import { ensureProviderCapability } from '../provider/provider-self-heal.js';
|
|
6
|
-
import { buildAttemptLedger, buildClaims, buildConvergence, buildLeads, buildProof, buildXDiscoverySources, dedupeSources, extractFirstUrl,
|
|
6
|
+
import { buildAttemptLedger, buildClaims, buildConvergence, buildLeads, buildProof, buildXDiscoverySources, dedupeSources, extractFirstUrl, materializeContext7SourceRows, renderSynthesis, sourceFromUrlFetch, sourceFromWebRow } from './runtime-helpers.js';
|
|
7
7
|
export async function runSuperSearch(input) {
|
|
8
|
+
const operationDeadlineMs = resolveSuperSearchDeadline(input);
|
|
9
|
+
if (operationDeadlineMs <= Date.now())
|
|
10
|
+
throw new Error('research_cycle_timeout_exceeded');
|
|
8
11
|
const root = path.resolve(input.root || process.cwd());
|
|
9
12
|
const missionDir = path.resolve(input.missionDir);
|
|
10
13
|
const missionId = input.missionId || path.basename(missionDir);
|
|
@@ -27,6 +30,7 @@ export async function runSuperSearch(input) {
|
|
|
27
30
|
const sourceRows = [];
|
|
28
31
|
const warnings = [...providerPlan.warnings];
|
|
29
32
|
const blockers = [...providerPlan.blockers];
|
|
33
|
+
const queryExecutionRows = [];
|
|
30
34
|
let providerSelfHeal;
|
|
31
35
|
if (!providerPlan.selected_providers.length && mode !== 'url_acquisition') {
|
|
32
36
|
if (!input.offline) {
|
|
@@ -51,28 +55,74 @@ export async function runSuperSearch(input) {
|
|
|
51
55
|
blockers.push('source_acquisition_unavailable');
|
|
52
56
|
}
|
|
53
57
|
if (input.context7 && providerPlan.selected_providers.includes('context7')) {
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
try {
|
|
59
|
+
const query = queryVariants[0] || input.query;
|
|
60
|
+
const raw = await raceSuperSearchOperation(input.context7(query), operationDeadlineMs);
|
|
61
|
+
const normalized = await materializeContext7SourceRows(raw, artifactDir, intent);
|
|
62
|
+
sourceRows.push(...normalized);
|
|
63
|
+
queryExecutionRows.push({ query, status: 'completed', source_count: normalized.length, blockers: [], warnings: [] });
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const blocker = `context7_query_failed:${error instanceof Error ? error.message : String(error)}`;
|
|
67
|
+
blockers.push(blocker);
|
|
68
|
+
queryExecutionRows.push({ query: queryVariants[0] || input.query, status: 'failed', source_count: 0, blockers: [blocker], warnings: [] });
|
|
69
|
+
}
|
|
56
70
|
}
|
|
57
71
|
else if (intent === 'official_documentation' && !input.offline) {
|
|
58
72
|
warnings.push('context7_not_invoked_for_docs_query');
|
|
59
73
|
}
|
|
60
74
|
if (providerPlan.selected_providers.includes('codex_web')) {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
75
|
+
const queries = queryVariants.slice(0, queryBudget(mode, input.maxQueryVariants));
|
|
76
|
+
const webRows = await raceSuperSearchOperation(Promise.all(queries.map(async (query) => {
|
|
77
|
+
try {
|
|
78
|
+
const evidence = await runCodexWebSearch(query, {
|
|
79
|
+
...(input.codexWebSearch ? { search: input.codexWebSearch } : {}),
|
|
80
|
+
artifactDir,
|
|
81
|
+
...(input.offline === undefined ? {} : { offline: input.offline }),
|
|
82
|
+
...(input.env ? { env: input.env } : {})
|
|
83
|
+
});
|
|
84
|
+
return { query, evidence, error: null };
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
return { query, evidence: null, error: error instanceof Error ? error.message : String(error) };
|
|
88
|
+
}
|
|
89
|
+
})), operationDeadlineMs);
|
|
90
|
+
for (const row of webRows) {
|
|
91
|
+
if (!row.evidence) {
|
|
92
|
+
const blocker = `codex_web_query_failed:${row.error || 'unknown'}`;
|
|
93
|
+
blockers.push(blocker);
|
|
94
|
+
queryExecutionRows.push({ query: row.query, status: 'failed', source_count: 0, blockers: [blocker], warnings: [] });
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (row.evidence.blockers.length)
|
|
98
|
+
blockers.push(...row.evidence.blockers);
|
|
99
|
+
warnings.push(...row.evidence.warnings);
|
|
100
|
+
const normalized = row.evidence.normalized_results.map((result, index) => sourceFromWebRow(result, index, intent));
|
|
101
|
+
sourceRows.push(...normalized);
|
|
102
|
+
queryExecutionRows.push({
|
|
103
|
+
query: row.query,
|
|
104
|
+
status: row.evidence.status === 'completed' ? 'completed' : 'skipped',
|
|
105
|
+
source_count: normalized.length,
|
|
106
|
+
blockers: [...row.evidence.blockers],
|
|
107
|
+
warnings: [...row.evidence.warnings]
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const hydrated = await hydrateDiscoverySources(sourceRows, artifactDir, intent, {
|
|
111
|
+
allowLocal: input.allowLocalFetch === true,
|
|
112
|
+
limit: hydrationBudget(mode, input.maxHydratedSources),
|
|
113
|
+
deadlineEpochMs: operationDeadlineMs
|
|
66
114
|
});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
115
|
+
sourceRows.push(...hydrated.sources);
|
|
116
|
+
if (hydrated.sources.length)
|
|
117
|
+
warnings.push(...hydrated.blockers.map((blocker) => `partial_hydration:${blocker}`));
|
|
118
|
+
else
|
|
119
|
+
blockers.push(...hydrated.blockers);
|
|
120
|
+
warnings.push(...hydrated.warnings);
|
|
71
121
|
}
|
|
72
122
|
if (mode === 'url_acquisition') {
|
|
73
123
|
const url = extractFirstUrl(input.query);
|
|
74
124
|
if (url) {
|
|
75
|
-
const fetched = await sourceFromUrlFetch(url, artifactDir, intent, { allowLocal: input.allowLocalFetch === true });
|
|
125
|
+
const fetched = await sourceFromUrlFetch(url, artifactDir, intent, { allowLocal: input.allowLocalFetch === true, deadlineEpochMs: operationDeadlineMs });
|
|
76
126
|
sourceRows.push(fetched.source);
|
|
77
127
|
blockers.push(...fetched.blockers);
|
|
78
128
|
warnings.push(...fetched.warnings);
|
|
@@ -102,6 +152,13 @@ export async function runSuperSearch(input) {
|
|
|
102
152
|
intent,
|
|
103
153
|
axes,
|
|
104
154
|
query_variants: queryVariants,
|
|
155
|
+
query_execution: {
|
|
156
|
+
schema: 'sks.super-search-query-execution.v1',
|
|
157
|
+
planned: queryExecutionRows.length,
|
|
158
|
+
completed: queryExecutionRows.filter((row) => row.status === 'completed').length,
|
|
159
|
+
failed: queryExecutionRows.filter((row) => row.status === 'failed').length,
|
|
160
|
+
rows: queryExecutionRows
|
|
161
|
+
},
|
|
105
162
|
provider_plan: providerPlan,
|
|
106
163
|
sources: deduped,
|
|
107
164
|
leads,
|
|
@@ -250,6 +307,7 @@ async function writeArtifacts(artifactDir, result) {
|
|
|
250
307
|
await writeJsonAtomic(path.join(artifactDir, 'intent.json'), { schema: 'sks.super-search-intent.v1', intent: result.intent, mode: result.mode });
|
|
251
308
|
await writeJsonAtomic(path.join(artifactDir, 'axes.json'), { schema: 'sks.super-search-axes.v1', axes: result.axes });
|
|
252
309
|
await writeJsonAtomic(path.join(artifactDir, 'query-variants.json'), { schema: 'sks.super-search-query-variants.v1', query_variants: result.query_variants });
|
|
310
|
+
await writeJsonAtomic(path.join(artifactDir, 'query-execution.json'), result.query_execution);
|
|
253
311
|
await writeJsonAtomic(path.join(artifactDir, 'provider-plan.json'), { schema: 'sks.super-search-provider-plan.v1', ...result.provider_plan });
|
|
254
312
|
await writeJsonAtomic(path.join(artifactDir, 'source-ledger.json'), { schema: 'sks.super-search-source-ledger.v1', sources: result.sources });
|
|
255
313
|
await writeJsonAtomic(path.join(artifactDir, 'lead-ledger.json'), { schema: 'sks.super-search-lead-ledger.v1', leads: result.leads });
|
|
@@ -271,7 +329,9 @@ async function writeArtifacts(artifactDir, result) {
|
|
|
271
329
|
passed: result.proof.ok,
|
|
272
330
|
execution_class: 'production',
|
|
273
331
|
mock_only: false,
|
|
274
|
-
replacement_state: result.proof.ok
|
|
332
|
+
replacement_state: result.proof.ok
|
|
333
|
+
? (result.proof.provider_independent ? 'usable_provider_independent_runtime' : 'usable_verified_runtime')
|
|
334
|
+
: 'replacement_incomplete',
|
|
275
335
|
blockers: result.proof.blockers,
|
|
276
336
|
human_summary: blockerDiagnostics.human_summary,
|
|
277
337
|
next_actions: [
|
|
@@ -288,7 +348,7 @@ async function writeArtifacts(artifactDir, result) {
|
|
|
288
348
|
await writeJsonAtomic(path.join(artifactDir, 'super-search-result.json'), result);
|
|
289
349
|
}
|
|
290
350
|
async function readCache(artifactDir, query, mode) {
|
|
291
|
-
const key = sha256(JSON.stringify({ query: query.trim().toLowerCase(), mode, adapter: 'super-search-runtime-
|
|
351
|
+
const key = sha256(JSON.stringify({ query: query.trim().toLowerCase(), mode, adapter: 'super-search-runtime-v2' })).slice(0, 16);
|
|
292
352
|
const artifact = path.join(artifactDir, 'cache', `${key}.json`);
|
|
293
353
|
const ttl_ms = mode === 'x_search' ? 2 * 60 * 1000 : mode === 'offline_cache' ? 7 * 24 * 60 * 60 * 1000 : 10 * 60 * 1000;
|
|
294
354
|
const cached = await readJson(artifact, null);
|
|
@@ -297,4 +357,69 @@ async function readCache(artifactDir, query, mode) {
|
|
|
297
357
|
const age_ms = Date.now() - Date.parse(cached.generated_at);
|
|
298
358
|
return { key, artifact, ttl_ms, hit: true, stale: age_ms > ttl_ms, age_ms, result: cached };
|
|
299
359
|
}
|
|
360
|
+
function queryBudget(mode, explicit) {
|
|
361
|
+
if (Number.isFinite(Number(explicit)))
|
|
362
|
+
return Math.max(1, Math.min(8, Math.floor(Number(explicit))));
|
|
363
|
+
if (mode === 'fast' || mode === 'url_acquisition' || mode === 'offline_cache')
|
|
364
|
+
return 1;
|
|
365
|
+
if (mode === 'balanced' || mode === 'x_search')
|
|
366
|
+
return 3;
|
|
367
|
+
if (mode === 'deep')
|
|
368
|
+
return 5;
|
|
369
|
+
return 8;
|
|
370
|
+
}
|
|
371
|
+
function hydrationBudget(mode, explicit) {
|
|
372
|
+
if (Number.isFinite(Number(explicit)))
|
|
373
|
+
return Math.max(0, Math.min(8, Math.floor(Number(explicit))));
|
|
374
|
+
if (mode === 'fast' || mode === 'url_acquisition' || mode === 'offline_cache')
|
|
375
|
+
return 1;
|
|
376
|
+
if (mode === 'balanced' || mode === 'x_search')
|
|
377
|
+
return 3;
|
|
378
|
+
if (mode === 'deep')
|
|
379
|
+
return 5;
|
|
380
|
+
return 8;
|
|
381
|
+
}
|
|
382
|
+
async function hydrateDiscoverySources(sources, artifactDir, intent, opts) {
|
|
383
|
+
const urls = [...new Set(sources
|
|
384
|
+
.filter((source) => source.acquisition_verdict !== 'verified_content')
|
|
385
|
+
.map((source) => source.canonical_url || source.original_url)
|
|
386
|
+
.filter((url) => Boolean(url)))]
|
|
387
|
+
.slice(0, opts.limit);
|
|
388
|
+
if (!urls.length)
|
|
389
|
+
return { sources: [], blockers: [], warnings: [] };
|
|
390
|
+
const rows = await raceSuperSearchOperation(Promise.all(urls.map((url) => sourceFromUrlFetch(url, artifactDir, intent, { allowLocal: opts.allowLocal, deadlineEpochMs: opts.deadlineEpochMs }))), opts.deadlineEpochMs);
|
|
391
|
+
const verified = rows.filter((row) => row.source.acquisition_verdict === 'verified_content').map((row) => row.source);
|
|
392
|
+
const blockers = rows.flatMap((row) => row.source.acquisition_verdict === 'verified_content' ? [] : row.blockers);
|
|
393
|
+
const warnings = rows.flatMap((row) => row.warnings);
|
|
394
|
+
return { sources: verified, blockers, warnings };
|
|
395
|
+
}
|
|
396
|
+
function resolveSuperSearchDeadline(input) {
|
|
397
|
+
const hard = Number(input.hardTimeoutMs);
|
|
398
|
+
const absolute = Number(input.deadlineEpochMs);
|
|
399
|
+
const candidates = [
|
|
400
|
+
Number.isFinite(hard) && hard > 0 ? Date.now() + hard : Number.POSITIVE_INFINITY,
|
|
401
|
+
Number.isFinite(absolute) && absolute > 0 ? absolute : Number.POSITIVE_INFINITY
|
|
402
|
+
];
|
|
403
|
+
const deadline = Math.min(...candidates);
|
|
404
|
+
return Number.isFinite(deadline) ? deadline : Date.now() + 120_000;
|
|
405
|
+
}
|
|
406
|
+
async function raceSuperSearchOperation(promise, deadlineEpochMs) {
|
|
407
|
+
const remainingMs = Math.max(0, Math.floor(deadlineEpochMs - Date.now()));
|
|
408
|
+
if (remainingMs <= 0)
|
|
409
|
+
throw new Error('research_cycle_timeout_exceeded');
|
|
410
|
+
let timer = null;
|
|
411
|
+
try {
|
|
412
|
+
return await Promise.race([
|
|
413
|
+
promise,
|
|
414
|
+
new Promise((_resolve, reject) => {
|
|
415
|
+
timer = setTimeout(() => reject(new Error('research_cycle_timeout_exceeded')), remainingMs);
|
|
416
|
+
timer.unref?.();
|
|
417
|
+
})
|
|
418
|
+
]);
|
|
419
|
+
}
|
|
420
|
+
finally {
|
|
421
|
+
if (timer)
|
|
422
|
+
clearTimeout(timer);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
300
425
|
//# sourceMappingURL=runtime.js.map
|
|
@@ -17,8 +17,16 @@ export function makeSource(opts) {
|
|
|
17
17
|
const now = nowIso();
|
|
18
18
|
const canonical = opts.url ? canonicalizeUrl(opts.url) : null;
|
|
19
19
|
const domain = canonical ? safeDomain(canonical) : null;
|
|
20
|
-
const
|
|
21
|
-
|
|
20
|
+
const verifiedArtifact = Boolean(opts.contentArtifact)
|
|
21
|
+
&& /^[a-f0-9]{32,}$/i.test(String(opts.contentSha256 || ''))
|
|
22
|
+
&& Number(opts.contentLength || 0) > 0;
|
|
23
|
+
const requestedVerified = opts.verdict === 'verified_content';
|
|
24
|
+
const verdict = requestedVerified && !verifiedArtifact ? 'weak_content' : opts.verdict;
|
|
25
|
+
const verified = verdict === 'verified_content';
|
|
26
|
+
const blockers = [
|
|
27
|
+
...(opts.blockers || []),
|
|
28
|
+
...(requestedVerified && !verifiedArtifact ? ['verified_content_artifact_missing'] : [])
|
|
29
|
+
];
|
|
22
30
|
return {
|
|
23
31
|
source_id: `src-${sha256(`${opts.providerId}:${canonical || opts.title}:${opts.snippet}`).slice(0, 12)}`,
|
|
24
32
|
provider_id: opts.providerId,
|
|
@@ -35,23 +43,56 @@ export function makeSource(opts) {
|
|
|
35
43
|
language: null,
|
|
36
44
|
snippet: opts.snippet,
|
|
37
45
|
content_artifact: opts.contentArtifact ?? null,
|
|
38
|
-
content_sha256: opts.contentSha256 ??
|
|
39
|
-
content_length: opts.contentLength ??
|
|
40
|
-
acquisition_verdict:
|
|
46
|
+
content_sha256: opts.contentSha256 ?? null,
|
|
47
|
+
content_length: opts.contentLength ?? null,
|
|
48
|
+
acquisition_verdict: verdict,
|
|
41
49
|
acquisition_path: opts.path,
|
|
42
50
|
authority_tier: opts.authority,
|
|
43
51
|
freshness_score: 0.5,
|
|
44
52
|
relevance_score: 0.6,
|
|
45
|
-
trust_score: verified ? 0.9 :
|
|
53
|
+
trust_score: verified ? 0.9 : verdict === 'weak_content' ? 0.55 : 0.35,
|
|
46
54
|
primary_source: opts.primary,
|
|
47
55
|
authenticated_source: false,
|
|
48
56
|
local_only_raw: false,
|
|
49
57
|
duplicate_cluster_id: null,
|
|
50
|
-
independence_cluster_id: domain || opts.providerId,
|
|
58
|
+
independence_cluster_id: independenceClusterForDomain(domain) || opts.providerId,
|
|
51
59
|
warnings: opts.warnings || [],
|
|
52
|
-
blockers
|
|
60
|
+
blockers
|
|
53
61
|
};
|
|
54
62
|
}
|
|
63
|
+
export function independenceClusterForDomain(value) {
|
|
64
|
+
const host = String(value || '').trim().toLowerCase().replace(/^\.+|\.+$/g, '');
|
|
65
|
+
if (!host)
|
|
66
|
+
return null;
|
|
67
|
+
const ownership = knownOwnershipCluster(host);
|
|
68
|
+
if (ownership)
|
|
69
|
+
return ownership;
|
|
70
|
+
const labels = host.split('.').filter(Boolean);
|
|
71
|
+
if (labels.length <= 2)
|
|
72
|
+
return host;
|
|
73
|
+
const publicSuffix = labels.slice(-2).join('.');
|
|
74
|
+
const multiLabelSuffixes = new Set([
|
|
75
|
+
'co.uk', 'org.uk', 'ac.uk', 'gov.uk', 'com.au', 'net.au', 'org.au',
|
|
76
|
+
'co.jp', 'ne.jp', 'or.jp', 'com.br', 'com.cn', 'com.sg', 'co.kr', 'co.nz'
|
|
77
|
+
]);
|
|
78
|
+
return multiLabelSuffixes.has(publicSuffix)
|
|
79
|
+
? labels.slice(-3).join('.')
|
|
80
|
+
: labels.slice(-2).join('.');
|
|
81
|
+
}
|
|
82
|
+
function knownOwnershipCluster(host) {
|
|
83
|
+
const groups = [
|
|
84
|
+
['owner:openai', ['openai.com', 'chatgpt.com']],
|
|
85
|
+
['owner:x', ['x.com', 'twitter.com']],
|
|
86
|
+
['owner:github', ['github.com', 'githubusercontent.com', 'githubassets.com']],
|
|
87
|
+
['owner:google', ['google.com', 'youtube.com', 'googleusercontent.com']],
|
|
88
|
+
['owner:microsoft', ['microsoft.com', 'azure.com', 'visualstudio.com']]
|
|
89
|
+
];
|
|
90
|
+
for (const [cluster, domains] of groups) {
|
|
91
|
+
if (domains.some((domain) => host === domain || host.endsWith(`.${domain}`)))
|
|
92
|
+
return cluster;
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
55
96
|
function canonicalizeUrl(raw) {
|
|
56
97
|
try {
|
|
57
98
|
const url = new URL(raw);
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
export const MIN_TEAM_REVIEWER_LANES = 5;
|
|
2
2
|
export const MIN_TEAM_REVIEW_STAGE_AGENT_SESSIONS = MIN_TEAM_REVIEWER_LANES;
|
|
3
3
|
export const MIN_TEAM_REVIEW_POLICY_TEXT = `Minimum Team review policy: run at least ${MIN_TEAM_REVIEWER_LANES} independent reviewer/QA validation lanes before integration or final, even when the requested reviewer role count is lower.`;
|
|
4
|
+
export const DEFAULT_OFFICIAL_REVIEWER_LANES = 1;
|
|
5
|
+
export const MAX_AUTOMATIC_OFFICIAL_REVIEWER_LANES = 2;
|
|
6
|
+
export const MAX_CRITICAL_OFFICIAL_REVIEWER_LANES = 3;
|
|
7
|
+
export const OFFICIAL_SUBAGENT_REVIEW_POLICY_TEXT = 'Official subagent review policy: start with one focused reviewer, expand to two only for independent review domains, and use at most three automatic reviewers for critical multi-domain risk. The parent owns integration and may honor a larger explicit operator request.';
|
|
8
|
+
export function officialSubagentReviewLaneBudget(input = {}) {
|
|
9
|
+
if (Number.isFinite(Number(input.explicit)) && Number(input.explicit) > 0) {
|
|
10
|
+
return { requested: Math.floor(Number(input.explicit)), source: 'explicit_operator' };
|
|
11
|
+
}
|
|
12
|
+
const domains = Math.max(0, Math.floor(Number(input.independentDomains || 0)));
|
|
13
|
+
const ceiling = input.critical === true ? MAX_CRITICAL_OFFICIAL_REVIEWER_LANES : MAX_AUTOMATIC_OFFICIAL_REVIEWER_LANES;
|
|
14
|
+
return {
|
|
15
|
+
requested: Math.max(DEFAULT_OFFICIAL_REVIEWER_LANES, Math.min(ceiling, domains || DEFAULT_OFFICIAL_REVIEWER_LANES)),
|
|
16
|
+
source: 'risk_scoped_automatic'
|
|
17
|
+
};
|
|
18
|
+
}
|
|
4
19
|
function numericCount(value, fallback = 0) {
|
|
5
20
|
const number = Number(value);
|
|
6
21
|
return Number.isFinite(number) ? Math.max(0, Math.floor(number)) : fallback;
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import fsp from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readJson, runProcess, writeJsonAtomic } from '../fsx.js';
|
|
4
|
+
const CODE_PACK_METADATA_PATHS = new Set([
|
|
5
|
+
'.sneakoscope/wiki/code-pack.json',
|
|
6
|
+
'.sneakoscope/wiki/code-pack.prev.json'
|
|
7
|
+
]);
|
|
8
|
+
const COMMIT_MARKER = '@SKS-CODE-PACK';
|
|
9
|
+
const ADVISORY_CACHE_SCHEMA = 'sks.code-pack-head-freshness-cache.v1';
|
|
10
|
+
const ADVISORY_CACHE_PATH = path.join('.sneakoscope', 'cache', 'code-pack-head-freshness.json');
|
|
11
|
+
export async function inspectCodePackHeadFreshness(root, packShaInput, opts = {}) {
|
|
12
|
+
const timeoutMs = Math.max(1, Math.floor(opts.timeoutMs ?? 5_000));
|
|
13
|
+
const startedAt = Date.now();
|
|
14
|
+
const packSha = normalizeGitSha(packShaInput);
|
|
15
|
+
const fastHead = await readGitHeadFromAdminFiles(root);
|
|
16
|
+
if (!packSha)
|
|
17
|
+
return staleWithCurrentHead(root, null, timeoutMs, fastHead, false, 'invalid_pack_sha');
|
|
18
|
+
if (fastHead === packSha)
|
|
19
|
+
return freshness(true, true, 'exact_head', fastHead, packSha, false, []);
|
|
20
|
+
// Only the non-blocking hook consumes this cache. Authoritative wiki
|
|
21
|
+
// validation always replays Git history and never trusts advisory state.
|
|
22
|
+
if (opts.advisoryCache && fastHead) {
|
|
23
|
+
const cached = await readAdvisoryCache(root, packSha, fastHead);
|
|
24
|
+
if (cached)
|
|
25
|
+
return cached;
|
|
26
|
+
}
|
|
27
|
+
// One common-path Git process returns HEAD plus every committed path after
|
|
28
|
+
// the pack was generated. Excluding all parents of packSha keeps packSha in
|
|
29
|
+
// the walk (including a root commit), so its presence proves ancestry. We
|
|
30
|
+
// keep scanning after the pack marker because a later merge can introduce
|
|
31
|
+
// sibling-branch commits that Git orders after packSha. `-m` exposes merge
|
|
32
|
+
// resolution paths and `--no-renames` makes touched paths auditable.
|
|
33
|
+
const history = await runProcess('git', [
|
|
34
|
+
'-c',
|
|
35
|
+
'core.quotepath=true',
|
|
36
|
+
'log',
|
|
37
|
+
'--topo-order',
|
|
38
|
+
'-m',
|
|
39
|
+
'--no-ext-diff',
|
|
40
|
+
`--format=${COMMIT_MARKER}%x09%H`,
|
|
41
|
+
'--name-status',
|
|
42
|
+
'--no-renames',
|
|
43
|
+
'HEAD',
|
|
44
|
+
'--not',
|
|
45
|
+
`${packSha}^@`,
|
|
46
|
+
'--'
|
|
47
|
+
], {
|
|
48
|
+
cwd: root,
|
|
49
|
+
timeoutMs,
|
|
50
|
+
maxOutputBytes: 64 * 1024,
|
|
51
|
+
env: gitEnvironment({
|
|
52
|
+
GIT_NO_REPLACE_OBJECTS: '1',
|
|
53
|
+
GIT_OPTIONAL_LOCKS: '0',
|
|
54
|
+
LC_ALL: 'C'
|
|
55
|
+
})
|
|
56
|
+
}).catch(() => null);
|
|
57
|
+
if (!history || history.code !== 0 || history.timedOut) {
|
|
58
|
+
return staleWithCurrentHead(root, packSha, remainingMs(startedAt, timeoutMs), fastHead, false, history?.timedOut ? 'git_timeout' : 'git_failed');
|
|
59
|
+
}
|
|
60
|
+
const parsed = parseHistory(history.stdout, packSha);
|
|
61
|
+
if (history.truncated || !parsed.currentSha || parsed.invalid) {
|
|
62
|
+
const currentSha = parsed.currentSha
|
|
63
|
+
|| fastHead
|
|
64
|
+
|| await readCurrentHead(root, remainingMs(startedAt, timeoutMs));
|
|
65
|
+
return freshness(false, false, history.truncated ? 'history_truncated' : 'history_parse_invalid', currentSha, packSha, false, parsed.changedPaths);
|
|
66
|
+
}
|
|
67
|
+
if (!parsed.sawPack) {
|
|
68
|
+
return freshness(false, true, 'pack_not_ancestor', parsed.currentSha, packSha, false, parsed.changedPaths);
|
|
69
|
+
}
|
|
70
|
+
const metadataOnly = parsed.changedPaths.every((value) => CODE_PACK_METADATA_PATHS.has(value));
|
|
71
|
+
const exactHead = parsed.currentSha === packSha;
|
|
72
|
+
const result = freshness(metadataOnly, true, metadataOnly ? 'metadata_only_history' : 'source_change_history', parsed.currentSha, packSha, metadataOnly && !exactHead, parsed.changedPaths);
|
|
73
|
+
if (opts.advisoryCache && fastHead === parsed.currentSha) {
|
|
74
|
+
await writeAdvisoryCache(root, result).catch(() => undefined);
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
function parseHistory(stdout, packSha) {
|
|
79
|
+
let currentSha = null;
|
|
80
|
+
let activeCommit = null;
|
|
81
|
+
let sawPack = false;
|
|
82
|
+
let invalid = false;
|
|
83
|
+
const changedPaths = [];
|
|
84
|
+
const seenPaths = new Set();
|
|
85
|
+
for (const line of String(stdout || '').split(/\r?\n/)) {
|
|
86
|
+
if (line === '')
|
|
87
|
+
continue;
|
|
88
|
+
const marker = line.match(/^@SKS-CODE-PACK\t([0-9a-f]{40,64})$/i);
|
|
89
|
+
if (marker) {
|
|
90
|
+
activeCommit = String(marker[1]).toLowerCase();
|
|
91
|
+
currentSha ||= activeCommit;
|
|
92
|
+
if (activeCommit === packSha)
|
|
93
|
+
sawPack = true;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (!activeCommit) {
|
|
97
|
+
invalid = true;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
const separator = line.indexOf('\t');
|
|
101
|
+
const status = separator > 0 ? line.slice(0, separator) : '';
|
|
102
|
+
const pathText = separator > 0 ? line.slice(separator + 1) : '';
|
|
103
|
+
if (!/^[A-Z][0-9]*$/.test(status) || !pathText) {
|
|
104
|
+
invalid = true;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
if (activeCommit === packSha)
|
|
108
|
+
continue;
|
|
109
|
+
// Do not trim Git paths: leading/trailing whitespace is meaningful and
|
|
110
|
+
// must never be normalized into an allowlisted metadata path.
|
|
111
|
+
for (const changedPath of pathText.split('\t')) {
|
|
112
|
+
if (!changedPath || seenPaths.has(changedPath))
|
|
113
|
+
continue;
|
|
114
|
+
seenPaths.add(changedPath);
|
|
115
|
+
changedPaths.push(changedPath);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return { currentSha, sawPack, invalid, changedPaths };
|
|
119
|
+
}
|
|
120
|
+
async function readAdvisoryCache(root, packSha, currentSha) {
|
|
121
|
+
const cached = await readJson(path.join(root, ADVISORY_CACHE_PATH), null).catch(() => null);
|
|
122
|
+
if (cached?.schema !== ADVISORY_CACHE_SCHEMA)
|
|
123
|
+
return null;
|
|
124
|
+
if (normalizeGitSha(cached.pack_sha) !== packSha || normalizeGitSha(cached.current_sha) !== currentSha)
|
|
125
|
+
return null;
|
|
126
|
+
const changedPaths = Array.isArray(cached.changed_paths)
|
|
127
|
+
? cached.changed_paths.filter((value) => typeof value === 'string').slice(0, 64)
|
|
128
|
+
: [];
|
|
129
|
+
const fresh = cached.fresh === true;
|
|
130
|
+
if (fresh && (cached.metadata_only_drift !== true || changedPaths.some((value) => !CODE_PACK_METADATA_PATHS.has(value)))) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
return freshness(fresh, true, 'advisory_cache', currentSha, packSha, fresh, changedPaths);
|
|
134
|
+
}
|
|
135
|
+
async function writeAdvisoryCache(root, result) {
|
|
136
|
+
if (!result.pack_sha || !result.current_sha)
|
|
137
|
+
return;
|
|
138
|
+
await writeJsonAtomic(path.join(root, ADVISORY_CACHE_PATH), {
|
|
139
|
+
schema: ADVISORY_CACHE_SCHEMA,
|
|
140
|
+
pack_sha: result.pack_sha,
|
|
141
|
+
current_sha: result.current_sha,
|
|
142
|
+
fresh: result.fresh,
|
|
143
|
+
reason: result.reason,
|
|
144
|
+
metadata_only_drift: result.metadata_only_drift,
|
|
145
|
+
changed_paths: result.changed_paths.slice(0, 64),
|
|
146
|
+
checked_at: new Date().toISOString()
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
async function staleWithCurrentHead(root, packSha, timeoutMs, knownCurrentSha = null, conclusive = true, reason = 'git_failed') {
|
|
150
|
+
const currentSha = knownCurrentSha || await readCurrentHead(root, timeoutMs);
|
|
151
|
+
return freshness(false, conclusive, reason, currentSha, packSha, false, []);
|
|
152
|
+
}
|
|
153
|
+
async function readCurrentHead(root, timeoutMs) {
|
|
154
|
+
if (timeoutMs <= 0)
|
|
155
|
+
return null;
|
|
156
|
+
const head = await runProcess('git', ['rev-parse', 'HEAD'], {
|
|
157
|
+
cwd: root,
|
|
158
|
+
timeoutMs,
|
|
159
|
+
maxOutputBytes: 4 * 1024,
|
|
160
|
+
env: gitEnvironment({
|
|
161
|
+
GIT_NO_REPLACE_OBJECTS: '1',
|
|
162
|
+
GIT_OPTIONAL_LOCKS: '0',
|
|
163
|
+
LC_ALL: 'C'
|
|
164
|
+
})
|
|
165
|
+
}).catch(() => null);
|
|
166
|
+
return head && head.code === 0 && !head.truncated ? normalizeGitSha(head.stdout) : null;
|
|
167
|
+
}
|
|
168
|
+
async function readGitHeadFromAdminFiles(root) {
|
|
169
|
+
const gitDir = await resolveGitDir(root);
|
|
170
|
+
if (!gitDir)
|
|
171
|
+
return null;
|
|
172
|
+
const headText = await readSmallText(path.join(gitDir, 'HEAD'), 4 * 1024);
|
|
173
|
+
if (!headText)
|
|
174
|
+
return null;
|
|
175
|
+
const detached = normalizeGitSha(headText);
|
|
176
|
+
if (detached)
|
|
177
|
+
return detached;
|
|
178
|
+
const symbolic = headText.match(/^ref:\s*(refs\/[^\r\n]+)\s*$/);
|
|
179
|
+
const ref = symbolic ? String(symbolic[1]) : '';
|
|
180
|
+
if (!safeGitRef(ref))
|
|
181
|
+
return null;
|
|
182
|
+
const commonDir = await resolveCommonDir(gitDir);
|
|
183
|
+
for (const base of [...new Set([gitDir, commonDir])]) {
|
|
184
|
+
const loose = await readLooseRef(base, ref);
|
|
185
|
+
if (loose)
|
|
186
|
+
return loose;
|
|
187
|
+
}
|
|
188
|
+
return readPackedRef(commonDir, ref);
|
|
189
|
+
}
|
|
190
|
+
async function resolveGitDir(root) {
|
|
191
|
+
const dotGit = path.join(root, '.git');
|
|
192
|
+
const stat = await fsp.stat(dotGit).catch(() => null);
|
|
193
|
+
if (!stat)
|
|
194
|
+
return null;
|
|
195
|
+
if (stat.isDirectory())
|
|
196
|
+
return dotGit;
|
|
197
|
+
if (!stat.isFile())
|
|
198
|
+
return null;
|
|
199
|
+
const text = await readSmallText(dotGit, 4 * 1024);
|
|
200
|
+
const match = text?.match(/^gitdir:\s*(.+?)\s*$/m);
|
|
201
|
+
return match ? path.resolve(path.dirname(dotGit), String(match[1])) : null;
|
|
202
|
+
}
|
|
203
|
+
async function resolveCommonDir(gitDir) {
|
|
204
|
+
const text = await readSmallText(path.join(gitDir, 'commondir'), 4 * 1024);
|
|
205
|
+
return text?.trim() ? path.resolve(gitDir, text.trim()) : gitDir;
|
|
206
|
+
}
|
|
207
|
+
async function readLooseRef(base, ref) {
|
|
208
|
+
const file = safeRefPath(base, ref);
|
|
209
|
+
if (!file)
|
|
210
|
+
return null;
|
|
211
|
+
return normalizeGitSha(await readSmallText(file, 4 * 1024));
|
|
212
|
+
}
|
|
213
|
+
async function readPackedRef(commonDir, ref) {
|
|
214
|
+
const text = await readSmallText(path.join(commonDir, 'packed-refs'), 4 * 1024 * 1024);
|
|
215
|
+
if (!text)
|
|
216
|
+
return null;
|
|
217
|
+
for (const line of text.split(/\r?\n/)) {
|
|
218
|
+
if (!line || line.startsWith('#') || line.startsWith('^'))
|
|
219
|
+
continue;
|
|
220
|
+
const separator = line.indexOf(' ');
|
|
221
|
+
if (separator <= 0 || line.slice(separator + 1) !== ref)
|
|
222
|
+
continue;
|
|
223
|
+
return normalizeGitSha(line.slice(0, separator));
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
async function readSmallText(file, maxBytes) {
|
|
228
|
+
const stat = await fsp.stat(file).catch(() => null);
|
|
229
|
+
if (!stat?.isFile() || stat.size > maxBytes)
|
|
230
|
+
return null;
|
|
231
|
+
return fsp.readFile(file, 'utf8').catch(() => null);
|
|
232
|
+
}
|
|
233
|
+
function safeGitRef(ref) {
|
|
234
|
+
return /^refs\/[A-Za-z0-9._/-]+$/.test(ref)
|
|
235
|
+
&& !ref.includes('..')
|
|
236
|
+
&& !ref.includes('//')
|
|
237
|
+
&& !ref.includes('@{')
|
|
238
|
+
&& !ref.endsWith('/')
|
|
239
|
+
&& !ref.endsWith('.')
|
|
240
|
+
&& !ref.endsWith('.lock');
|
|
241
|
+
}
|
|
242
|
+
function safeRefPath(base, ref) {
|
|
243
|
+
if (!safeGitRef(ref))
|
|
244
|
+
return null;
|
|
245
|
+
const candidate = path.resolve(base, ...ref.split('/'));
|
|
246
|
+
const relative = path.relative(path.resolve(base), candidate);
|
|
247
|
+
return relative && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative) ? candidate : null;
|
|
248
|
+
}
|
|
249
|
+
function remainingMs(startedAt, timeoutMs) {
|
|
250
|
+
return Math.max(0, timeoutMs - (Date.now() - startedAt));
|
|
251
|
+
}
|
|
252
|
+
function gitEnvironment(extra = {}) {
|
|
253
|
+
return {
|
|
254
|
+
GIT_ALTERNATE_OBJECT_DIRECTORIES: undefined,
|
|
255
|
+
GIT_COMMON_DIR: undefined,
|
|
256
|
+
GIT_CONFIG: undefined,
|
|
257
|
+
GIT_CONFIG_COUNT: '0',
|
|
258
|
+
GIT_CONFIG_GLOBAL: undefined,
|
|
259
|
+
GIT_CONFIG_NOSYSTEM: undefined,
|
|
260
|
+
GIT_CONFIG_PARAMETERS: undefined,
|
|
261
|
+
GIT_CONFIG_SYSTEM: undefined,
|
|
262
|
+
GIT_DIR: undefined,
|
|
263
|
+
GIT_DISCOVERY_ACROSS_FILESYSTEM: undefined,
|
|
264
|
+
GIT_EXTERNAL_DIFF: undefined,
|
|
265
|
+
GIT_GRAFT_FILE: undefined,
|
|
266
|
+
GIT_INDEX_FILE: undefined,
|
|
267
|
+
GIT_NAMESPACE: undefined,
|
|
268
|
+
GIT_OBJECT_DIRECTORY: undefined,
|
|
269
|
+
GIT_QUARANTINE_PATH: undefined,
|
|
270
|
+
GIT_REPLACE_REF_BASE: undefined,
|
|
271
|
+
GIT_SHALLOW_FILE: undefined,
|
|
272
|
+
GIT_WORK_TREE: undefined,
|
|
273
|
+
...extra
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function freshness(fresh, conclusive, reason, currentSha, packSha, metadataOnlyDrift, changedPaths) {
|
|
277
|
+
return {
|
|
278
|
+
fresh,
|
|
279
|
+
conclusive,
|
|
280
|
+
reason,
|
|
281
|
+
current_sha: currentSha,
|
|
282
|
+
pack_sha: packSha,
|
|
283
|
+
metadata_only_drift: metadataOnlyDrift,
|
|
284
|
+
changed_paths: changedPaths
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function normalizeGitSha(value) {
|
|
288
|
+
const text = String(value || '').trim();
|
|
289
|
+
return /^[0-9a-f]{40,64}$/i.test(text) && !/^0+$/.test(text) ? text.toLowerCase() : null;
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=code-pack-head-freshness.js.map
|
|
@@ -14,7 +14,7 @@ export const DEFAULT_TRIWIKI_MODULE_CARDS = [
|
|
|
14
14
|
moduleCard('doctor-dirty-repair', ['src/core/doctor/doctor-dirty-planner.ts', 'src/core/doctor/doctor-repair-postcheck.ts', 'src/scripts/doctor-dirty-*.ts'], ['doctor:dirty'], ['doctor-production'], 'high'),
|
|
15
15
|
moduleCard('startup-config-repair', ['src/core/doctor/*startup*.ts', 'src/scripts/doctor-startup-*.ts'], ['doctor:startup'], ['doctor-production'], 'high'),
|
|
16
16
|
moduleCard('context7-mcp', ['src/core/doctor/*context7*.ts', 'src/commands/context7.ts'], ['doctor:context7', 'context7:'], ['startup-mcp'], 'critical'),
|
|
17
|
-
moduleCard('supabase-mcp', ['src/core/doctor/*supabase*.ts', 'src/
|
|
17
|
+
moduleCard('supabase-mcp', ['src/core/doctor/*supabase*.ts', 'src/core/db-safety.ts', 'src/core/pipeline-internals/runtime-core.ts'], ['doctor:supabase', 'mad-db:', 'mad-sks:'], ['startup-mcp'], 'critical'),
|
|
18
18
|
moduleCard('native-capability', ['src/core/codex-native/**', 'src/scripts/native-*.ts'], ['native:', 'codex-native:'], ['native-capability'], 'high'),
|
|
19
19
|
moduleCard('secret-preservation', ['src/core/**/secret*.ts', 'src/scripts/secret-*.ts', 'safety-mutation-allowlist.json'], ['secret:', 'supabase-secret'], ['doctor-production'], 'critical'),
|
|
20
20
|
moduleCard('core-skill', ['.agents/skills/**', 'src/scripts/core-skill-*.ts'], ['core-skill:'], ['core-skill'], 'high'),
|
|
@@ -65,7 +65,14 @@ async function writeWrongnessLedgerUnlocked(root, ledger) {
|
|
|
65
65
|
export async function readCombinedWrongnessRecords(root, missionId = null) {
|
|
66
66
|
const project = await readWrongnessLedger(root, null);
|
|
67
67
|
const mission = missionId ? await readWrongnessLedger(root, missionId) : emptyWrongnessLedger('mission', missionId);
|
|
68
|
-
|
|
68
|
+
// The project ledger is also the cross-mission index, so it contains copies
|
|
69
|
+
// of mission-scoped records. A mission proof must inherit only truly global
|
|
70
|
+
// project records plus rows owned by that mission; otherwise unrelated old
|
|
71
|
+
// missions can block every future route forever.
|
|
72
|
+
const projectRecords = missionId
|
|
73
|
+
? project.records.filter((record) => !record.mission_id || record.mission_id === missionId)
|
|
74
|
+
: project.records;
|
|
75
|
+
return dedupeRecords([...projectRecords, ...mission.records]);
|
|
69
76
|
}
|
|
70
77
|
export async function addWrongnessRecord(root, input = {}, opts = {}) {
|
|
71
78
|
const row = asRecord(input);
|
|
@@ -291,7 +298,7 @@ export async function recordDbSafetyMismatchWrongness(root, input = {}) {
|
|
|
291
298
|
wrongness_kind: kind,
|
|
292
299
|
severity: kind === 'db_safety_false_negative' ? 'high' : 'medium',
|
|
293
300
|
claim: { text: `DB safety expected ${expected} but classified ${actual}.` },
|
|
294
|
-
detected_by: { source: 'db_safety_check', command: typeof row.command === 'string' ? row.command : '
|
|
301
|
+
detected_by: { source: 'db_safety_check', command: typeof row.command === 'string' ? row.command : '$DB internal safety check', artifact: typeof row.artifact === 'string' ? row.artifact : null, detail: typeof row.sql === 'string' ? row.sql : null },
|
|
295
302
|
root_cause: { category: 'missing_db_policy', explanation: 'A DB safety expectation did not match the current classifier output.' },
|
|
296
303
|
corrective_action: { summary: 'Adjust the policy/classifier or fixture expectation, then rerun DB safety validation.', required_evidence: ['db-operation-report.json'], patch_status: 'pending' },
|
|
297
304
|
links: { artifacts: typeof row.artifact === 'string' ? [row.artifact] : [] }
|