sneakoscope 7.3.0 → 7.6.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 +129 -10
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/cli/codex-app-command.js +1 -1
- package/dist/cli/command-manifest-lite.js +4 -1
- package/dist/cli/command-registry.js +2 -0
- package/dist/cli/install-helpers-codex-lb-chain.js +42 -0
- package/dist/cli/install-helpers-codex-lb-config.js +114 -9
- package/dist/cli/install-helpers-install-support.js +6 -16
- package/dist/cli/install-helpers.js +788 -600
- package/dist/cli/router.js +30 -2
- package/dist/commands/codex-app.js +37 -1
- package/dist/commands/codex-lb.js +491 -300
- package/dist/config/skills-manifest.json +57 -71
- package/dist/core/align/align-route.js +127 -0
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +8 -4
- package/dist/core/codex-app/codex-app-restart.js +83 -0
- package/dist/core/codex-app/codex-app-ui-state-snapshot.js +8 -4
- package/dist/core/codex-app/desktop-routing-snapshot.js +1 -1
- package/dist/core/codex-app/menubar/constants.js +5 -0
- package/dist/core/codex-app/menubar/generation-transaction-journal.js +1 -3
- package/dist/core/codex-app/menubar/installer.js +18 -0
- package/dist/core/codex-app/multi-provider-router.js +22 -10
- package/dist/core/codex-app/openrouter-activate.js +26 -1
- package/dist/core/codex-app.js +118 -26
- package/dist/core/codex-control/codex-app-server-runtime-env.js +86 -0
- package/dist/core/codex-control/codex-app-server-v2-client.js +78 -8
- package/dist/core/codex-control/codex-task-runner.js +2 -2
- package/dist/core/codex-lb/capability-runner.js +204 -0
- package/dist/core/codex-lb/capability-types.js +1 -0
- package/dist/core/codex-lb/codex-lb-env.js +9 -13
- package/dist/core/codex-lb/codex-lb-setup.js +45 -8
- package/dist/core/codex-lb/codex-lb-tool-catalog.js +52 -74
- package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +1 -1
- package/dist/core/codex-lb/desktop-auth-invariant.js +185 -0
- package/dist/core/codex-lb/desktop-bridge/client.js +34 -0
- package/dist/core/codex-lb/desktop-bridge/header-policy.js +106 -0
- package/dist/core/codex-lb/desktop-bridge/http-forward.js +101 -0
- package/dist/core/codex-lb/desktop-bridge/index.js +10 -0
- package/dist/core/codex-lb/desktop-bridge/launchd.js +81 -0
- package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +27 -0
- package/dist/core/codex-lb/desktop-bridge/security.js +274 -0
- package/dist/core/codex-lb/desktop-bridge/server.js +179 -0
- package/dist/core/codex-lb/desktop-bridge/state.js +119 -0
- package/dist/core/codex-lb/desktop-bridge/types.js +16 -0
- package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +151 -0
- package/dist/core/codex-lb/desktop-center-credentials.js +189 -0
- package/dist/core/codex-lb/desktop-controller.js +1410 -0
- package/dist/core/codex-lb/desktop-mode.js +32 -0
- package/dist/core/codex-lb/desktop-real-evidence.js +168 -0
- package/dist/core/codex-lb/desktop-service.js +613 -0
- package/dist/core/codex-lb/legacy-migration.js +575 -0
- package/dist/core/codex-lb/migration-receipt.js +246 -0
- package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +60 -0
- package/dist/core/codex-lb/probes/bridge-probe.js +75 -0
- package/dist/core/codex-lb/probes/catalog-probe.js +128 -0
- package/dist/core/codex-lb/probes/computer-use-probe.js +50 -0
- package/dist/core/codex-lb/probes/image-generation-probe.js +47 -0
- package/dist/core/codex-lb/probes/probe-evidence.js +39 -0
- package/dist/core/codex-lb/probes/voice-realtime-probe.js +44 -0
- package/dist/core/codex-lb/trusted-deep-evidence.js +403 -0
- package/dist/core/codex-native/core-skill-manifest.js +22 -6
- package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -1
- package/dist/core/commands/align-command.js +220 -0
- package/dist/core/commands/image-ux-review-command.js +280 -68
- package/dist/core/commands/naruto-command.js +257 -8
- package/dist/core/commands/ppt-command.js +2 -2
- package/dist/core/commands/telegram-command.js +402 -34
- package/dist/core/commands/triwiki-command.js +11 -1
- package/dist/core/commands/triwiki-graph-command.js +160 -0
- package/dist/core/commands/wiki-command.js +100 -20
- package/dist/core/doctor/skill-legacy-surface.js +1 -3
- package/dist/core/errors/message.js +3 -0
- package/dist/core/evidence/evidence-freshness.js +14 -0
- package/dist/core/feature-fixtures.js +9 -1
- package/dist/core/feature-registry.js +5 -3
- package/dist/core/fsx.js +7 -3
- package/dist/core/hooks-runtime/codex-commit-hooks-selftest.js +82 -0
- package/dist/core/hooks-runtime/context-graph-freshness-preflight.js +113 -0
- package/dist/core/hooks-runtime/hook-context.js +15 -2
- package/dist/core/hooks-runtime/managed-skill-generation-heal.js +46 -0
- package/dist/core/hooks-runtime/naruto-terminal-finalization.js +1 -0
- package/dist/core/hooks-runtime/official-subagent-lifecycle.js +1 -1
- package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
- package/dist/core/hooks-runtime.js +33 -89
- package/dist/core/image-ux-review/callout-extraction.js +6 -0
- package/dist/core/image-ux-review/imagegen-adapter.js +64 -23
- package/dist/core/image-ux-review/real-callout-extractor.js +1 -0
- package/dist/core/image-ux-review.js +230 -12
- package/dist/core/imagegen/codex-lb-imagegen-target.js +21 -7
- package/dist/core/imagegen/imagegen-capability.js +10 -4
- package/dist/core/imagegen/require-imagegen.js +29 -5
- package/dist/core/init/skills.js +25 -13
- package/dist/core/init.js +1 -1
- package/dist/core/install/installed-package-smoke.js +157 -4
- package/dist/core/managed-assets/managed-assets-manifest.js +2 -1
- package/dist/core/managed-path-safety.js +8 -10
- package/dist/core/mcp-config/backup.js +2 -4
- package/dist/core/mcp-config/config-reader.js +2 -4
- package/dist/core/mcp-config/scope.js +3 -5
- package/dist/core/naruto/context-graph-advisor-scope.js +242 -0
- package/dist/core/naruto/context-graph-advisor.js +0 -0
- package/dist/core/perf/release-latency-slo.js +12 -6
- package/dist/core/pipeline-internals/runtime-core.js +78 -0
- package/dist/core/pipeline-internals/runtime-gates.js +5 -2
- package/dist/core/policy/latest-version-guidance.js +113 -0
- package/dist/core/ppt.js +8 -8
- package/dist/core/preflight/parallel-preflight-engine.js +1 -1
- package/dist/core/proof/auto-finalize.js +98 -6
- package/dist/core/proof/route-proof-gate.js +12 -1
- package/dist/core/proof/route-proof-policy.js +8 -8
- package/dist/core/release/gate-manifest.js +32 -1
- package/dist/core/release/npm-stage-contract.js +21 -0
- package/dist/core/release/package-size-budget.js +2 -2
- package/dist/core/release/release-gate-contract.js +5 -0
- package/dist/core/release/release-proof-io.js +1 -3
- package/dist/core/release/release-real-contract.js +5 -4
- package/dist/core/release/release-stamp-proof.js +1 -3
- package/dist/core/release/stage-publish.js +27 -0
- package/dist/core/remote/audit-idempotency.js +50 -18
- package/dist/core/remote/codex-public-activity.js +283 -0
- package/dist/core/remote/index.js +1 -0
- package/dist/core/remote/ssh-worker-client.js +4 -1
- package/dist/core/remote/worker.js +206 -27
- package/dist/core/research/research-adversarial-review.js +1 -3
- package/dist/core/research/research-claim-synthesizer.js +1 -3
- package/dist/core/research/research-falsification-runner.js +1 -3
- package/dist/core/research/research-source-evidence.js +1 -3
- package/dist/core/responses-stream.js +65 -19
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/design-policy.js +7 -2
- package/dist/core/routes/dollar-manifest-lite.js +2 -4
- package/dist/core/routes/evidence.js +1 -1
- package/dist/core/routes.js +30 -10
- package/dist/core/safety/command-contract/contracts.js +2 -0
- package/dist/core/safety/command-contract/types.js +1 -1
- package/dist/core/search/context-graph-seeds.js +205 -0
- package/dist/core/search/context.js +0 -0
- package/dist/core/search/provider.js +2 -2
- package/dist/core/secret-redaction.js +6 -0
- package/dist/core/subagents/naruto-help-contract.js +2 -1
- package/dist/core/subagents/naruto-host-credentials.js +161 -0
- package/dist/core/subagents/official-subagent-preparation.js +4 -1
- package/dist/core/subagents/official-subagent-prompt.js +44 -2
- package/dist/core/subagents/official-subagent-runner.js +26 -8
- package/dist/core/subagents/triwiki-attention.js +135 -123
- package/dist/core/telegram/bot-api.js +85 -10
- package/dist/core/telegram/center-snapshot.js +718 -0
- package/dist/core/telegram/config.js +158 -31
- package/dist/core/telegram/hub.js +288 -33
- package/dist/core/telegram/index.js +2 -0
- package/dist/core/telegram/ingress-spool.js +419 -0
- package/dist/core/telegram/ledgers.js +188 -29
- package/dist/core/telegram/messages.js +26 -6
- package/dist/core/telegram/owner-lock.js +10 -7
- package/dist/core/telegram/runtime-projection.js +38 -3
- package/dist/core/telegram/runtime.js +298 -63
- package/dist/core/telegram/service.js +137 -8
- package/dist/core/telegram/setup.js +291 -73
- package/dist/core/text/strings.js +3 -0
- package/dist/core/triwiki/code-pack.js +12 -120
- package/dist/core/triwiki/context-graph/compiler/cache-key.js +277 -0
- package/dist/core/triwiki/context-graph/compiler/extract.js +104 -0
- package/dist/core/triwiki/context-graph/compiler/freshness.js +108 -0
- package/dist/core/triwiki/context-graph/compiler/index.js +237 -0
- package/dist/core/triwiki/context-graph/compiler/merge.js +0 -0
- package/dist/core/triwiki/context-graph/compiler/serialize.js +115 -0
- package/dist/core/triwiki/context-graph/contracts.js +236 -0
- package/dist/core/triwiki/context-graph/extractors/code/builders.js +150 -0
- package/dist/core/triwiki/context-graph/extractors/code/declarations.js +161 -0
- package/dist/core/triwiki/context-graph/extractors/code/index.js +265 -0
- package/dist/core/triwiki/context-graph/extractors/code/inventory.js +237 -0
- package/dist/core/triwiki/context-graph/extractors/code/module-graph.js +252 -0
- package/dist/core/triwiki/context-graph/extractors/code/modules.js +79 -0
- package/dist/core/triwiki/context-graph/extractors/code/references.js +184 -0
- package/dist/core/triwiki/context-graph/extractors/code/selection.js +100 -0
- package/dist/core/triwiki/context-graph/extractors/code/ts-config.js +161 -0
- package/dist/core/triwiki/context-graph/extractors/code/types.js +18 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/claims.js +289 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/index.js +54 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/proof-index.js +213 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/proofs.js +266 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/redaction.js +177 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/shared.js +0 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/sources.js +154 -0
- package/dist/core/triwiki/context-graph/extractors/index.js +7 -0
- package/dist/core/triwiki/context-graph/extractors/topology/commands.js +207 -0
- package/dist/core/triwiki/context-graph/extractors/topology/gate-edges.js +201 -0
- package/dist/core/triwiki/context-graph/extractors/topology/gates.js +182 -0
- package/dist/core/triwiki/context-graph/extractors/topology/globs.js +124 -0
- package/dist/core/triwiki/context-graph/extractors/topology/index.js +92 -0
- package/dist/core/triwiki/context-graph/extractors/topology/routes.js +135 -0
- package/dist/core/triwiki/context-graph/extractors/topology/shared.js +215 -0
- package/dist/core/triwiki/context-graph/graph-index.js +143 -0
- package/dist/core/triwiki/context-graph/ids.js +0 -0
- package/dist/core/triwiki/context-graph/lint/index.js +0 -0
- package/dist/core/triwiki/context-graph/lint/rules.js +232 -0
- package/dist/core/triwiki/context-graph/lint/warnings.js +93 -0
- package/dist/core/triwiki/context-graph/paths.js +116 -0
- package/dist/core/triwiki/context-graph/profiles.js +78 -0
- package/dist/core/triwiki/context-graph/projections/anchors.js +91 -0
- package/dist/core/triwiki/context-graph/projections/attention.js +58 -0
- package/dist/core/triwiki/context-graph/projections/code-pack-workspace.js +62 -0
- package/dist/core/triwiki/context-graph/projections/code-pack.js +144 -0
- package/dist/core/triwiki/context-graph/projections/index.js +7 -0
- package/dist/core/triwiki/context-graph/projections/module-view.js +140 -0
- package/dist/core/triwiki/context-graph/projections/node-summary.js +118 -0
- package/dist/core/triwiki/context-graph/projections/pack-contract.js +6 -0
- package/dist/core/triwiki/context-graph/query/explain.js +0 -0
- package/dist/core/triwiki/context-graph/query/index.js +178 -0
- package/dist/core/triwiki/context-graph/query/load.js +116 -0
- package/dist/core/triwiki/context-graph/query/pack.js +117 -0
- package/dist/core/triwiki/context-graph/query/rank.js +142 -0
- package/dist/core/triwiki/context-graph/query/ranking-config.js +64 -0
- package/dist/core/triwiki/context-graph/query/seeds.js +241 -0
- package/dist/core/triwiki/context-graph/query/snapshot-cache.js +72 -0
- package/dist/core/triwiki/context-graph/query/traverse.js +154 -0
- package/dist/core/triwiki/context-graph/query-types.js +29 -0
- package/dist/core/triwiki/context-graph/store/compile-lock.js +21 -0
- package/dist/core/triwiki/context-graph/store/event-log.js +48 -0
- package/dist/core/triwiki/context-graph/store/fragment-cache.js +85 -0
- package/dist/core/triwiki/context-graph/store/graph-status.js +85 -0
- package/dist/core/triwiki/context-graph/store/snapshot-store.js +155 -0
- package/dist/core/triwiki/triwiki-proof-bank-index-repair.js +115 -0
- package/dist/core/triwiki/triwiki-proof-bank-index-store.js +290 -0
- package/dist/core/triwiki/triwiki-proof-bank-index.js +126 -0
- package/dist/core/triwiki/triwiki-proof-bank.js +7 -1
- package/dist/core/verification/context-graph-affected.js +271 -0
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/AlertFactory.swift +11 -3
- package/dist/native/sks-menubar/Sources/AppDelegate.swift +9 -0
- package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +25 -3
- package/dist/native/sks-menubar/Sources/ControlKit.swift +19 -8
- package/dist/native/sks-menubar/Sources/DiagnosticsViewController.swift +1 -2
- package/dist/native/sks-menubar/Sources/MCPServersViewController.swift +45 -17
- package/dist/native/sks-menubar/Sources/OverviewSummary.swift +162 -0
- package/dist/native/sks-menubar/Sources/OverviewViewController.swift +136 -190
- package/dist/native/sks-menubar/Sources/ProcessClient.swift +107 -11
- package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +5 -1
- package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +16 -4
- package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +4 -1
- package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +131 -0
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +288 -341
- package/dist/native/sks-menubar/Sources/RemoteTelegramCenterState.swift +447 -0
- package/dist/native/sks-menubar/Sources/RemoteTelegramRendering.swift +484 -0
- package/dist/native/sks-menubar/Sources/RemoteTelegramViewController.swift +364 -115
- package/dist/native/sks-menubar/Sources/SettingsViewController.swift +73 -12
- package/dist/native/sks-menubar/Sources/SidebarItem.swift +3 -3
- package/dist/native/sks-menubar/Sources/StatusItemController.swift +13 -13
- package/dist/native/sks-menubar/Sources/TelegramHubSupervisor.swift +469 -0
- package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +1 -6
- package/dist/native/sks-menubar/Tests/AppRuntimeTestSupport.swift +12 -0
- package/dist/native/sks-menubar/Tests/NativeTelegramRegressionRunner.swift +55 -0
- package/dist/native/sks-menubar/Tests/ProcessClientTests.swift +33 -0
- package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +142 -0
- package/dist/native/sks-menubar/Tests/RemoteTelegramCenterStateTests.swift +56 -0
- package/dist/native/sks-menubar/Tests/TelegramHubSupervisorTests.swift +55 -0
- package/dist/scripts/codex-lb-catalog-passthrough-check.js +120 -0
- package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +169 -0
- package/dist/scripts/codex-lb-desktop-bridge-check.js +394 -0
- package/dist/scripts/codex-lb-desktop-bridge-latency-check.js +196 -0
- package/dist/scripts/codex-lb-desktop-capabilities-check.js +287 -0
- package/dist/scripts/codex-lb-desktop-real-evidence-check.js +123 -0
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +10 -3
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +81 -40
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +99 -37
- package/dist/scripts/context-graph-check.js +191 -0
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +1 -1
- package/dist/scripts/gate-policy-audit-check.js +1 -1
- package/dist/scripts/helper-dedup-check.js +0 -2
- package/dist/scripts/installed-package-smoke-check.js +4 -1
- package/dist/scripts/latest-version-guidance-check.js +74 -0
- package/dist/scripts/release-metadata-check.js +21 -4
- package/dist/scripts/release-real-check.js +7 -0
- package/dist/scripts/ux-review-imagegen-blackbox-check.js +25 -1
- package/dist/scripts/ux-review-run-wires-imagegen-check.js +9 -1
- package/package.json +8 -3
- package/release-gates.v2.json +176 -1
- package/runtime-required-scripts.json +30 -0
- package/schemas/triwiki/context-graph.schema.json +119 -0
- package/dist/cli/install-helpers-codex-lb-selftest-chain.js +0 -112
- package/dist/cli/install-helpers-codex-lb-selftest.js +0 -481
- package/dist/core/triwiki/code-index-scanner.js +0 -309
|
@@ -13,7 +13,8 @@ export function buildNarutoHelpResult() {
|
|
|
13
13
|
'sks naruto run "<task>" [--agents N] [--max-threads N] [--trusted-project] [--json]',
|
|
14
14
|
'sks naruto status [latest|M-...] [--json]',
|
|
15
15
|
'sks naruto subagents [latest|M-...] [--json]',
|
|
16
|
-
'sks naruto proof [latest|M-...] [--json]'
|
|
16
|
+
'sks naruto proof [latest|M-...] [--json]',
|
|
17
|
+
'sks naruto parent-summary --mission M-... --stdin [--json] (active Codex App Naruto only)'
|
|
17
18
|
],
|
|
18
19
|
commands: [...NARUTO_ACTIONS],
|
|
19
20
|
default_requested_subagents: DEFAULT_AUTOMATIC_SUBAGENT_COUNT,
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
export const NARUTO_AUTH_MODES = ['managed', 'host'];
|
|
2
|
+
const IDENTIFIER_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
3
|
+
export const NARUTO_EFFORT_TIERS = ['minimal', 'low', 'medium', 'high', 'max'];
|
|
4
|
+
function readFlagValue(args, name) {
|
|
5
|
+
const inline = args.find((arg) => arg.startsWith(`${name}=`));
|
|
6
|
+
if (inline)
|
|
7
|
+
return inline.slice(name.length + 1);
|
|
8
|
+
const index = args.indexOf(name);
|
|
9
|
+
if (index >= 0) {
|
|
10
|
+
const next = args[index + 1];
|
|
11
|
+
if (next !== undefined && !next.startsWith('-'))
|
|
12
|
+
return next;
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
function resolve(args, env, flag, envKey) {
|
|
17
|
+
const fromFlag = readFlagValue(args, flag);
|
|
18
|
+
if (fromFlag !== null && fromFlag !== '')
|
|
19
|
+
return { value: fromFlag, source: 'flag' };
|
|
20
|
+
const fromEnv = env[envKey];
|
|
21
|
+
if (typeof fromEnv === 'string' && fromEnv.trim())
|
|
22
|
+
return { value: fromEnv.trim(), source: 'env' };
|
|
23
|
+
return { value: null, source: 'default' };
|
|
24
|
+
}
|
|
25
|
+
function validIdentifier(value) {
|
|
26
|
+
return IDENTIFIER_RE.test(value);
|
|
27
|
+
}
|
|
28
|
+
export function resolveNarutoCredentialPolicy(input) {
|
|
29
|
+
const args = input.args ?? [];
|
|
30
|
+
const env = input.env ?? process.env;
|
|
31
|
+
const warnings = [];
|
|
32
|
+
const blockers = [];
|
|
33
|
+
const sources = {};
|
|
34
|
+
const authModeRaw = resolve(args, env, '--auth-mode', 'SKS_NARUTO_AUTH_MODE');
|
|
35
|
+
let authMode = 'managed';
|
|
36
|
+
if (authModeRaw.value !== null) {
|
|
37
|
+
if (NARUTO_AUTH_MODES.includes(authModeRaw.value)) {
|
|
38
|
+
authMode = authModeRaw.value;
|
|
39
|
+
sources.authMode = authModeRaw.source;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
blockers.push(`naruto_auth_mode_invalid:${authModeRaw.value}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (sources.authMode === undefined)
|
|
46
|
+
sources.authMode = 'default';
|
|
47
|
+
const providerRaw = resolve(args, env, '--model-provider', 'SKS_NARUTO_MODEL_PROVIDER');
|
|
48
|
+
let modelProvider = authMode === 'host' ? null : 'openai';
|
|
49
|
+
sources.modelProvider = 'default';
|
|
50
|
+
if (providerRaw.value !== null) {
|
|
51
|
+
if (!validIdentifier(providerRaw.value)) {
|
|
52
|
+
blockers.push(`naruto_model_provider_invalid:${providerRaw.value.slice(0, 32)}`);
|
|
53
|
+
}
|
|
54
|
+
else if (authMode === 'managed') {
|
|
55
|
+
blockers.push('naruto_model_provider_requires_host_auth_mode');
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
modelProvider = providerRaw.value;
|
|
59
|
+
sources.modelProvider = providerRaw.source;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const noForcedLogin = args.includes('--no-forced-login-method')
|
|
63
|
+
|| String(env.SKS_NARUTO_FORCED_LOGIN_METHOD ?? '').toLowerCase() === 'none';
|
|
64
|
+
let forcedLoginMethod = 'chatgpt';
|
|
65
|
+
sources.forcedLoginMethod = 'default';
|
|
66
|
+
if (authMode === 'host') {
|
|
67
|
+
forcedLoginMethod = null;
|
|
68
|
+
sources.forcedLoginMethod = sources.authMode;
|
|
69
|
+
}
|
|
70
|
+
else if (noForcedLogin) {
|
|
71
|
+
forcedLoginMethod = null;
|
|
72
|
+
sources.forcedLoginMethod = args.includes('--no-forced-login-method') ? 'flag' : 'env';
|
|
73
|
+
warnings.push('naruto_forced_login_method_released_without_host_auth_mode');
|
|
74
|
+
}
|
|
75
|
+
const models = [
|
|
76
|
+
{ key: 'parentModel', flag: '--parent-model', envKey: 'SKS_NARUTO_PARENT_MODEL', fallback: input.defaultParentModel, effort: false },
|
|
77
|
+
{ key: 'parentEffort', flag: '--parent-effort', envKey: 'SKS_NARUTO_PARENT_EFFORT', fallback: input.defaultParentEffort, effort: true },
|
|
78
|
+
{ key: 'subagentModel', flag: '--subagent-model', envKey: 'SKS_NARUTO_SUBAGENT_MODEL', fallback: input.defaultSubagentModel, effort: false },
|
|
79
|
+
{ key: 'subagentEffort', flag: '--subagent-effort', envKey: 'SKS_NARUTO_SUBAGENT_EFFORT', fallback: input.defaultSubagentEffort, effort: true }
|
|
80
|
+
];
|
|
81
|
+
const resolvedModels = {};
|
|
82
|
+
for (const entry of models) {
|
|
83
|
+
const raw = resolve(args, env, entry.flag, entry.envKey);
|
|
84
|
+
if (raw.value === null) {
|
|
85
|
+
resolvedModels[entry.key] = entry.fallback;
|
|
86
|
+
sources[entry.key] = 'default';
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const ok = entry.effort
|
|
90
|
+
? NARUTO_EFFORT_TIERS.includes(raw.value)
|
|
91
|
+
: validIdentifier(raw.value);
|
|
92
|
+
if (!ok) {
|
|
93
|
+
blockers.push(`naruto_${String(entry.key)}_invalid:${raw.value.slice(0, 32)}`);
|
|
94
|
+
resolvedModels[entry.key] = entry.fallback;
|
|
95
|
+
sources[entry.key] = 'default';
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
resolvedModels[entry.key] = raw.value;
|
|
99
|
+
sources[entry.key] = raw.source;
|
|
100
|
+
}
|
|
101
|
+
const envKeyRaw = resolve(args, env, '--provider-env-key', 'SKS_NARUTO_PROVIDER_ENV_KEY');
|
|
102
|
+
let providerEnvKey = null;
|
|
103
|
+
sources.providerEnvKey = 'default';
|
|
104
|
+
if (envKeyRaw.value !== null) {
|
|
105
|
+
if (!/^[A-Z][A-Z0-9_]{0,63}$/.test(envKeyRaw.value)) {
|
|
106
|
+
blockers.push(`naruto_provider_env_key_invalid:${envKeyRaw.value.slice(0, 32)}`);
|
|
107
|
+
}
|
|
108
|
+
else if (authMode === 'managed') {
|
|
109
|
+
blockers.push('naruto_provider_env_key_requires_host_auth_mode');
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
providerEnvKey = envKeyRaw.value;
|
|
113
|
+
sources.providerEnvKey = envKeyRaw.source;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (authMode === 'host' && modelProvider === null) {
|
|
117
|
+
warnings.push('naruto_host_auth_mode_without_explicit_model_provider');
|
|
118
|
+
}
|
|
119
|
+
if (authMode === 'host' && providerEnvKey !== null && env[providerEnvKey] === undefined) {
|
|
120
|
+
blockers.push(`naruto_provider_env_key_absent:${providerEnvKey}`);
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
schema: 'sks.naruto-credential-policy.v1',
|
|
124
|
+
authMode,
|
|
125
|
+
modelProvider,
|
|
126
|
+
forcedLoginMethod,
|
|
127
|
+
providerEnvKey,
|
|
128
|
+
parentModel: String(resolvedModels.parentModel),
|
|
129
|
+
parentEffort: String(resolvedModels.parentEffort),
|
|
130
|
+
subagentModel: String(resolvedModels.subagentModel),
|
|
131
|
+
subagentEffort: String(resolvedModels.subagentEffort),
|
|
132
|
+
sources,
|
|
133
|
+
warnings,
|
|
134
|
+
blockers
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
export function narutoCredentialConfigArgs(policy) {
|
|
138
|
+
const out = [];
|
|
139
|
+
if (policy.modelProvider)
|
|
140
|
+
out.push('-c', `model_provider="${policy.modelProvider}"`);
|
|
141
|
+
if (policy.forcedLoginMethod)
|
|
142
|
+
out.push('-c', `forced_login_method="${policy.forcedLoginMethod}"`);
|
|
143
|
+
return out;
|
|
144
|
+
}
|
|
145
|
+
export function narutoCredentialPolicyReceipt(policy) {
|
|
146
|
+
return {
|
|
147
|
+
schema: policy.schema,
|
|
148
|
+
auth_mode: policy.authMode,
|
|
149
|
+
model_provider: policy.modelProvider,
|
|
150
|
+
forced_login_method: policy.forcedLoginMethod,
|
|
151
|
+
provider_env_key: policy.providerEnvKey,
|
|
152
|
+
parent_model: policy.parentModel,
|
|
153
|
+
parent_effort: policy.parentEffort,
|
|
154
|
+
subagent_model: policy.subagentModel,
|
|
155
|
+
subagent_effort: policy.subagentEffort,
|
|
156
|
+
sources: policy.sources,
|
|
157
|
+
warnings: policy.warnings,
|
|
158
|
+
blockers: policy.blockers,
|
|
159
|
+
credential_handled_by: policy.authMode === 'host' ? 'host_config_toml_provider_block' : 'sks_managed_chatgpt_login'
|
|
160
|
+
};
|
|
161
|
+
}
|
|
@@ -151,7 +151,10 @@ async function prepareOfficialSubagentMissionLocked(input) {
|
|
|
151
151
|
triwikiAttention,
|
|
152
152
|
recommendedAgents: suggestedAgents,
|
|
153
153
|
roleModelPreferences: roleModelPreferences.store.roles,
|
|
154
|
-
activeMainModel
|
|
154
|
+
activeMainModel,
|
|
155
|
+
parentOutputMode: mode === 'naruto' && input.sessionScope ? 'app_naruto_stdin' : 'raw_json',
|
|
156
|
+
missionId: input.missionId,
|
|
157
|
+
workflowRunId
|
|
155
158
|
});
|
|
156
159
|
const selectedAgentPlan = officialSubagentOnDemandRolePlan(suggestedAgents);
|
|
157
160
|
const agentRouting = Object.fromEntries(Object.entries(selectedAgentPlan).map(([name, config]) => {
|
|
@@ -45,6 +45,9 @@ export function buildOfficialSubagentPrompt(input) {
|
|
|
45
45
|
const activeMainModel = normalizedActiveMainModel(input.activeMainModel);
|
|
46
46
|
const inheritActiveMainOntoChildren = childInheritsActiveMainModel(activeMainModel?.model);
|
|
47
47
|
const spawnModelRouting = renderSpawnModelRouting(activeMainModel);
|
|
48
|
+
const parentOutputMode = input.parentOutputMode === 'app_naruto_stdin'
|
|
49
|
+
? 'app_naruto_stdin'
|
|
50
|
+
: 'raw_json';
|
|
48
51
|
const rows = resolvedSlices.map(({ slice, agentName }, index) => {
|
|
49
52
|
const mode = slice.readOnly ? 'read-only' : 'use the parent permission mode';
|
|
50
53
|
const paths = (slice.paths || []).map((entry) => String(entry).trim()).filter(Boolean);
|
|
@@ -160,7 +163,13 @@ ${String(input.goal || '').trim()}
|
|
|
160
163
|
Slices:
|
|
161
164
|
${rows || '(parent decomposition required before any subagent is spawned)'}
|
|
162
165
|
|
|
163
|
-
|
|
166
|
+
${parentOutputMode === 'app_naruto_stdin'
|
|
167
|
+
? renderAppNarutoParentOutput(input.missionId, input.workflowRunId)
|
|
168
|
+
: renderRawJsonParentOutput()}
|
|
169
|
+
`.trim();
|
|
170
|
+
}
|
|
171
|
+
function renderRawJsonParentOutput() {
|
|
172
|
+
return `Final parent output:
|
|
164
173
|
- return one JSON object as the final message; prose outside that object is not completion evidence
|
|
165
174
|
- use this exact schema so SKS can correlate every stopped agent thread with a trustworthy parent outcome:
|
|
166
175
|
{
|
|
@@ -200,7 +209,40 @@ Final parent output:
|
|
|
200
209
|
- if changed_files is non-empty, include at least one passed named check or a specifically justified not_applicable verification row
|
|
201
210
|
- use empty artifacts/capabilities_used arrays when no host capability was used; SKS overwrites these fields with observed Codex JSONL evidence before persistence
|
|
202
211
|
- keep completion summary and Honest Mode wording inside the JSON fields; do not add prose outside the object
|
|
203
|
-
|
|
212
|
+
`;
|
|
213
|
+
}
|
|
214
|
+
function renderAppNarutoParentOutput(missionId, workflowRunId) {
|
|
215
|
+
const mission = String(missionId || '').trim();
|
|
216
|
+
const runId = String(workflowRunId || '').trim();
|
|
217
|
+
return `Final parent output for this active Codex App Naruto run:
|
|
218
|
+
- build one exact JSON object using the strict sks.subagent-parent-summary.v1 schema below, with run_id=${JSON.stringify(runId || 'workflow_run_id from subagent-plan.json')}
|
|
219
|
+
- send that object only through stdin to \`sks naruto parent-summary --mission ${mission || '<mission-id>'} --stdin --json\`; this command is the sole parent-summary commit path
|
|
220
|
+
- do not expose, paste, quote, embed, or fence the JSON in the user-visible response
|
|
221
|
+
- only after the command accepts the object, return concise Markdown in the user's language with completion summary, verification, remaining gaps/blockers, and Honest Mode
|
|
222
|
+
- if the parent status, any thread outcome, or any blocker is blocked/failed, state the blocker or failure first and do not use completion or success wording
|
|
223
|
+
- a successful visible response must contain an explicit completion summary and Honest Mode assessment; hard-blocked/failed responses state the blocker first instead
|
|
224
|
+
- use this exact object schema for the stdin submission:
|
|
225
|
+
{
|
|
226
|
+
"schema": "sks.subagent-parent-summary.v1",
|
|
227
|
+
"run_id": "workflow_run_id from subagent-plan.json",
|
|
228
|
+
"status": "completed|blocked|failed",
|
|
229
|
+
"summary": "Concise integrated result and Honest Mode assessment.",
|
|
230
|
+
"thread_outcomes": [
|
|
231
|
+
{ "thread_id": "official agent/thread id", "status": "completed|blocked|failed", "summary": "slice result" }
|
|
232
|
+
],
|
|
233
|
+
"changed_files": [],
|
|
234
|
+
"verification": [
|
|
235
|
+
{ "name": "focused check", "status": "passed|not_applicable", "reason": "required when not_applicable" }
|
|
236
|
+
],
|
|
237
|
+
"artifacts": [],
|
|
238
|
+
"capabilities_used": [],
|
|
239
|
+
"blockers": []
|
|
240
|
+
}
|
|
241
|
+
- include one thread_outcomes row for every requested subagent; a SubagentStop event alone never proves success
|
|
242
|
+
- copy workflow_run_id from subagent-plan.json into run_id exactly so delayed or stale summaries cannot bind to another run
|
|
243
|
+
- if changed_files is non-empty, include at least one passed named check or a specifically justified not_applicable verification row
|
|
244
|
+
- use empty artifacts/capabilities_used arrays when no host capability was used; SKS replaces these fields with observed Codex JSONL evidence before canonical persistence
|
|
245
|
+
`;
|
|
204
246
|
}
|
|
205
247
|
function renderRoleModelPreferenceMetadata(preferences, activeMainModel) {
|
|
206
248
|
const rows = Object.entries(preferences || {}).map(([role, preference]) => ({
|
|
@@ -9,6 +9,7 @@ import { resolveOfficialCodexPackageRuntime } from '../codex-runtime/resolve-cod
|
|
|
9
9
|
import { withFileLock } from '../locks/file-lock.js';
|
|
10
10
|
import { HOST_CAPABILITY_HOOK_PENDING_RUNTIME_FILENAME, HOST_CAPABILITY_MCP_SERVER, createHostCapabilityHookPendingRuntime, createHostCapabilityEventCollector, hostCapabilityCodexConfigArgs, inspectHostCapabilityRuntime, requestHostCapabilities } from '../agent-bridge/host-capability-runtime.js';
|
|
11
11
|
import { uniqueStringsSorted as uniqueStrings } from '../text/strings.js';
|
|
12
|
+
import { narutoCredentialConfigArgs, resolveNarutoCredentialPolicy } from './naruto-host-credentials.js';
|
|
12
13
|
export const OFFICIAL_SUBAGENT_WORKFLOW_SCHEMA = 'sks.subagent-workflow.v1';
|
|
13
14
|
function officialSubagentMissionDir(root, missionId) {
|
|
14
15
|
return path.join(root, '.sneakoscope', 'missions', missionId);
|
|
@@ -82,23 +83,33 @@ export function codexAppSessionKey(env = process.env) {
|
|
|
82
83
|
const threadId = String(env.CODEX_THREAD_ID || '').trim();
|
|
83
84
|
return threadId || null;
|
|
84
85
|
}
|
|
86
|
+
export function defaultNarutoCredentialPolicy() {
|
|
87
|
+
return resolveNarutoCredentialPolicy({
|
|
88
|
+
args: [],
|
|
89
|
+
env: {},
|
|
90
|
+
defaultParentModel: NARUTO_PARENT_MODEL,
|
|
91
|
+
defaultParentEffort: NARUTO_PARENT_EFFORT,
|
|
92
|
+
defaultSubagentModel: DEFAULT_SUBAGENT_MODEL,
|
|
93
|
+
defaultSubagentEffort: DEFAULT_SUBAGENT_EFFORT
|
|
94
|
+
});
|
|
95
|
+
}
|
|
85
96
|
export function buildOfficialSubagentCodexArgs(input) {
|
|
86
97
|
const maxThreads = Math.max(1, Math.floor(input.maxThreads));
|
|
87
98
|
const maV2Total = maxThreads + 1;
|
|
99
|
+
const policy = input.credentialPolicy ?? defaultNarutoCredentialPolicy();
|
|
88
100
|
return [
|
|
89
101
|
'exec',
|
|
90
102
|
'--json',
|
|
91
103
|
...(input.workingDirectory ? ['-C', input.workingDirectory] : []),
|
|
92
|
-
'-m',
|
|
93
|
-
'-c', `model_reasoning_effort="${
|
|
94
|
-
|
|
95
|
-
'-c', 'forced_login_method="chatgpt"',
|
|
104
|
+
'-m', policy.parentModel,
|
|
105
|
+
'-c', `model_reasoning_effort="${policy.parentEffort}"`,
|
|
106
|
+
...narutoCredentialConfigArgs(policy),
|
|
96
107
|
'-c', `features.multi_agent_v2={enabled=true,max_concurrent_threads_per_session=${maV2Total},expose_spawn_agent_model_overrides=true}`,
|
|
97
108
|
'-c', 'agents.enabled=true',
|
|
98
109
|
'-c', `agents.max_concurrent_threads_per_session=${maxThreads}`,
|
|
99
110
|
'-c', 'agents.max_depth=1',
|
|
100
|
-
'-c', `agents.default_subagent_model="${
|
|
101
|
-
'-c', `agents.default_subagent_reasoning_effort="${
|
|
111
|
+
'-c', `agents.default_subagent_model="${policy.subagentModel}"`,
|
|
112
|
+
'-c', `agents.default_subagent_reasoning_effort="${policy.subagentEffort}"`,
|
|
102
113
|
'-c', 'agents.interrupt_message=true',
|
|
103
114
|
...(input.projectConfigArgs || []),
|
|
104
115
|
...(input.hostCapabilityConfigArgs || []),
|
|
@@ -113,6 +124,10 @@ export function buildOfficialSubagentChildEnv(input = {}) {
|
|
|
113
124
|
if (source[key] !== undefined)
|
|
114
125
|
childEnv[key] = source[key];
|
|
115
126
|
}
|
|
127
|
+
const providerEnvKey = input.credentialPolicy?.providerEnvKey;
|
|
128
|
+
if (providerEnvKey && source[providerEnvKey] !== undefined) {
|
|
129
|
+
childEnv[providerEnvKey] = source[providerEnvKey];
|
|
130
|
+
}
|
|
116
131
|
childEnv.SKS_NARUTO_STANDALONE_CLI = '0';
|
|
117
132
|
childEnv.SKS_NARUTO_PARENT_LAUNCH = '1';
|
|
118
133
|
if (input.missionId)
|
|
@@ -343,11 +358,13 @@ export async function runOfficialSubagentWorkflow(input) {
|
|
|
343
358
|
hostCapabilityLaunchNonce = randomId(32);
|
|
344
359
|
hostCapabilityPendingDir = officialSubagentMissionDir(canonicalRoot, input.missionId);
|
|
345
360
|
}
|
|
361
|
+
const credentialPolicy = input.credentialPolicy ?? defaultNarutoCredentialPolicy();
|
|
346
362
|
const childEnv = buildOfficialSubagentChildEnv({
|
|
347
363
|
...(input.env ? { env: input.env } : {}),
|
|
348
364
|
...(input.missionId ? { missionId: input.missionId } : {}),
|
|
349
365
|
...(input.workflowRunId ? { workflowRunId: input.workflowRunId } : {}),
|
|
350
|
-
...(hostCapabilityLaunchNonce ? { hostCapabilityLaunchNonce } : {})
|
|
366
|
+
...(hostCapabilityLaunchNonce ? { hostCapabilityLaunchNonce } : {}),
|
|
367
|
+
credentialPolicy
|
|
351
368
|
});
|
|
352
369
|
const outputSecretValues = hostCapabilityLaunchNonce
|
|
353
370
|
? [...inheritedSecretValues, hostCapabilityLaunchNonce]
|
|
@@ -450,7 +467,8 @@ export async function runOfficialSubagentWorkflow(input) {
|
|
|
450
467
|
projectTrusted: input.projectTrusted === true,
|
|
451
468
|
globalHostCapabilityConfigured
|
|
452
469
|
}),
|
|
453
|
-
hostCapabilityConfigArgs: hostCapabilityCodexConfigArgs(hostCapabilityRuntime)
|
|
470
|
+
hostCapabilityConfigArgs: hostCapabilityCodexConfigArgs(hostCapabilityRuntime),
|
|
471
|
+
credentialPolicy
|
|
454
472
|
});
|
|
455
473
|
const toolOutputRecovery = await inspectCodexLbCliLaunchRecovery({
|
|
456
474
|
root: input.root,
|
|
@@ -1,158 +1,170 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { CONTEXT_GRAPH_REPAIR_COMMAND } from '../triwiki/context-graph/contracts.js';
|
|
2
|
+
import { readContextGraphAttention } from '../triwiki/context-graph/projections/attention.js';
|
|
3
3
|
import { asRecordOrEmpty as asRecord } from '../json/records.js';
|
|
4
4
|
export const BOUNDED_TRIWIKI_ATTENTION_SCHEMA = 'sks.subagent-triwiki-attention.v1';
|
|
5
5
|
export const DEFAULT_TRIWIKI_ATTENTION_ANCHOR_LIMIT = 8;
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
export const MAX_TRIWIKI_ATTENTION_ANCHOR_LIMIT = 16;
|
|
7
|
+
export const DEFAULT_TRIWIKI_ATTENTION_TOKEN_BUDGET = 2000;
|
|
8
|
+
export const TRIWIKI_ATTENTION_GRAPH_SOURCE = '.sneakoscope/wiki/context-graph.json';
|
|
9
|
+
export const TRIWIKI_ATTENTION_PACK_SOURCE = '.sneakoscope/wiki/context-pack.json';
|
|
10
|
+
export async function readBoundedTriwikiAttention(root, limit = DEFAULT_TRIWIKI_ATTENTION_ANCHOR_LIMIT, query = '', options = {}) {
|
|
11
|
+
const anchorLimit = normalizeLimit(limit);
|
|
12
|
+
const tokenBudget = Math.max(0, options.tokenBudget ?? DEFAULT_TRIWIKI_ATTENTION_TOKEN_BUDGET);
|
|
13
|
+
const result = await readContextGraphAttention({
|
|
14
|
+
root,
|
|
15
|
+
query,
|
|
16
|
+
limit: anchorLimit,
|
|
17
|
+
profile: options.profile ?? 'implementation',
|
|
18
|
+
tokenBudget,
|
|
19
|
+
risk: options.risk
|
|
20
|
+
}, options);
|
|
21
|
+
return {
|
|
22
|
+
schema: BOUNDED_TRIWIKI_ATTENTION_SCHEMA,
|
|
23
|
+
source: TRIWIKI_ATTENTION_GRAPH_SOURCE,
|
|
24
|
+
available: result.available,
|
|
25
|
+
attention_mode: result.available ? `context_graph:${result.profile}` : null,
|
|
26
|
+
anchor_limit: anchorLimit,
|
|
27
|
+
anchors: result.anchors.map(toAnchor),
|
|
28
|
+
hydration_policy: 'on_demand_only',
|
|
29
|
+
full_pack_injected: false,
|
|
30
|
+
reason: result.reason,
|
|
31
|
+
repair_command: CONTEXT_GRAPH_REPAIR_COMMAND,
|
|
32
|
+
snapshot_hash: result.snapshotHash,
|
|
33
|
+
snapshot_freshness: result.snapshotFreshness,
|
|
34
|
+
profile: result.available ? result.profile : null,
|
|
35
|
+
token_cost: result.tokenCost,
|
|
36
|
+
token_budget: result.tokenBudget
|
|
37
|
+
};
|
|
9
38
|
}
|
|
10
|
-
export function extractBoundedTriwikiAttention(value, limit = DEFAULT_TRIWIKI_ATTENTION_ANCHOR_LIMIT,
|
|
39
|
+
export function extractBoundedTriwikiAttention(value, limit = DEFAULT_TRIWIKI_ATTENTION_ANCHOR_LIMIT, _retiredQueryHint) {
|
|
11
40
|
const pack = asRecord(value);
|
|
12
41
|
const attention = asRecord(pack.attention);
|
|
13
42
|
const anchorLimit = normalizeLimit(limit);
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
continue;
|
|
19
|
-
const id = text(row[0]);
|
|
20
|
-
const hint = text(row[1]);
|
|
21
|
-
if (id && hint) {
|
|
22
|
-
hydrateHints.set(id, hint.slice(0, 240));
|
|
23
|
-
hydrateOrder.set(id, index);
|
|
24
|
-
}
|
|
43
|
+
const hints = new Map();
|
|
44
|
+
for (const row of rowsOf(attention.hydrate_first)) {
|
|
45
|
+
if (row.id && row.hydrate_hint)
|
|
46
|
+
hints.set(row.id, row.hydrate_hint.slice(0, 240));
|
|
25
47
|
}
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (!id ||
|
|
48
|
+
const anchors = [];
|
|
49
|
+
const seen = new Set();
|
|
50
|
+
for (const row of rowsOf(attention.use_first)) {
|
|
51
|
+
if (anchors.length >= anchorLimit)
|
|
52
|
+
break;
|
|
53
|
+
if (!row.id || seen.has(row.id))
|
|
32
54
|
continue;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
claim_hash: text(row[1]) || null,
|
|
36
|
-
source_hash: text(row[2]) || null,
|
|
37
|
-
hydrate_hint: hydrateHints.get(id) || null,
|
|
38
|
-
order: index
|
|
39
|
-
});
|
|
55
|
+
seen.add(row.id);
|
|
56
|
+
anchors.push({ ...row, hydrate_hint: row.hydrate_hint ?? hints.get(row.id) ?? null });
|
|
40
57
|
}
|
|
41
|
-
const
|
|
58
|
+
const tokenCost = anchors.reduce((sum, anchor) => sum + anchor.token_cost, 0);
|
|
42
59
|
return {
|
|
43
60
|
schema: BOUNDED_TRIWIKI_ATTENTION_SCHEMA,
|
|
44
|
-
source:
|
|
61
|
+
source: TRIWIKI_ATTENTION_PACK_SOURCE,
|
|
45
62
|
available: anchors.length > 0,
|
|
46
63
|
attention_mode: text(attention.mode) || null,
|
|
47
64
|
anchor_limit: anchorLimit,
|
|
48
65
|
anchors,
|
|
49
66
|
hydration_policy: 'on_demand_only',
|
|
50
|
-
full_pack_injected: false
|
|
67
|
+
full_pack_injected: false,
|
|
68
|
+
reason: anchors.length > 0 ? null : 'context_graph_no_match',
|
|
69
|
+
repair_command: CONTEXT_GRAPH_REPAIR_COMMAND,
|
|
70
|
+
snapshot_hash: text(pack.snapshot_hash) || null,
|
|
71
|
+
snapshot_freshness: null,
|
|
72
|
+
profile: null,
|
|
73
|
+
token_cost: tokenCost,
|
|
74
|
+
token_budget: DEFAULT_TRIWIKI_ATTENTION_TOKEN_BUDGET
|
|
51
75
|
};
|
|
52
76
|
}
|
|
53
|
-
function
|
|
54
|
-
const tokens = attentionQueryTokens(query);
|
|
55
|
-
if (!tokens.length)
|
|
56
|
-
return useFirst.slice(0, limit).map(stripOrder);
|
|
57
|
-
const selected = [];
|
|
58
|
-
const seen = new Set();
|
|
59
|
-
for (const anchor of useFirst.slice(0, Math.min(3, limit))) {
|
|
60
|
-
selected.push(stripOrder(anchor));
|
|
61
|
-
seen.add(anchor.id);
|
|
62
|
-
}
|
|
63
|
-
const candidates = [];
|
|
64
|
-
for (const anchor of useFirst) {
|
|
65
|
-
if (seen.has(anchor.id))
|
|
66
|
-
continue;
|
|
67
|
-
candidates.push({
|
|
68
|
-
...stripOrder(anchor),
|
|
69
|
-
score: attentionRelevance(anchor.id, anchor.hydrate_hint, tokens),
|
|
70
|
-
order: anchor.order,
|
|
71
|
-
priority: 0
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
for (const [id, hint] of hydrateHints.entries()) {
|
|
75
|
-
if (seen.has(id) || useFirst.some((anchor) => anchor.id === id))
|
|
76
|
-
continue;
|
|
77
|
-
const score = attentionRelevance(id, hint, tokens);
|
|
78
|
-
if (score <= 0)
|
|
79
|
-
continue;
|
|
80
|
-
candidates.push({
|
|
81
|
-
id,
|
|
82
|
-
claim_hash: null,
|
|
83
|
-
source_hash: null,
|
|
84
|
-
hydrate_hint: hint,
|
|
85
|
-
score,
|
|
86
|
-
order: hydrateOrder.get(id) ?? Number.MAX_SAFE_INTEGER,
|
|
87
|
-
priority: 1
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
candidates.sort((left, right) => right.score - left.score || left.priority - right.priority || left.order - right.order);
|
|
91
|
-
for (const candidate of candidates) {
|
|
92
|
-
if (selected.length >= limit)
|
|
93
|
-
break;
|
|
94
|
-
if (candidate.score <= 0 || seen.has(candidate.id))
|
|
95
|
-
continue;
|
|
96
|
-
selected.push(stripRank(candidate));
|
|
97
|
-
seen.add(candidate.id);
|
|
98
|
-
}
|
|
99
|
-
for (const anchor of useFirst) {
|
|
100
|
-
if (selected.length >= limit)
|
|
101
|
-
break;
|
|
102
|
-
if (seen.has(anchor.id))
|
|
103
|
-
continue;
|
|
104
|
-
selected.push(stripOrder(anchor));
|
|
105
|
-
seen.add(anchor.id);
|
|
106
|
-
}
|
|
107
|
-
return selected;
|
|
108
|
-
}
|
|
109
|
-
function attentionQueryTokens(value) {
|
|
110
|
-
const stop = new Set([
|
|
111
|
-
'and', 'the', 'for', 'with', 'from', 'into', 'this', 'that', 'sks', 'src', 'core',
|
|
112
|
-
'작업', '구현', '개선', '추가', '변경', '기능', '모든', '최대한'
|
|
113
|
-
]);
|
|
114
|
-
return [...new Set(String(value || '')
|
|
115
|
-
.normalize('NFKC')
|
|
116
|
-
.toLowerCase()
|
|
117
|
-
.replace(/[^\p{L}\p{N}]+/gu, ' ')
|
|
118
|
-
.split(/\s+/)
|
|
119
|
-
.map((token) => token.trim())
|
|
120
|
-
.filter((token) => token.length >= 2 && !stop.has(token)))]
|
|
121
|
-
.slice(0, 64);
|
|
122
|
-
}
|
|
123
|
-
function attentionRelevance(id, hint, tokens) {
|
|
124
|
-
const haystack = `${id} ${hint || ''}`
|
|
125
|
-
.normalize('NFKC')
|
|
126
|
-
.toLowerCase()
|
|
127
|
-
.replace(/[^\p{L}\p{N}]+/gu, ' ');
|
|
128
|
-
const compact = haystack.replace(/\s+/g, '');
|
|
129
|
-
return tokens.reduce((score, token) => {
|
|
130
|
-
if (haystack.includes(token))
|
|
131
|
-
return score + (token.length >= 5 ? 4 : 3);
|
|
132
|
-
return compact.includes(token) ? score + 2 : score;
|
|
133
|
-
}, 0);
|
|
134
|
-
}
|
|
135
|
-
function stripOrder(anchor) {
|
|
77
|
+
function toAnchor(anchor) {
|
|
136
78
|
return {
|
|
137
79
|
id: anchor.id,
|
|
138
80
|
claim_hash: anchor.claim_hash,
|
|
139
81
|
source_hash: anchor.source_hash,
|
|
140
|
-
hydrate_hint: anchor.hydrate_hint
|
|
82
|
+
hydrate_hint: anchor.hydrate_hint,
|
|
83
|
+
reason_path: anchor.reason_path,
|
|
84
|
+
trust_score: anchor.trust_score,
|
|
85
|
+
freshness: anchor.freshness,
|
|
86
|
+
token_cost: anchor.token_cost,
|
|
87
|
+
provenance: anchor.provenance.map((ref) => ({
|
|
88
|
+
path: ref.path,
|
|
89
|
+
...(ref.line === undefined ? {} : { line: ref.line }),
|
|
90
|
+
hash: ref.hash
|
|
91
|
+
}))
|
|
141
92
|
};
|
|
142
93
|
}
|
|
143
|
-
function
|
|
94
|
+
function rowsOf(value) {
|
|
95
|
+
if (!Array.isArray(value))
|
|
96
|
+
return [];
|
|
97
|
+
const out = [];
|
|
98
|
+
for (const raw of value) {
|
|
99
|
+
const row = Array.isArray(raw) ? tupleRow(raw) : objectRow(raw);
|
|
100
|
+
if (row)
|
|
101
|
+
out.push(row);
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
function tupleRow(row) {
|
|
106
|
+
const id = text(row[0]);
|
|
107
|
+
if (!id)
|
|
108
|
+
return null;
|
|
109
|
+
const second = text(row[1]);
|
|
110
|
+
const third = text(row[2]);
|
|
111
|
+
const isHydrateRow = row.length <= 2;
|
|
144
112
|
return {
|
|
145
|
-
id
|
|
146
|
-
claim_hash:
|
|
147
|
-
source_hash:
|
|
148
|
-
hydrate_hint:
|
|
113
|
+
id,
|
|
114
|
+
claim_hash: isHydrateRow ? null : second || null,
|
|
115
|
+
source_hash: isHydrateRow ? null : third || null,
|
|
116
|
+
hydrate_hint: isHydrateRow ? second || null : null,
|
|
117
|
+
reason_path: [],
|
|
118
|
+
trust_score: 0,
|
|
119
|
+
freshness: 'unknown',
|
|
120
|
+
token_cost: 0,
|
|
121
|
+
provenance: []
|
|
149
122
|
};
|
|
150
123
|
}
|
|
124
|
+
function objectRow(raw) {
|
|
125
|
+
const row = asRecord(raw);
|
|
126
|
+
const id = text(row.id);
|
|
127
|
+
if (!id)
|
|
128
|
+
return null;
|
|
129
|
+
return {
|
|
130
|
+
id,
|
|
131
|
+
claim_hash: text(row.claim_hash) || null,
|
|
132
|
+
source_hash: text(row.source_hash) || null,
|
|
133
|
+
hydrate_hint: text(row.hydrate_hint) || null,
|
|
134
|
+
reason_path: Array.isArray(row.reason_path) ? row.reason_path.map(text).filter(Boolean) : [],
|
|
135
|
+
trust_score: number(row.trust_score),
|
|
136
|
+
freshness: freshnessOf(row.freshness),
|
|
137
|
+
token_cost: Math.max(0, Math.trunc(number(row.token_cost))),
|
|
138
|
+
provenance: provenanceOf(row.provenance)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function provenanceOf(value) {
|
|
142
|
+
if (!Array.isArray(value))
|
|
143
|
+
return [];
|
|
144
|
+
const out = [];
|
|
145
|
+
for (const raw of value) {
|
|
146
|
+
const ref = asRecord(raw);
|
|
147
|
+
const refPath = text(ref.path);
|
|
148
|
+
const hash = text(ref.hash);
|
|
149
|
+
if (!refPath || !hash)
|
|
150
|
+
continue;
|
|
151
|
+
const line = number(ref.line);
|
|
152
|
+
out.push({ path: refPath, ...(line > 0 ? { line } : {}), hash });
|
|
153
|
+
}
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
function freshnessOf(value) {
|
|
157
|
+
return value === 'fresh' || value === 'stale' ? value : 'unknown';
|
|
158
|
+
}
|
|
151
159
|
function normalizeLimit(value) {
|
|
152
160
|
const parsed = Number(value);
|
|
153
161
|
if (!Number.isFinite(parsed))
|
|
154
162
|
return DEFAULT_TRIWIKI_ATTENTION_ANCHOR_LIMIT;
|
|
155
|
-
return Math.max(1, Math.min(
|
|
163
|
+
return Math.max(1, Math.min(MAX_TRIWIKI_ATTENTION_ANCHOR_LIMIT, Math.floor(parsed)));
|
|
164
|
+
}
|
|
165
|
+
function number(value) {
|
|
166
|
+
const parsed = Number(value);
|
|
167
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
156
168
|
}
|
|
157
169
|
function text(value) {
|
|
158
170
|
return typeof value === 'string' ? value.trim() : '';
|