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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fsp from 'node:fs/promises';
|
|
2
2
|
import { parseCodexConfigToml } from '../codex/codex-config-toml.js';
|
|
3
|
+
import { errorCodeOf } from '../errors/message.js';
|
|
3
4
|
import { publicMcpCommand, redactMcpError, redactMcpUrl, sanitizeMcpArgs } from './redaction.js';
|
|
4
5
|
import { normalizeApprovalMode } from './secret-policy.js';
|
|
5
6
|
import { MCP_DEFAULT_STARTUP_TIMEOUT_SEC, MCP_DEFAULT_TOOL_TIMEOUT_SEC, MCP_SERVER_CONFIG_SCHEMA } from './types.js';
|
|
@@ -16,7 +17,7 @@ export class McpConfigReadError extends Error {
|
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
export async function readMcpConfigDocument(ref) {
|
|
19
|
-
const stat = await fsp.lstat(ref.configPath).catch((error) =>
|
|
20
|
+
const stat = await fsp.lstat(ref.configPath).catch((error) => errorCodeOf(error) === 'ENOENT' ? null : Promise.reject(error));
|
|
20
21
|
if (!stat)
|
|
21
22
|
return { ref, exists: false, text: '', parsed: {}, rawServers: {} };
|
|
22
23
|
if (stat.isSymbolicLink())
|
|
@@ -142,6 +143,3 @@ function positiveNumber(value) {
|
|
|
142
143
|
const number = Number(value);
|
|
143
144
|
return Number.isFinite(number) && number > 0 ? number : null;
|
|
144
145
|
}
|
|
145
|
-
function errorCode(error) {
|
|
146
|
-
return error && typeof error === 'object' && 'code' in error ? String(error.code) : '';
|
|
147
|
-
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fsp from 'node:fs/promises';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { errorCodeOf } from '../errors/message.js';
|
|
4
5
|
export class McpScopeError extends Error {
|
|
5
6
|
code;
|
|
6
7
|
constructor(code) {
|
|
@@ -41,7 +42,7 @@ export function isPathInside(root, candidate) {
|
|
|
41
42
|
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
42
43
|
}
|
|
43
44
|
async function assertSafeDirectory(directory, boundary, strictNoSymlink) {
|
|
44
|
-
const stat = await fsp.lstat(directory).catch((error) =>
|
|
45
|
+
const stat = await fsp.lstat(directory).catch((error) => errorCodeOf(error) === 'ENOENT' ? null : Promise.reject(error));
|
|
45
46
|
if (!stat)
|
|
46
47
|
return;
|
|
47
48
|
if (strictNoSymlink && stat.isSymbolicLink())
|
|
@@ -53,7 +54,7 @@ async function assertSafeDirectory(directory, boundary, strictNoSymlink) {
|
|
|
53
54
|
throw new McpScopeError('mcp_codex_home_escape_refused');
|
|
54
55
|
}
|
|
55
56
|
async function assertSafeConfig(configPath, boundary) {
|
|
56
|
-
const stat = await fsp.lstat(configPath).catch((error) =>
|
|
57
|
+
const stat = await fsp.lstat(configPath).catch((error) => errorCodeOf(error) === 'ENOENT' ? null : Promise.reject(error));
|
|
57
58
|
if (!stat)
|
|
58
59
|
return;
|
|
59
60
|
if (stat.isSymbolicLink())
|
|
@@ -64,6 +65,3 @@ async function assertSafeConfig(configPath, boundary) {
|
|
|
64
65
|
if (!resolved || !isPathInside(boundary, resolved))
|
|
65
66
|
throw new McpScopeError('mcp_config_escape_refused');
|
|
66
67
|
}
|
|
67
|
-
function errorCode(error) {
|
|
68
|
-
return error && typeof error === 'object' && 'code' in error ? String(error.code) : '';
|
|
69
|
-
}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { incomingEdges, outgoingEdges } from '../triwiki/context-graph/graph-index.js';
|
|
2
|
+
import { contextGraphPathFromId } from '../triwiki/context-graph/ids.js';
|
|
3
|
+
import { isWorkspaceRelativePosixPath } from '../triwiki/context-graph/paths.js';
|
|
4
|
+
import { normalizeNarutoPath } from './naruto-work-item.js';
|
|
5
|
+
export const NARUTO_ADVISOR_CAPS = {
|
|
6
|
+
maxDepth: 2,
|
|
7
|
+
maxNodesPerWalk: 512,
|
|
8
|
+
maxEdgesPerWalk: 4096,
|
|
9
|
+
maxSharedPathsPerPair: 12,
|
|
10
|
+
maxRecommendationsPerSlice: 24,
|
|
11
|
+
maxTaskTokens: 32,
|
|
12
|
+
maxNodesPerLabel: 8
|
|
13
|
+
};
|
|
14
|
+
const DEPENDENCY_EDGE_TYPES = new Set(['imports', 'reexports', 'depends_on', 'references', 'calls', 'routes_to']);
|
|
15
|
+
const IMPACT_EDGE_TYPES = new Set([
|
|
16
|
+
'imports', 'reexports', 'references', 'calls', 'tests', 'affected_by', 'verified_by', 'gated_by', 'depends_on', 'owns', 'routes_to'
|
|
17
|
+
]);
|
|
18
|
+
const SEED_EXPANSION_EDGE_TYPES = new Set(['defines', 'contains']);
|
|
19
|
+
function explanationStep(edge) {
|
|
20
|
+
return { edgeId: edge.id, type: edge.type, from: edge.from, to: edge.to, confidence: edge.confidence, path: edge.provenance.path };
|
|
21
|
+
}
|
|
22
|
+
function nodePathOf(node) {
|
|
23
|
+
return node.path ?? contextGraphPathFromId(node.id);
|
|
24
|
+
}
|
|
25
|
+
function isTestNode(node) {
|
|
26
|
+
return node.kind === 'test' || node.metadata.isTest === true;
|
|
27
|
+
}
|
|
28
|
+
function isProtectedGateNode(node) {
|
|
29
|
+
return node.risk === 'protected' || node.metadata.requiredForPublish === true || node.metadata.alwaysOnRelease === true;
|
|
30
|
+
}
|
|
31
|
+
function riskDomainOf(node) {
|
|
32
|
+
if (node.kind === 'risk_domain')
|
|
33
|
+
return node.label || null;
|
|
34
|
+
if (node.kind !== 'gate')
|
|
35
|
+
return null;
|
|
36
|
+
const declared = node.metadata.namespace;
|
|
37
|
+
return (typeof declared === 'string' && declared ? declared : node.label.split(':')[0]) || null;
|
|
38
|
+
}
|
|
39
|
+
export function narutoAdvisorWorkspacePath(value) {
|
|
40
|
+
const normalized = normalizeNarutoPath(value);
|
|
41
|
+
return normalized && isWorkspaceRelativePosixPath(normalized) ? normalized : null;
|
|
42
|
+
}
|
|
43
|
+
export function narutoAdvisorPathList(values) {
|
|
44
|
+
return [...new Set((values ?? []).map(narutoAdvisorWorkspacePath).filter((value) => value !== null))].sort();
|
|
45
|
+
}
|
|
46
|
+
function rootHit(nodeId) {
|
|
47
|
+
return { nodeId, depth: 0, reasonPath: [nodeId], explanation: [] };
|
|
48
|
+
}
|
|
49
|
+
function walkGraph(index, roots, direction, types, maxDepth) {
|
|
50
|
+
const hits = new Map();
|
|
51
|
+
const queue = [];
|
|
52
|
+
for (const root of roots) {
|
|
53
|
+
if (hits.has(root.nodeId) || !index.nodesById.has(root.nodeId))
|
|
54
|
+
continue;
|
|
55
|
+
hits.set(root.nodeId, root);
|
|
56
|
+
queue.push(root);
|
|
57
|
+
}
|
|
58
|
+
let edgesVisited = 0;
|
|
59
|
+
for (let head = 0; head < queue.length; head += 1) {
|
|
60
|
+
const current = queue[head];
|
|
61
|
+
if (!current || current.depth >= maxDepth)
|
|
62
|
+
continue;
|
|
63
|
+
for (const edge of direction === 'out' ? outgoingEdges(index, current.nodeId) : incomingEdges(index, current.nodeId)) {
|
|
64
|
+
edgesVisited += 1;
|
|
65
|
+
if (edgesVisited > NARUTO_ADVISOR_CAPS.maxEdgesPerWalk)
|
|
66
|
+
return { hits, truncated: true };
|
|
67
|
+
if (!types.has(edge.type))
|
|
68
|
+
continue;
|
|
69
|
+
const next = direction === 'out' ? edge.to : edge.from;
|
|
70
|
+
if (hits.has(next) || !index.nodesById.has(next))
|
|
71
|
+
continue;
|
|
72
|
+
if (hits.size >= NARUTO_ADVISOR_CAPS.maxNodesPerWalk)
|
|
73
|
+
return { hits, truncated: true };
|
|
74
|
+
const hit = {
|
|
75
|
+
nodeId: next,
|
|
76
|
+
depth: current.depth + 1,
|
|
77
|
+
reasonPath: [...current.reasonPath, direction === 'out' ? edge.type : `<-${edge.type}`, next],
|
|
78
|
+
explanation: [...current.explanation, explanationStep(edge)]
|
|
79
|
+
};
|
|
80
|
+
hits.set(next, hit);
|
|
81
|
+
queue.push(hit);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { hits, truncated: false };
|
|
85
|
+
}
|
|
86
|
+
export function narutoAdvisorProvenance(index, hit) {
|
|
87
|
+
const out = [];
|
|
88
|
+
const seen = new Set();
|
|
89
|
+
for (const step of hit.explanation) {
|
|
90
|
+
const edge = index.edgesById.get(step.edgeId);
|
|
91
|
+
if (!edge)
|
|
92
|
+
continue;
|
|
93
|
+
const key = `${edge.provenance.path}#${edge.provenance.line ?? 0}#${edge.provenance.hash}`;
|
|
94
|
+
if (seen.has(key))
|
|
95
|
+
continue;
|
|
96
|
+
seen.add(key);
|
|
97
|
+
const line = edge.provenance.line;
|
|
98
|
+
out.push({ path: edge.provenance.path, ...(line === undefined ? {} : { line }), hash: edge.provenance.hash });
|
|
99
|
+
}
|
|
100
|
+
if (out.length)
|
|
101
|
+
return out;
|
|
102
|
+
const node = index.nodesById.get(hit.nodeId);
|
|
103
|
+
const nodePath = node ? nodePathOf(node) : null;
|
|
104
|
+
if (node?.contentHash && nodePath)
|
|
105
|
+
out.push({ path: nodePath, hash: node.contentHash });
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
function resolveSeedNodes(index, paths, labels, unresolved) {
|
|
109
|
+
const out = [];
|
|
110
|
+
const seen = new Set();
|
|
111
|
+
const push = (id) => {
|
|
112
|
+
if (!seen.has(id) && index.nodesById.has(id)) {
|
|
113
|
+
seen.add(id);
|
|
114
|
+
out.push(id);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const miss = (value) => {
|
|
118
|
+
if (value && !unresolved.includes(value))
|
|
119
|
+
unresolved.push(value);
|
|
120
|
+
};
|
|
121
|
+
for (const raw of paths) {
|
|
122
|
+
const rel = narutoAdvisorWorkspacePath(raw);
|
|
123
|
+
const ids = rel ? index.nodesByPath.get(rel) ?? [] : [];
|
|
124
|
+
if (!ids.length)
|
|
125
|
+
miss(raw);
|
|
126
|
+
for (const id of ids)
|
|
127
|
+
push(id);
|
|
128
|
+
}
|
|
129
|
+
for (const label of labels) {
|
|
130
|
+
const ids = index.nodesByLabel.get(String(label ?? '').toLowerCase()) ?? [];
|
|
131
|
+
if (!ids.length || ids.length > NARUTO_ADVISOR_CAPS.maxNodesPerLabel)
|
|
132
|
+
miss(String(label ?? ''));
|
|
133
|
+
else
|
|
134
|
+
for (const id of ids)
|
|
135
|
+
push(id);
|
|
136
|
+
}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
export function narutoAdvisorTaskTokens(text) {
|
|
140
|
+
const tokens = [];
|
|
141
|
+
for (const raw of String(text ?? '').split(/[^\w$./-]+/)) {
|
|
142
|
+
const token = raw.replace(/^[./-]+/, '').replace(/[./-]+$/, '');
|
|
143
|
+
if (token.length < 3 || tokens.includes(token))
|
|
144
|
+
continue;
|
|
145
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(token) && !/^[\w$./-]+\.[A-Za-z]\w*$/.test(token))
|
|
146
|
+
continue;
|
|
147
|
+
tokens.push(token);
|
|
148
|
+
if (tokens.length >= NARUTO_ADVISOR_CAPS.maxTaskTokens)
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
return tokens;
|
|
152
|
+
}
|
|
153
|
+
function expandRoots(index, seeds) {
|
|
154
|
+
const roots = seeds.map(rootHit);
|
|
155
|
+
const seen = new Set(seeds);
|
|
156
|
+
for (const seed of seeds) {
|
|
157
|
+
for (const edge of outgoingEdges(index, seed)) {
|
|
158
|
+
if (!SEED_EXPANSION_EDGE_TYPES.has(edge.type) || seen.has(edge.to))
|
|
159
|
+
continue;
|
|
160
|
+
seen.add(edge.to);
|
|
161
|
+
roots.push({ nodeId: edge.to, depth: 0, reasonPath: [seed, edge.type, edge.to], explanation: [explanationStep(edge)] });
|
|
162
|
+
if (roots.length >= NARUTO_ADVISOR_CAPS.maxNodesPerWalk)
|
|
163
|
+
return roots;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return roots;
|
|
167
|
+
}
|
|
168
|
+
function closurePaths(index, walk) {
|
|
169
|
+
const out = new Map();
|
|
170
|
+
for (const hit of walk.hits.values()) {
|
|
171
|
+
const node = index.nodesById.get(hit.nodeId);
|
|
172
|
+
if (!node || isTestNode(node))
|
|
173
|
+
continue;
|
|
174
|
+
const nodePath = nodePathOf(node);
|
|
175
|
+
if (nodePath && !out.has(nodePath))
|
|
176
|
+
out.set(nodePath, hit);
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
180
|
+
function recommendationsFrom(index, sliceId, writeSet, impact) {
|
|
181
|
+
const out = [];
|
|
182
|
+
for (const hit of impact.hits.values()) {
|
|
183
|
+
const node = index.nodesById.get(hit.nodeId);
|
|
184
|
+
if (!node)
|
|
185
|
+
continue;
|
|
186
|
+
const isGate = node.kind === 'gate';
|
|
187
|
+
if (!isGate && !isTestNode(node))
|
|
188
|
+
continue;
|
|
189
|
+
const nodePath = nodePathOf(node);
|
|
190
|
+
if (!nodePath || (!isGate && writeSet.has(nodePath)))
|
|
191
|
+
continue;
|
|
192
|
+
out.push({
|
|
193
|
+
slice_id: sliceId,
|
|
194
|
+
kind: isGate ? 'gate' : 'test',
|
|
195
|
+
id: isGate ? node.label : nodePath,
|
|
196
|
+
path: nodePath,
|
|
197
|
+
protected: isGate ? isProtectedGateNode(node) : false,
|
|
198
|
+
risk_domain: isGate ? riskDomainOf(node) : null,
|
|
199
|
+
reason_path: [...hit.reasonPath],
|
|
200
|
+
explanation: [...hit.explanation],
|
|
201
|
+
provenance: narutoAdvisorProvenance(index, hit)
|
|
202
|
+
});
|
|
203
|
+
if (out.length >= NARUTO_ADVISOR_CAPS.maxRecommendationsPerSlice)
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
return out.sort((a, b) => (a.kind === b.kind ? (a.id < b.id ? -1 : a.id > b.id ? 1 : 0) : a.kind < b.kind ? -1 : 1));
|
|
207
|
+
}
|
|
208
|
+
export function buildNarutoSliceState(index, slice, taskTokens, maxDepth) {
|
|
209
|
+
const unresolved = [];
|
|
210
|
+
const writePaths = narutoAdvisorPathList(slice.writePaths);
|
|
211
|
+
const labels = [...(slice.symbols ?? [])];
|
|
212
|
+
if (!writePaths.length && !labels.length)
|
|
213
|
+
labels.push(...narutoAdvisorTaskTokens(slice.title ?? ''), ...taskTokens);
|
|
214
|
+
const seeds = resolveSeedNodes(index, writePaths, labels, unresolved);
|
|
215
|
+
const walk = walkGraph(index, seeds.map(rootHit), 'out', DEPENDENCY_EDGE_TYPES, maxDepth);
|
|
216
|
+
const impact = walkGraph(index, expandRoots(index, seeds), 'in', IMPACT_EDGE_TYPES, maxDepth);
|
|
217
|
+
const closure = closurePaths(index, walk);
|
|
218
|
+
const writeSet = new Set(writePaths);
|
|
219
|
+
return {
|
|
220
|
+
scope: {
|
|
221
|
+
slice_id: slice.id,
|
|
222
|
+
seed_node_ids: [...seeds].sort(),
|
|
223
|
+
write_paths: writePaths,
|
|
224
|
+
write_closure: [...closure.keys()].sort(),
|
|
225
|
+
unresolved_seeds: [...new Set(unresolved)].sort(),
|
|
226
|
+
truncated: walk.truncated || impact.truncated
|
|
227
|
+
},
|
|
228
|
+
closure,
|
|
229
|
+
writeSet,
|
|
230
|
+
recommendations: recommendationsFrom(index, slice.id, writeSet, impact)
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
export function emptyNarutoScope(sliceId, slice) {
|
|
234
|
+
return {
|
|
235
|
+
slice_id: sliceId,
|
|
236
|
+
seed_node_ids: [],
|
|
237
|
+
write_paths: narutoAdvisorPathList(slice?.writePaths),
|
|
238
|
+
write_closure: [],
|
|
239
|
+
unresolved_seeds: [],
|
|
240
|
+
truncated: false
|
|
241
|
+
};
|
|
242
|
+
}
|
|
Binary file
|
|
@@ -8,6 +8,7 @@ import { runProcess, writeJsonAtomic } from '../fsx.js';
|
|
|
8
8
|
import { listMcpInventory } from '../mcp-config/index.js';
|
|
9
9
|
import { RemoteSshWorkerClient } from '../remote/ssh-worker-client.js';
|
|
10
10
|
import { TelegramHubRouter } from '../telegram/hub.js';
|
|
11
|
+
import { buildTelegramConfigV2, telegramTokenFingerprint } from '../telegram/config.js';
|
|
11
12
|
import { TelegramActionBroker, TelegramAuditLedger, TelegramIdempotencyLedger, TelegramTopicRegistry } from '../telegram/ledgers.js';
|
|
12
13
|
import { TelegramMessageProjector } from '../telegram/messages.js';
|
|
13
14
|
import { TelegramHubRuntime } from '../telegram/runtime.js';
|
|
@@ -124,10 +125,14 @@ async function measureUpdateCacheRead(tmp, count) {
|
|
|
124
125
|
}
|
|
125
126
|
async function measureTelegramAck(tmp, count) {
|
|
126
127
|
const base = path.join(tmp, 'telegram');
|
|
127
|
-
const config = {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
const config = buildTelegramConfigV2({
|
|
129
|
+
botTokenRef: { type: 'external_file', path: '/dev/null' },
|
|
130
|
+
botUserId: '99',
|
|
131
|
+
botTokenFingerprint: telegramTokenFingerprint('123456789:ABCDEFGHIJKLMNOPQRSTUVWX'),
|
|
132
|
+
pairedChatId: '1',
|
|
133
|
+
pairedUserId: '1',
|
|
134
|
+
configGeneration: 1
|
|
135
|
+
});
|
|
131
136
|
let ackAt = 0;
|
|
132
137
|
const api = {
|
|
133
138
|
call: async (method) => {
|
|
@@ -257,6 +262,7 @@ function nativeHarnessSource() {
|
|
|
257
262
|
return `let application = NSApplication.shared
|
|
258
263
|
application.setActivationPolicy(.accessory)
|
|
259
264
|
let processClient = ProcessClient(actionScript: AppRuntime.actionScript, logPath: AppRuntime.lastActionLogPath, projectRoot: AppRuntime.projectRoot)
|
|
265
|
+
let telegramHubSupervisor = TelegramHubSupervisor(processClient: processClient, actionScript: AppRuntime.actionScript, projectRoot: AppRuntime.projectRoot)
|
|
260
266
|
let operations = OperationCoordinator(directory: AppRuntime.operationDirectory)
|
|
261
267
|
let notifications = NotificationCoordinator()
|
|
262
268
|
let status = StatusItemController(processClient: processClient, operations: operations, notifications: notifications, openControlCenter: { _ in })
|
|
@@ -264,11 +270,11 @@ let firstStart = DispatchTime.now().uptimeNanoseconds
|
|
|
264
270
|
status.start()
|
|
265
271
|
let firstMs = Double(DispatchTime.now().uptimeNanoseconds - firstStart) / 1_000_000
|
|
266
272
|
status.stop()
|
|
267
|
-
let control = ControlCenterWindowController(processClient: processClient, operations: operations, notifications: notifications)
|
|
273
|
+
let control = ControlCenterWindowController(processClient: processClient, telegramHubSupervisor: telegramHubSupervisor, operations: operations, notifications: notifications)
|
|
268
274
|
let controlStart = DispatchTime.now().uptimeNanoseconds
|
|
269
275
|
control.show(section: .overview)
|
|
270
276
|
let controlMs = Double(DispatchTime.now().uptimeNanoseconds - controlStart) / 1_000_000
|
|
271
|
-
control.window?.orderOut(nil)
|
|
277
|
+
control.window?.orderOut(nil as Any?)
|
|
272
278
|
let data = try! JSONSerialization.data(withJSONObject: ["menu_bar_first_state_render_ms": firstMs, "control_center_open_ms": controlMs])
|
|
273
279
|
print(String(data: data, encoding: .utf8)!)`;
|
|
274
280
|
}
|
|
@@ -14,6 +14,7 @@ import { writeMistakeMemoryReport } from '../mistake-memory.js';
|
|
|
14
14
|
import { MISTAKE_RECALL_ARTIFACT, mistakeRecallGateStatus } from '../mistake-recall.js';
|
|
15
15
|
import { recordSkillDreamEvent, SKILL_DREAM_POLICY, writeSkillForgeReport } from '../skill-forge.js';
|
|
16
16
|
import { evaluateResearchGate, researchPaperArtifactForPlan, writeResearchPlan } from '../research.js';
|
|
17
|
+
import { ALIGN_GATE_ARTIFACT, ALIGN_LEDGER_ARTIFACT, ALIGN_PLAN_ARTIFACT, alignNextActionText, writeAlignRouteArtifacts } from '../align/align-route.js';
|
|
17
18
|
import { PPT_REQUIRED_GATE_FIELDS, writePptRouteArtifacts } from '../ppt.js';
|
|
18
19
|
import { writeQaLoopArtifacts } from '../qa-loop.js';
|
|
19
20
|
import { IMAGE_UX_REVIEW_GATE_ARTIFACT, IMAGE_UX_REVIEW_POLICY_ARTIFACT, IMAGE_UX_REVIEW_SCREEN_INVENTORY_ARTIFACT, IMAGE_UX_REVIEW_GENERATED_REVIEW_LEDGER_ARTIFACT, IMAGE_UX_REVIEW_ISSUE_LEDGER_ARTIFACT, IMAGE_UX_REVIEW_ITERATION_REPORT_ARTIFACT, IMAGE_UX_REVIEW_REQUIRED_GATE_FIELDS, writeImageUxReviewRouteArtifacts } from '../image-ux-review.js';
|
|
@@ -678,6 +679,8 @@ export function promptPipelineContext(prompt, route = null) {
|
|
|
678
679
|
lines.push('MAD-SKS SQL-plane: explicit invocation is the approval boundary. Use the mission-local write-capable Supabase MCP profile only for the bound cycle, verify execute_sql/apply_migration inventory before claiming ready, execute requested SQL-plane mutations, read back postconditions, then close the capability/profile and prove normal read-only restoration. Supabase project/account/billing/credential control-plane actions remain denied.');
|
|
679
680
|
if (route?.id === 'GX')
|
|
680
681
|
lines.push('GX route: use deterministic vgraph/beta render, validate, drift, and snapshot artifacts.');
|
|
682
|
+
if (route?.id === 'Align')
|
|
683
|
+
lines.push('Align route: modernize SKS prompts, settings, and skill/command surfaces to latest GPT-5.6 official prompting, programmatic tool calling, agents, and openai/skills guidance. Latest-version only: delete legacy compat knobs, deduplicate redundant prompt/config content, protect immutable core skills, update align-ledger.json, and pass align-gate.json.');
|
|
681
684
|
return lines.join('\n');
|
|
682
685
|
}
|
|
683
686
|
export function dfixQuickContext(prompt, route = routePrompt(prompt)) {
|
|
@@ -791,6 +794,8 @@ export async function prepareRoute(root, prompt, state = {}, opts = {}) {
|
|
|
791
794
|
return finish(await prepareResearch(root, route, task, required, { sessionKey }));
|
|
792
795
|
if (route.id === 'AutoResearch')
|
|
793
796
|
return finish(await prepareAutoResearch(root, route, task, required, { sessionKey }));
|
|
797
|
+
if (route.id === 'Align')
|
|
798
|
+
return finish(await prepareAlign(root, route, task, required, { sessionKey }));
|
|
794
799
|
if (route.id === 'DB')
|
|
795
800
|
return finish(await prepareDb(root, route, task, required, { sessionKey }));
|
|
796
801
|
if (route.id === 'GX')
|
|
@@ -956,6 +961,16 @@ export async function activeRouteContext(root, state) {
|
|
|
956
961
|
return `Route contract sealed for ${state.route_command || state.route || state.mode}. Use decision-contract.json and ${PIPELINE_PLAN_ARTIFACT} before executing the route. Before the next route phase, read relevant TriWiki context, hydrate low-trust claims from source, and refresh/validate TriWiki again after new findings or artifact changes. Next atomic action: continue the original route lifecycle with the inferred goal, constraints, non-goals, risk boundary, and test scope.${planNote}`;
|
|
957
962
|
}
|
|
958
963
|
if (state.mode === 'NARUTO') {
|
|
964
|
+
if (state.session_scope) {
|
|
965
|
+
const parentEvidenceState = await appNarutoParentEvidenceState(root, state);
|
|
966
|
+
if (parentEvidenceState === 'completed') {
|
|
967
|
+
return `Active Codex App Naruto mission ${state.mission_id || 'latest'} has trustworthy current-run parent evidence and a passed Naruto gate. Do not resubmit or expose the sks.subagent-parent-summary.v1 JSON. Return concise Markdown in the user's language with an explicit completion summary, verification, remaining gaps, and Honest Mode.${reasoningNote}${planNote}`;
|
|
968
|
+
}
|
|
969
|
+
if (parentEvidenceState === 'blocked') {
|
|
970
|
+
return `Active Codex App Naruto mission ${state.mission_id || 'latest'} has trustworthy current-run blocked or failed parent evidence. Do not resubmit or expose the sks.subagent-parent-summary.v1 JSON. Return concise Markdown in the user's language that states the blocker or failure first, avoids completion or success wording, and includes verification, remaining gaps, and Honest Mode.${reasoningNote}${planNote}`;
|
|
971
|
+
}
|
|
972
|
+
return `Active Codex App Naruto mission ${state.mission_id || 'latest'} uses the official Codex subagent workflow. Read subagent-plan.json, keep ${SUBAGENT_EVENT_LOG_FILENAME} and ${SUBAGENT_EVIDENCE_FILENAME} current from SubagentStart/SubagentStop, and wait for all requested agent threads. Build the exact sks.subagent-parent-summary.v1 object with run_id matching subagent-plan.json.workflow_run_id, then send it only through stdin to "sks naruto parent-summary --mission ${state.mission_id} --stdin --json". Do not expose, paste, embed, quote, or fence that JSON in the user-visible response. Only after the command accepts it, return concise Markdown in the user's language with completion summary, verification, remaining gaps/blockers, and Honest Mode. A successful response must visibly include the completion summary and Honest Mode assessment. If any parent/thread status is blocked or failed, or blockers remain, state that first and do not use completion or success wording. Do not substitute process counts, PID evidence, retired process-pool artifacts, or a custom active pool.${reasoningNote}${planNote}`;
|
|
973
|
+
}
|
|
959
974
|
return `Active Naruto mission ${state.mission_id || 'latest'} uses the official Codex subagent workflow. Read subagent-plan.json, keep ${SUBAGENT_EVENT_LOG_FILENAME} and ${SUBAGENT_EVIDENCE_FILENAME} current from SubagentStart/SubagentStop, wait for all requested agent threads, then return the exact sks.subagent-parent-summary.v1 JSON result so SKS can persist ${SUBAGENT_PARENT_SUMMARY_FILENAME} and derive naruto-summary.json/naruto-gate.json. Do not substitute process counts, PID evidence, retired process-pool artifacts, or a custom active pool.${reasoningNote}${planNote}`;
|
|
960
975
|
}
|
|
961
976
|
if (state.subagents_required && !(await hasSubagentEvidence(root, state))) {
|
|
@@ -968,6 +983,40 @@ export async function activeRouteContext(root, state) {
|
|
|
968
983
|
}
|
|
969
984
|
return planNote.trim();
|
|
970
985
|
}
|
|
986
|
+
async function appNarutoParentEvidenceState(root, state) {
|
|
987
|
+
const missionId = String(state?.mission_id || '').trim();
|
|
988
|
+
const workflowRunId = String(state?.official_subagent_run_id || '').trim();
|
|
989
|
+
if (!missionId || !workflowRunId)
|
|
990
|
+
return null;
|
|
991
|
+
const dir = missionDir(root, missionId);
|
|
992
|
+
const [evidence, summary, gate] = await Promise.all([
|
|
993
|
+
subagentEvidence(root, state).catch(() => null),
|
|
994
|
+
readJson(path.join(dir, NARUTO_SUMMARY_FILENAME), null).catch(() => null),
|
|
995
|
+
readJson(path.join(dir, NARUTO_GATE_FILENAME), null).catch(() => null)
|
|
996
|
+
]);
|
|
997
|
+
const currentRun = evidence?.run_id === workflowRunId
|
|
998
|
+
&& summary?.workflow_run_id === workflowRunId
|
|
999
|
+
&& gate?.workflow_run_id === workflowRunId;
|
|
1000
|
+
if (!currentRun || evidence?.parent_summary_trustworthy !== true)
|
|
1001
|
+
return null;
|
|
1002
|
+
if (evidence.ok === true
|
|
1003
|
+
&& evidence.status === 'completed'
|
|
1004
|
+
&& summary?.status === 'completed'
|
|
1005
|
+
&& summary?.completion_evidence === true
|
|
1006
|
+
&& gate?.passed === true
|
|
1007
|
+
&& gate?.terminal === true
|
|
1008
|
+
&& gate?.terminal_state === 'completed') {
|
|
1009
|
+
return 'completed';
|
|
1010
|
+
}
|
|
1011
|
+
if (evidence.parent_summary_status === 'failed'
|
|
1012
|
+
&& ['blocked', 'incomplete'].includes(String(summary?.status || ''))
|
|
1013
|
+
&& summary?.completion_evidence !== true
|
|
1014
|
+
&& gate?.passed !== true
|
|
1015
|
+
&& gate?.terminal_state === 'blocked') {
|
|
1016
|
+
return 'blocked';
|
|
1017
|
+
}
|
|
1018
|
+
return null;
|
|
1019
|
+
}
|
|
971
1020
|
async function activePipelinePlanNote(root, state = {}) {
|
|
972
1021
|
if (!state?.mission_id)
|
|
973
1022
|
return '';
|
|
@@ -1263,6 +1312,35 @@ async function prepareGx(root, route, task, required, opts = {}) {
|
|
|
1263
1312
|
await setCurrent(root, routeState(id, route, 'GX_VALIDATE_REQUIRED', required, { prompt: task, ...pipelinePlanState(pipelinePlan) }), { sessionKey: opts.sessionKey });
|
|
1264
1313
|
return routeContext(route, id, task, required, 'Run sks gx init/render/validate/drift/snapshot, then pass gx-gate.json.');
|
|
1265
1314
|
}
|
|
1315
|
+
async function prepareAlign(root, route, task, required, opts = {}) {
|
|
1316
|
+
const { id, dir } = await createMission(root, { mode: 'align', prompt: task, sessionKey: opts.sessionKey });
|
|
1317
|
+
const artifacts = await writeAlignRouteArtifacts(dir, id, task);
|
|
1318
|
+
await writeJsonAtomic(path.join(dir, 'route-context.json'), {
|
|
1319
|
+
route: route.id,
|
|
1320
|
+
command: route.command,
|
|
1321
|
+
mode: route.mode,
|
|
1322
|
+
task,
|
|
1323
|
+
mission_id: id,
|
|
1324
|
+
required_skills: route.requiredSkills,
|
|
1325
|
+
context7_required: required,
|
|
1326
|
+
context_tracking: triwikiContextTracking(),
|
|
1327
|
+
stop_gate: route.stopGate,
|
|
1328
|
+
official_guides: artifacts.plan.official_guides,
|
|
1329
|
+
workstreams: artifacts.plan.workstreams,
|
|
1330
|
+
artifacts: {
|
|
1331
|
+
plan: ALIGN_PLAN_ARTIFACT,
|
|
1332
|
+
ledger: ALIGN_LEDGER_ARTIFACT,
|
|
1333
|
+
gate: ALIGN_GATE_ARTIFACT
|
|
1334
|
+
}
|
|
1335
|
+
});
|
|
1336
|
+
const pipelinePlan = await writePipelinePlan(dir, { missionId: id, route, task, required, ambiguity: { required: false, status: 'direct_route' } });
|
|
1337
|
+
await setCurrent(root, routeState(id, route, 'ALIGN_PREPARED', required, {
|
|
1338
|
+
prompt: task,
|
|
1339
|
+
stop_gate: route.stopGate,
|
|
1340
|
+
...pipelinePlanState(pipelinePlan)
|
|
1341
|
+
}), { sessionKey: opts.sessionKey });
|
|
1342
|
+
return routeContext(route, id, task, required, alignNextActionText(id));
|
|
1343
|
+
}
|
|
1266
1344
|
async function prepareLightRoute(root, route, task, required, opts = {}) {
|
|
1267
1345
|
const { id, dir } = await createMission(root, { mode: route.id.toLowerCase(), prompt: task, sessionKey: opts.sessionKey });
|
|
1268
1346
|
await writeJsonAtomic(path.join(dir, 'route-context.json'), { route: route.id, command: route.command, task, required_skills: route.requiredSkills, context7_required: required, context_tracking: triwikiContextTracking(), stop_gate: 'honest_mode' });
|
|
@@ -413,6 +413,7 @@ function fireAndForgetProjectMemory(root, state = {}) {
|
|
|
413
413
|
return appendJsonl(path.join(missionDir(root, id), 'events.jsonl'), {
|
|
414
414
|
ts: nowIso(),
|
|
415
415
|
type: 'triwiki.agents_md_projected',
|
|
416
|
+
proof_invalidating: false,
|
|
416
417
|
ok: report.ok,
|
|
417
418
|
reason: report.reason,
|
|
418
419
|
written: report.written
|
|
@@ -424,6 +425,7 @@ function fireAndForgetProjectMemory(root, state = {}) {
|
|
|
424
425
|
return appendJsonl(path.join(missionDir(root, id), 'events.jsonl'), {
|
|
425
426
|
ts: nowIso(),
|
|
426
427
|
type: 'triwiki.agents_md_project_failed',
|
|
428
|
+
proof_invalidating: false,
|
|
427
429
|
error: err?.message || String(err)
|
|
428
430
|
}).catch(() => undefined);
|
|
429
431
|
});
|
|
@@ -473,7 +475,7 @@ async function complianceBlock(root, state = {}, reason = '', detail = {}) {
|
|
|
473
475
|
missing: Array.isArray(detail.missing) ? detail.missing : []
|
|
474
476
|
};
|
|
475
477
|
await writeJsonAtomic(guardPath, record);
|
|
476
|
-
await appendJsonl(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'pipeline.compliance_loop_guard', gate: record.gate, repeat_count: count, limit, tripped: record.tripped, missing: record.missing });
|
|
478
|
+
await appendJsonl(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'pipeline.compliance_loop_guard', proof_invalidating: false, gate: record.gate, repeat_count: count, limit, tripped: record.tripped, missing: record.missing });
|
|
477
479
|
if (!record.tripped)
|
|
478
480
|
return { decision: 'block', reason, gate: detail.gate || state.stop_gate || null, missing: Array.isArray(detail.missing) ? detail.missing : [] };
|
|
479
481
|
await writeJsonAtomic(path.join(dir, HARD_BLOCKER_ARTIFACT), {
|
|
@@ -492,7 +494,7 @@ async function complianceBlock(root, state = {}, reason = '', detail = {}) {
|
|
|
492
494
|
'Pipeline stopped as a hard blocker instead of looping indefinitely; no completion success is claimed.'
|
|
493
495
|
]
|
|
494
496
|
});
|
|
495
|
-
await appendJsonl(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'pipeline.compliance_loop_guard.tripped', gate: record.gate, repeat_count: count, limit });
|
|
497
|
+
await appendJsonl(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'pipeline.compliance_loop_guard.tripped', proof_invalidating: false, gate: record.gate, repeat_count: count, limit });
|
|
496
498
|
return { decision: 'escalate', reason, gate: detail.gate || state.stop_gate || null, repeat_count: count, message: '동일 사유가 반복됩니다. 사용자 개입이 필요합니다.', systemMessage: '동일 사유가 반복됩니다. 사용자 개입이 필요합니다.' };
|
|
497
499
|
}
|
|
498
500
|
async function markReflectionInvalidatedForGateFailure(root, state = {}, detail = {}) {
|
|
@@ -611,6 +613,7 @@ async function resolveRecoveredComplianceBlocker(root, state = {}, recovered) {
|
|
|
611
613
|
await appendJsonl(path.join(dir, 'events.jsonl'), {
|
|
612
614
|
ts: nowIso(),
|
|
613
615
|
type: 'pipeline.compliance_loop_guard.resolved',
|
|
616
|
+
proof_invalidating: false,
|
|
614
617
|
gate,
|
|
615
618
|
recovery_artifact: artifactName,
|
|
616
619
|
hard_blocker_sha256: blockerSha256,
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
export const LATEST_VERSION_GUIDANCE_SCHEMA = 'sks.latest-version-guidance.v1';
|
|
2
|
+
const SEMVER_RE = /\b\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?\b/g;
|
|
3
|
+
export const GUIDANCE_TRIGGERS = [
|
|
4
|
+
'current release',
|
|
5
|
+
'current version',
|
|
6
|
+
'currently',
|
|
7
|
+
'preferred',
|
|
8
|
+
'minimum',
|
|
9
|
+
'at least',
|
|
10
|
+
'requires',
|
|
11
|
+
'required',
|
|
12
|
+
'require',
|
|
13
|
+
'must be',
|
|
14
|
+
'must use',
|
|
15
|
+
'update to',
|
|
16
|
+
'upgrade to',
|
|
17
|
+
'recommend',
|
|
18
|
+
'recommended',
|
|
19
|
+
'or later',
|
|
20
|
+
'or newer',
|
|
21
|
+
'or above',
|
|
22
|
+
'supported version',
|
|
23
|
+
'baseline remains',
|
|
24
|
+
'이상',
|
|
25
|
+
'권장',
|
|
26
|
+
'최소',
|
|
27
|
+
'필요합니다',
|
|
28
|
+
'사용하세요'
|
|
29
|
+
];
|
|
30
|
+
export const HISTORICAL_MARKERS = [
|
|
31
|
+
'changelog',
|
|
32
|
+
'historical',
|
|
33
|
+
'history',
|
|
34
|
+
'previously',
|
|
35
|
+
'fixed in',
|
|
36
|
+
'regression',
|
|
37
|
+
'released in',
|
|
38
|
+
'shipped in',
|
|
39
|
+
'was released',
|
|
40
|
+
'compatibility matrix',
|
|
41
|
+
'compatibility snapshot',
|
|
42
|
+
'schema revision',
|
|
43
|
+
'fixture',
|
|
44
|
+
'reproduces',
|
|
45
|
+
'as of the',
|
|
46
|
+
'no longer'
|
|
47
|
+
];
|
|
48
|
+
const STRING_LITERAL_RE = /'(?:[^'\\\n]|\\.)*'|"(?:[^"\\\n]|\\.)*"|`(?:[^`\\]|\\.)*`/g;
|
|
49
|
+
const WINDOW_CHARS = 90;
|
|
50
|
+
function containsTrigger(haystack) {
|
|
51
|
+
const lower = haystack.toLowerCase();
|
|
52
|
+
for (const trigger of GUIDANCE_TRIGGERS) {
|
|
53
|
+
if (lower.includes(trigger.toLowerCase()))
|
|
54
|
+
return trigger;
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function isHistorical(haystack) {
|
|
59
|
+
const lower = haystack.toLowerCase();
|
|
60
|
+
return HISTORICAL_MARKERS.some((marker) => lower.includes(marker));
|
|
61
|
+
}
|
|
62
|
+
function excerpt(line) {
|
|
63
|
+
const compact = line.trim().replace(/\s+/g, ' ');
|
|
64
|
+
return compact.length > 160 ? `${compact.slice(0, 157)}...` : compact;
|
|
65
|
+
}
|
|
66
|
+
export function scanLatestVersionGuidance(relativePath, text, options = {}) {
|
|
67
|
+
const findings = [];
|
|
68
|
+
const lines = text.split(/\r?\n/);
|
|
69
|
+
for (const [index, rawLine] of lines.entries()) {
|
|
70
|
+
const line = rawLine ?? '';
|
|
71
|
+
const candidates = [];
|
|
72
|
+
if (options.stringLiteralsOnly) {
|
|
73
|
+
STRING_LITERAL_RE.lastIndex = 0;
|
|
74
|
+
let match;
|
|
75
|
+
while ((match = STRING_LITERAL_RE.exec(line)))
|
|
76
|
+
candidates.push(match[0]);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
candidates.push(line);
|
|
80
|
+
}
|
|
81
|
+
if (!candidates.length)
|
|
82
|
+
continue;
|
|
83
|
+
let reported = false;
|
|
84
|
+
for (const candidate of candidates) {
|
|
85
|
+
if (reported)
|
|
86
|
+
break;
|
|
87
|
+
SEMVER_RE.lastIndex = 0;
|
|
88
|
+
let match;
|
|
89
|
+
while ((match = SEMVER_RE.exec(candidate))) {
|
|
90
|
+
const window = candidate.slice(Math.max(0, match.index - WINDOW_CHARS), match.index + match[0].length + WINDOW_CHARS);
|
|
91
|
+
if (isHistorical(window))
|
|
92
|
+
continue;
|
|
93
|
+
const trigger = containsTrigger(window);
|
|
94
|
+
if (!trigger)
|
|
95
|
+
continue;
|
|
96
|
+
findings.push({ path: relativePath, line: index + 1, version: match[0], trigger, excerpt: excerpt(line) });
|
|
97
|
+
reported = true;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return findings;
|
|
103
|
+
}
|
|
104
|
+
export const LATEST_VERSION_GUIDANCE_TEXT = 'Use the official latest stable SKS and Codex CLI releases. Run `sks update-check` and read the capability report for the current state — feature support is decided by capability probes, not by a pinned version number.';
|
|
105
|
+
export function latestVersionGuidanceReport(findings, scannedFiles, exemptions) {
|
|
106
|
+
return {
|
|
107
|
+
schema: LATEST_VERSION_GUIDANCE_SCHEMA,
|
|
108
|
+
ok: findings.length === 0,
|
|
109
|
+
scannedFiles,
|
|
110
|
+
findings: [...findings].sort((left, right) => left.path.localeCompare(right.path) || left.line - right.line),
|
|
111
|
+
exemptions: [...exemptions].sort()
|
|
112
|
+
};
|
|
113
|
+
}
|