Merge remote-tracking branch 'origin/master' into fix/stats

This commit is contained in:
07akioni
2026-08-12 21:22:05 +08:00
465 changed files with 11350 additions and 1149 deletions

View File

@@ -19,11 +19,32 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SDK_DISTRIBUTION = "deepseek-harness-sdk"
RUNTIME_DISTRIBUTION = "deepseek-harness-runtime-bin"
PLATFORMS = {
"linux-x64": ("manylinux_2_28_x86_64", "dsh-jsonrpc-agent-pkg-linux-x64"),
"linux-arm64": ("manylinux_2_28_aarch64", "dsh-jsonrpc-agent-pkg-linux-arm64"),
"macos-arm64": ("macosx_11_0_arm64", "dsh-jsonrpc-agent-pkg-macos-arm64"),
}
PLATFORM_MANIFEST = ROOT / "python" / "sdk-runtime" / "platforms.json"
def load_platforms(path: Path = PLATFORM_MANIFEST) -> dict[str, tuple[str, str]]:
"""Load the release platform tag and executable pairs from the build manifest."""
try:
payload = json.loads(path.read_text())
except (OSError, json.JSONDecodeError) as error:
raise ValueError(f"could not read runtime platform manifest from {path}") from error
if not isinstance(payload, dict) or not payload:
raise ValueError(f"{path} must contain a non-empty platform object")
platforms: dict[str, tuple[str, str]] = {}
for name, raw in payload.items():
if (
not isinstance(name, str)
or not isinstance(raw, dict)
or set(raw) != {"tag", "executable"}
or not isinstance(raw["tag"], str)
or not isinstance(raw["executable"], str)
):
raise ValueError(f"{path} platform entries must contain string tag and executable fields")
platforms[name] = (raw["tag"], raw["executable"])
return platforms
PLATFORMS = load_platforms()
def runtime_suffixes(executable_name: str) -> tuple[str, ...]:
@@ -35,7 +56,7 @@ def main() -> None:
parser.add_argument("--package", choices=("sdk", "runtime"), required=True)
parser.add_argument(
"--tag",
help="optional python-vX.Y.Z release tag; it must match package.json",
help="optional python-v<repository-version> release tag; it must match package.json",
)
parser.add_argument("--output-dir", type=Path, required=True)
parser.add_argument("--platform", choices=tuple(PLATFORMS))
@@ -146,8 +167,29 @@ def rewrite_version(pyproject: Path, version: str) -> None:
pyproject.write_text(text)
def stage_license_files(destination: Path, *, include_notices: bool) -> None:
"""Copy legal files and declare them as wheel license payloads."""
shutil.copy2(ROOT / "LICENSE", destination / "LICENSE")
license_files = '["LICENSE"]'
if include_notices:
shutil.copy2(ROOT / "THIRD_PARTY_NOTICES.md", destination / "THIRD_PARTY_NOTICES.md")
license_files = '["LICENSE", "THIRD_PARTY_NOTICES.md"]'
pyproject = destination / "pyproject.toml"
text, count = re.subn(
r'^(license = "[^"]+")$',
rf"\1\nlicense-files = {license_files}",
pyproject.read_text(),
count=1,
flags=re.MULTILINE,
)
if count != 1:
raise RuntimeError(f"could not declare license files in {pyproject}")
pyproject.write_text(text)
def stage_sdk(destination: Path, version: str) -> None:
copy_package(ROOT / "python" / "sdk", destination)
stage_license_files(destination, include_notices=False)
pyproject = destination / "pyproject.toml"
rewrite_version(pyproject, version)
text, count = re.subn(
@@ -163,6 +205,7 @@ def stage_sdk(destination: Path, version: str) -> None:
def stage_runtime(destination: Path, version: str, executable: Path, executable_name: str) -> None:
copy_package(ROOT / "python" / "sdk-runtime", destination)
stage_license_files(destination, include_notices=True)
rewrite_version(destination / "pyproject.toml", version)
runtime_dir = destination / "src" / "deepseek_harness_runtime" / "runtime"
runtime_dir.mkdir(parents=True, exist_ok=True)
@@ -191,6 +234,16 @@ def verify_wheel(
raise RuntimeError(
f"{wheel} has distribution name {metadata.get('Name')}, expected {expected_distribution}"
)
if metadata.get("License-Expression") != "BSD-3-Clause":
raise RuntimeError(
f"{wheel} has license expression {metadata.get('License-Expression')}, expected BSD-3-Clause"
)
expected_license_files = ["LICENSE"] if package == "sdk" else ["LICENSE", "THIRD_PARTY_NOTICES.md"]
license_files = [Path(name).name for name in metadata.get_all("License-File") or []]
if license_files != expected_license_files:
raise RuntimeError(
f"{wheel} has license files {license_files}, expected {expected_license_files}"
)
runtime_files = [
name for name in archive.namelist() if "/runtime/dsh-jsonrpc-agent-pkg-" in name
]

View File

@@ -0,0 +1,95 @@
#!/usr/bin/env python3
"""Reject runtime executables that require newer macOS than their wheel tag."""
from __future__ import annotations
import argparse
import re
import runpy
import subprocess
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
RELEASE = runpy.run_path(str(ROOT / "scripts" / "build-python-release.py"))
MACOS_PLATFORM_TAG = RELEASE["PLATFORMS"]["macos-arm64"][0]
def parse_version(value: str) -> tuple[int, ...]:
"""Parse a dot-separated numeric deployment version."""
if re.fullmatch(r"\d+(?:\.\d+)*", value) is None:
raise ValueError(f"invalid macOS deployment version: {value!r}")
return tuple(int(part) for part in value.split("."))
def claimed_version(platform_tag: str) -> tuple[int, ...]:
"""Return the minimum macOS version encoded by a wheel platform tag."""
match = re.fullmatch(r"macosx_(\d+)_(\d+)_arm64", platform_tag)
if match is None:
raise ValueError(f"unsupported macOS wheel platform tag: {platform_tag!r}")
return int(match.group(1)), int(match.group(2))
def parse_otool_deployment_target(output: str) -> tuple[int, ...]:
"""Return the newest deployment target from one or more Mach-O slices."""
versions = [
parse_version(match.group(1))
for match in re.finditer(r"^\s*minos\s+(\d+(?:\.\d+)*)\s*$", output, re.MULTILINE)
]
if not versions:
raise ValueError("otool output contains no LC_BUILD_VERSION deployment target")
return max(versions)
def deployment_target(executable: Path) -> tuple[int, ...]:
"""Read one Mach-O executable's deployment target with ``otool``."""
if not executable.is_file():
raise FileNotFoundError(f"runtime executable does not exist: {executable}")
result = subprocess.run(
["otool", "-l", str(executable)],
check=True,
capture_output=True,
text=True,
)
try:
return parse_otool_deployment_target(result.stdout)
except ValueError as error:
raise ValueError(f"{executable}: {error}") from error
def ensure_compatible(
executable: Path, actual: tuple[int, ...], platform_tag: str
) -> None:
"""Reject an executable whose deployment target exceeds its wheel claim."""
claimed = claimed_version(platform_tag)
width = max(len(actual), len(claimed))
padded_actual = actual + (0,) * (width - len(actual))
padded_claimed = claimed + (0,) * (width - len(claimed))
if padded_actual > padded_claimed:
rendered = ".".join(str(part) for part in actual)
raise RuntimeError(
f"{executable} requires macOS {rendered} but the wheel claims {platform_tag}"
)
def validate_deployment_targets(
executables: list[Path], platform_tag: str = MACOS_PLATFORM_TAG
) -> list[tuple[Path, tuple[int, ...]]]:
"""Validate every executable and return its measured deployment target."""
measured = [(executable, deployment_target(executable)) for executable in executables]
for executable, actual in measured:
ensure_compatible(executable, actual, platform_tag)
return measured
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("executables", type=Path, nargs="+")
args = parser.parse_args()
for executable, version in validate_deployment_targets(args.executables):
rendered = ".".join(str(part) for part in version)
print(f"{executable}: macOS {rendered} <= {MACOS_PLATFORM_TAG}")
if __name__ == "__main__":
main()

View File

@@ -92,6 +92,26 @@ describe('CI workflow', () => {
expect(config).not.toContain('packages/lsp/lsp-local/src/instance.ts')
})
it('requires one release-shaped Python runtime target on every pull request', () => {
const workflow = loadWorkflow('.github/workflows/ci.yml')
const pythonRuntime = workflowJob(workflow, 'python-runtime')
const aggregate = workflowJob(workflow, 'all-checks-passed')
if (!Array.isArray(aggregate.needs)) {
throw new TypeError('CI aggregate must define required job dependencies')
}
expect(pythonRuntime).toMatchObject({
if: "github.event_name == 'pull_request'",
name: 'python runtime / release-shaped Linux x64',
uses: './.github/workflows/build-exe-for-python-sdk.yml',
with: {
targets: 'node24-linux-x64',
ci: true,
},
})
expect(aggregate.needs).toContain('python-runtime')
})
it('keeps every Vitest project process-isolated on native Windows', () => {
const config = readFileSync(resolve(root, 'vitest.config.ts'), 'utf8')
@@ -127,6 +147,142 @@ describe('E2B e2e workflow', () => {
})
})
describe('Python release workflows', () => {
it('keeps complete wheel validation separate from protected public publication', () => {
const workflow = loadWorkflow('.github/workflows/python-release.yml')
const dispatch = workflowEvent(workflow, 'workflow_dispatch')
const pullRequest = workflowEvent(workflow, 'pull_request')
const build = workflowJob(workflow, 'build')
const pythonCompat = workflowJob(workflow, 'python-compat')
const validate = workflowJob(workflow, 'validate')
const publishRuntime = workflowJob(workflow, 'publish-runtime')
const publishSdk = workflowJob(workflow, 'publish-sdk')
if (!isRecord(dispatch.inputs)
|| !isRecord(dispatch.inputs.publish)
|| !Array.isArray(pythonCompat.steps)
|| !Array.isArray(validate.steps)
|| !Array.isArray(publishRuntime.steps)
|| !Array.isArray(publishSdk.steps)) {
throw new TypeError('Python release workflow must define publish input and release steps')
}
expect(dispatch.inputs.publish).toMatchObject({ type: 'boolean', default: false })
expect(pullRequest).toEqual({ types: ['labeled'] })
expect(build).toMatchObject({
if: "github.event_name == 'workflow_dispatch' || github.event.label.name == 'python-release-dry-run'",
uses: './.github/workflows/build-exe-for-python-sdk.yml',
with: {
targets: 'node24-linux-x64,node24-linux-arm64,node24-macos-arm64',
release: true,
},
})
expect(pythonCompat.strategy).toMatchObject({ matrix: { python: ['3.10', '3.14'] } })
expect(JSON.stringify(pythonCompat.steps)).toContain('deepseek-harness-sdk==${{ steps.compatibility-version.outputs.version }}')
const validateSteps = JSON.stringify(validate.steps)
const authorize = validate.steps.filter(isRecord).find(step => step.name === 'Authorize publication request')
if (!isRecord(authorize) || typeof authorize.run !== 'string') {
throw new TypeError('Python release validation must authorize publication requests')
}
expect(validateSteps).toContain('PUBLIC_PYPI_RELEASE_ENABLED')
expect(authorize).toMatchObject({
env: {
PYPI_PUBLISHER_REPOSITORY: '${{ vars.PYPI_PUBLISHER_REPOSITORY }}',
REPOSITORY: '${{ github.repository }}',
},
})
expect(authorize.run).toContain('[ "$REPOSITORY" = "$PYPI_PUBLISHER_REPOSITORY" ]')
expect(validateSteps).toContain('100000000')
expect(publishRuntime).toMatchObject({
if: "github.event_name == 'workflow_dispatch' && inputs.publish",
needs: 'validate',
environment: 'pypi-runtime',
permissions: { contents: 'read', 'id-token': 'write' },
})
expect(publishSdk).toMatchObject({
if: "github.event_name == 'workflow_dispatch' && inputs.publish",
needs: ['validate', 'publish-runtime'],
environment: 'pypi',
permissions: { contents: 'read', 'id-token': 'write' },
})
const runtimeSteps = publishRuntime.steps.filter(isRecord)
const sdkSteps = publishSdk.steps.filter(isRecord)
const runtimePublish = runtimeSteps.find(step => step.name === 'Publish runtime wheels')
const sdkPublish = sdkSteps.find(step => step.name === 'Publish SDK wheel')
const runtimeHashes = runtimeSteps.find(step => step.name === 'Verify release artifact hashes')
const sdkHashes = sdkSteps.find(step => step.name === 'Verify release artifact hashes')
expect([...runtimeSteps, ...sdkSteps].some(
step => typeof step.uses === 'string' && step.uses.startsWith('actions/checkout@'),
)).toBe(false)
expect([...runtimeSteps, ...sdkSteps].filter(
step => step.uses === 'pypa/gh-action-pypi-publish@release/v1',
)).toHaveLength(2)
expect(runtimePublish).toMatchObject({
with: { 'packages-dir': 'dist/runtime/', attestations: false },
})
expect(sdkPublish).toMatchObject({
with: { 'packages-dir': 'dist/sdk/', attestations: false },
})
expect(runtimeHashes).toMatchObject({ run: 'cd dist && sha256sum -c SHA256SUMS' })
expect(sdkHashes).toMatchObject({ run: 'cd dist && sha256sum -c SHA256SUMS' })
})
it('exposes the native wheel builder to the release caller with normalized versions', () => {
const workflow = loadWorkflow('.github/workflows/build-exe-for-python-sdk.yml')
const call = workflowEvent(workflow, 'workflow_call')
const plan = workflowJob(workflow, 'plan')
const build = workflowJob(workflow, 'build')
if (!isRecord(call.inputs) || !Array.isArray(plan.steps) || !Array.isArray(build.steps)) {
throw new TypeError('Python wheel builder must define workflow_call inputs and plan steps')
}
const buildSteps: unknown[] = build.steps
const manylinuxAddon = buildSteps.find(step => isRecord(step) && step.name === 'Rebuild Linux node-pty against manylinux 2.28')
const macosCheck = buildSteps.find(step => isRecord(step) && step.name === 'Check macOS deployment target')
const manylinuxSmoke = buildSteps.find(step => isRecord(step) && step.name === 'Run wheel in a manylinux 2.28 container')
expect(call.inputs).toHaveProperty('targets')
expect(call.inputs).toMatchObject({
ci: { type: 'boolean', default: false },
release: { type: 'boolean', default: false },
})
expect(workflow.concurrency).toMatchObject({
group: 'build-single-exe-${{ github.workflow }}-${{ github.ref }}',
})
expect(plan.if).toContain('inputs.ci')
expect(plan.if).toContain('inputs.release')
expect(JSON.stringify(plan.steps)).toContain('pep440_version')
expect(JSON.stringify(workflow)).toContain('macosx_14_0_arm64')
expect(manylinuxAddon).toMatchObject({ if: "runner.os == 'Linux'" })
expect(JSON.stringify(manylinuxAddon)).toContain('manylinux_2_28_x86_64')
expect(JSON.stringify(manylinuxAddon)).toContain('manylinux_2_28_aarch64')
expect(JSON.stringify(manylinuxAddon)).toContain('$HOME/setup-pnpm:$HOME/setup-pnpm:ro')
expect(JSON.stringify(manylinuxAddon)).toContain('node-pty-glibc-versions.txt')
expect(JSON.stringify(manylinuxAddon)).toContain('le 2.28')
expect(macosCheck).toMatchObject({ if: "runner.os == 'macOS'" })
expect(JSON.stringify(macosCheck)).toContain('scripts/check-macos-deployment-target.py')
expect(JSON.stringify(macosCheck)).toContain('$EXE-spawn-helper')
expect(manylinuxSmoke).toMatchObject({ if: "runner.os == 'Linux'" })
expect(JSON.stringify(manylinuxSmoke)).toContain('-e DSH_TELEMETRY_DISABLED')
})
it('uses the shared macOS deployment-target check in GitLab', () => {
const workflow = loadWorkflow('.gitlab-ci.yml')
const runtimeWheel = workflow['.runtime-wheel']
if (!isRecord(runtimeWheel) || !Array.isArray(runtimeWheel.script)) {
throw new TypeError('GitLab CI must define the runtime wheel script')
}
const runtimeScript: unknown[] = runtimeWheel.script
const macosCheck = runtimeScript.find(
step => typeof step === 'string' && step.includes('PLATFORM" = macos-arm64'),
)
if (typeof macosCheck !== 'string') {
throw new TypeError('GitLab CI must check the macOS deployment target')
}
expect(macosCheck).toContain('scripts/check-macos-deployment-target.py')
expect(macosCheck).toContain('"$EXE" "$EXE-spawn-helper"')
})
})
describe('Issue lifecycle workflow', () => {
it('uses explicit review handoff events without rerunning when a draft becomes ready', () => {
const lifecycle = loadWorkflow('.github/workflows/issue-lifecycle.yml')

View File

@@ -133,6 +133,7 @@ export const SERVICE_WALK_EXEMPTIONS: Record<string, string> = {
models: 'client-side interface-typed browser service — packages/client/ui-model/README.md owns the API',
modules: 'client-side interface-typed browser service — packages/client/modules/README.md owns the API',
remote: 'client-side interface-typed gateway accessor (ClientRemote) — packages/api/gateway/README.md owns the API',
sessionExport: 'client-side browser download controller — packages/session-query/session-export/README.md owns the API',
slash: 'client-side interface-typed browser service — packages/client/ui-slash/README.md owns the API',
slots: 'client-side interface-typed browser service — packages/client/runtime/README.md owns the API',
theme: 'client-side interface-typed browser service — packages/client/ui-theme/README.md owns the API',
@@ -178,6 +179,7 @@ export const EVENT_SCOPE_PAGE: Record<string, string> = {
* exemption cannot mask another declaration in that scope.
*/
export const EVENT_WALK_EXEMPTIONS: Record<string, string> = {
'command/executed': 'client-face local command acknowledgment — packages/client/ui-command/README.md owns the API',
'connection/reset': 'client-face transport signal — packages/client/runtime/README.md owns the API',
'locale/change': 'client-face locale switch signal — packages/client/locale/README.md owns the API',
'slash/input-begin-command': 'client-face slash-input protocol — packages/client/ui-slash/README.md owns the API',

View File

@@ -123,7 +123,7 @@ const POSTCONDITIONS: readonly PostCondition[] = [
{ file: 'scripts/check-workspace-constraints.ts', text: '?.[\'@deepseek-ai/cordis\']', count: 2 },
{ file: 'packages/boot/app-boot/tsdown.config.ts', text: '[\'@deepseek-ai/cordis-plugin-include\']', count: 1 },
{ file: 'tsconfig.base.json', text: '"@deepseek-ai/cordis-plugin-loader": ["./vendor/loader/src"]', count: 1 },
// One insertion, once: a duplicated log entry is what a non-idempotent apply produced.
// The vendored README owns this required entry; reject its deletion or duplication.
{ file: 'vendor/README.md', text: '17. **`@deepseek-ai` rescope**', count: 1 },
{ file: 'knip.json', text: '@cordisjs', count: 0 },
{ file: 'pnpm-workspace.yaml', text: 'cordis@4.0.0-rc.7', count: 0 },
@@ -241,13 +241,6 @@ const EXACT_EDITS: readonly ExactEdit[] = [
replace: '| Directory | npm name | Upstream name | Version | Upstream repo | Commit |\n|---|---|---|---|---|---|',
expect: 1,
},
{
id: 'vendor-readme-local-modification-log',
file: 'vendor/README.md',
find: '\n16. **`cordis/package.json` publishes `src`**',
replace: '\n16. **`cordis/package.json` publishes `src`**: added `src` to the `files` list, joining the other eight vendored packages. Cordis declares `"./src/*": "./src/*"` in its exports, so a tarball without `src` publishes an export map pointing at absent files; the release change judgement also reads `files` to decide whether a diff reaches the payload, and a package whose only published paths are build output has no tracked path to match.\n17. **`@deepseek-ai` rescope**: every vendored manifest `name`, every internal dependency entry among the vendored set, and every module specifier that reaches them use the scoped names in the manifest table\'s `npm name` column. Directory names, version numbers, and dependency ranges are unchanged, and no upstream runtime identifier is renamed — `Symbol.for(\'schemastery\')` and Schemastery\'s `vendor:` metadata field keep their upstream values. Re-apply with `pnpm run rescope-vendor --apply` after a sync; the table\'s two name columns are the mapping, restated for consumers in [docs/rescope.md](../docs/rescope.md).',
expect: 1,
},
{
// A plain fence listing the bundle's mounted tree: a bare token, no quotes.
id: 'agent-spine-demo-mounted-tree',

View File

@@ -155,15 +155,16 @@ def completion_chunks(body: dict[str, object]) -> list[dict[str, object]]:
return text_chunks(WORKFLOW_WORKER_TEXT)
raise AssertionError(f"unexpected tool follow-up: {tool_name}")
user_prompts = [
message_text(message.get("content"))
for message in reversed(messages)
if isinstance(message, dict) and message.get("role") == "user"
]
minimal_prompt = next(
(
message_text(message.get("content"))
for message in reversed(messages)
if isinstance(message, dict)
and message.get("role") == "user"
and message_text(message.get("content")).startswith(
f"{MINIMAL_PROMPT}\n{MINIMAL_EDITOR_PATH_PREFIX}"
)
prompt
for prompt in user_prompts
if prompt.startswith(f"{MINIMAL_PROMPT}\n{MINIMAL_EDITOR_PATH_PREFIX}")
),
None,
)
@@ -183,7 +184,17 @@ def completion_chunks(body: dict[str, object]) -> list[dict[str, object]]:
"bash",
{"command": MINIMAL_BASH_COMMAND},
)
prompt = message_text(latest.get("content"))
scenario_prompts = {
SNAPSHOT_DIRECT_CHILD_PROMPT,
SNAPSHOT_WORKFLOW_CHILD_PROMPT,
SNAPSHOT_PROMPT,
CODE_PROMPT,
WORKFLOW_PROMPT,
}
prompt = next(
(candidate for candidate in user_prompts if candidate in scenario_prompts),
message_text(latest.get("content")),
)
if prompt == SNAPSHOT_DIRECT_CHILD_PROMPT:
return text_chunks("DIRECT_CHILD_OK")
if prompt == SNAPSHOT_WORKFLOW_CHILD_PROMPT:
@@ -781,6 +792,7 @@ def build_snapshot_files(
) -> dict[str, str]:
"""Render the SDK result and three persisted logs into stable expected outputs."""
replacements = [(str(cwd), "{{cwd}}"), (SNAPSHOT_SESSION_ID, "{{parent}}")]
replacements.append((snapshot_workflow_run_id(result), "{{workflow-run}}"))
for index, child_id in enumerate(child_ids, start=1):
replacements.append((child_id, f"{{{{child-{index}}}}}"))
agent_id = snapshot_agent_id(result, child_id)
@@ -813,6 +825,21 @@ def build_snapshot_files(
return files
def snapshot_workflow_run_id(result: "RunResult") -> str:
"""Return the one workflow run id emitted by the advanced scenario."""
run_ids: set[str] = set()
for event in result.events:
event_type = event.get("type")
data = event.get("data")
if not isinstance(event_type, str) or not event_type.startswith("tool-workflow/"):
continue
if isinstance(data, dict) and isinstance(data.get("runId"), str):
run_ids.add(data["runId"])
if len(run_ids) != 1:
raise AssertionError(f"advanced snapshot expected one workflow run id: {sorted(run_ids)}")
return next(iter(run_ids))
def snapshot_agent_id(result: "RunResult", child_id: str) -> str:
"""Find the successful subagent id paired with one child session."""
for notification in result.notifications:

View File

@@ -874,9 +874,49 @@
}
},
{
"type": "tool/result",
"type": "tool-workflow/run-start",
"seq": 48,
"time": 0,
"data": {
"runId": "{{workflow-run}}",
"name": "advanced-exe-snapshot"
}
},
{
"type": "tool-workflow/agent-start",
"seq": 49,
"time": 0,
"data": {
"runId": "{{workflow-run}}",
"seq": 1,
"label": "workflow-child",
"phase": "Delegate",
"childId": "{{child-2}}"
}
},
{
"type": "tool-workflow/agent-end",
"seq": 50,
"time": 0,
"data": {
"runId": "{{workflow-run}}",
"seq": 1,
"outcome": "completed"
}
},
{
"type": "tool-workflow/run-end",
"seq": 51,
"time": 0,
"data": {
"runId": "{{workflow-run}}",
"stopReason": "completed"
}
},
{
"type": "tool/result",
"seq": 52,
"time": 0,
"data": {
"turn": 1,
"step": 4,
@@ -909,7 +949,7 @@
},
{
"type": "step/end",
"seq": 49,
"seq": 53,
"time": 0,
"data": {
"turn": 1,
@@ -918,7 +958,7 @@
},
{
"type": "step/start",
"seq": 50,
"seq": 54,
"time": 0,
"data": {
"turn": 1,
@@ -927,7 +967,7 @@
},
{
"type": "assistant/chunk",
"seq": 51,
"seq": 55,
"time": 0,
"data": {
"turn": 1,
@@ -941,7 +981,7 @@
},
{
"type": "assistant/chunk",
"seq": 52,
"seq": 56,
"time": 0,
"data": {
"turn": 1,
@@ -957,7 +997,7 @@
},
{
"type": "assistant/chunk",
"seq": 53,
"seq": 57,
"time": 0,
"data": {
"turn": 1,
@@ -976,7 +1016,7 @@
},
{
"type": "assistant/chunk",
"seq": 54,
"seq": 58,
"time": 0,
"data": {
"turn": 1,
@@ -992,7 +1032,7 @@
},
{
"type": "assistant/chunk",
"seq": 55,
"seq": 59,
"time": 0,
"data": {
"turn": 1,
@@ -1007,7 +1047,7 @@
},
{
"type": "assistant/message",
"seq": 56,
"seq": 60,
"time": 0,
"data": {
"turn": 1,
@@ -1035,17 +1075,17 @@
}
},
"sourceEventSeqs": [
51,
52,
53,
54,
55
55,
56,
57,
58,
59
],
"surfaceOp": "append"
},
{
"type": "tool/call",
"seq": 57,
"seq": 61,
"time": 0,
"data": {
"turn": 1,
@@ -1057,7 +1097,7 @@
},
{
"type": "tool/result",
"seq": 58,
"seq": 62,
"time": 0,
"data": {
"turn": 1,
@@ -1085,13 +1125,13 @@
}
},
"sourceEventSeqs": [
57
61
],
"surfaceOp": "append"
},
{
"type": "step/end",
"seq": 59,
"seq": 63,
"time": 0,
"data": {
"turn": 1,
@@ -1100,7 +1140,7 @@
},
{
"type": "step/start",
"seq": 60,
"seq": 64,
"time": 0,
"data": {
"turn": 1,
@@ -1109,7 +1149,7 @@
},
{
"type": "request/header",
"seq": 61,
"seq": 65,
"time": 0,
"data": {
"header": {
@@ -1141,7 +1181,7 @@
},
{
"type": "assistant/chunk",
"seq": 62,
"seq": 66,
"time": 0,
"data": {
"turn": 1,
@@ -1155,7 +1195,7 @@
},
{
"type": "assistant/chunk",
"seq": 63,
"seq": 67,
"time": 0,
"data": {
"turn": 1,
@@ -1169,7 +1209,7 @@
},
{
"type": "assistant/chunk",
"seq": 64,
"seq": 68,
"time": 0,
"data": {
"turn": 1,
@@ -1186,7 +1226,7 @@
},
{
"type": "assistant/chunk",
"seq": 65,
"seq": 69,
"time": 0,
"data": {
"turn": 1,
@@ -1202,7 +1242,7 @@
},
{
"type": "assistant/chunk",
"seq": 66,
"seq": 70,
"time": 0,
"data": {
"turn": 1,
@@ -1217,7 +1257,7 @@
},
{
"type": "assistant/message",
"seq": 67,
"seq": 71,
"time": 0,
"data": {
"turn": 1,
@@ -1243,17 +1283,17 @@
}
},
"sourceEventSeqs": [
62,
63,
64,
65,
66
66,
67,
68,
69,
70
],
"surfaceOp": "append"
},
{
"type": "step/end",
"seq": 68,
"seq": 72,
"time": 0,
"data": {
"turn": 1,
@@ -1262,7 +1302,7 @@
},
{
"type": "turn/end",
"seq": 69,
"seq": 73,
"time": 0,
"data": {
"turn": 1,
@@ -2334,9 +2374,42 @@
"payload": {
"sessionId": "{{child-1}}",
"event": {
"type": "session/title",
"type": "user/message",
"seq": 6,
"time": 0,
"data": {
"content": [
{
"type": "text",
"text": "Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."
}
],
"source": {
"kind": "plugin",
"plugin": "@deepseek-ai/dsh-system-prompt",
"form": "snapshot",
"sections": [
{
"name": "subagent:delegation",
"text": "You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."
}
]
},
"role": "user",
"id": "{{messageId}}"
},
"surfaceOp": "append"
}
}
},
{
"method": "session.event",
"payload": {
"sessionId": "{{child-1}}",
"event": {
"type": "session/title",
"seq": 7,
"time": 0,
"data": {
"title": "Reply with exactly DIRECT_CHILD_OK and",
"messageSeqs": [
@@ -2355,7 +2428,7 @@
"sessionId": "{{child-1}}",
"event": {
"type": "request/header",
"seq": 7,
"seq": 8,
"time": 0,
"data": {
"header": {
@@ -2394,7 +2467,7 @@
"sessionId": "{{child-1}}",
"event": {
"type": "request/context",
"seq": 8,
"seq": 9,
"time": 0,
"data": {
"provider": "deepseek-official",
@@ -2410,7 +2483,7 @@
"sessionId": "{{child-1}}",
"event": {
"type": "assistant/chunk",
"seq": 9,
"seq": 10,
"time": 0,
"data": {
"turn": 1,
@@ -2430,7 +2503,7 @@
"sessionId": "{{child-1}}",
"event": {
"type": "assistant/chunk",
"seq": 10,
"seq": 11,
"time": 0,
"data": {
"turn": 1,
@@ -2450,7 +2523,7 @@
"sessionId": "{{child-1}}",
"event": {
"type": "assistant/chunk",
"seq": 11,
"seq": 12,
"time": 0,
"data": {
"turn": 1,
@@ -2473,7 +2546,7 @@
"sessionId": "{{child-1}}",
"event": {
"type": "assistant/chunk",
"seq": 12,
"seq": 13,
"time": 0,
"data": {
"turn": 1,
@@ -2495,7 +2568,7 @@
"sessionId": "{{child-1}}",
"event": {
"type": "assistant/chunk",
"seq": 13,
"seq": 14,
"time": 0,
"data": {
"turn": 1,
@@ -2516,7 +2589,7 @@
"sessionId": "{{child-1}}",
"event": {
"type": "assistant/message",
"seq": 14,
"seq": 15,
"time": 0,
"data": {
"turn": 1,
@@ -2542,11 +2615,11 @@
}
},
"sourceEventSeqs": [
9,
10,
11,
12,
13
13,
14
],
"surfaceOp": "append"
}
@@ -2558,7 +2631,7 @@
"sessionId": "{{child-1}}",
"event": {
"type": "step/end",
"seq": 15,
"seq": 16,
"time": 0,
"data": {
"turn": 1,
@@ -2573,7 +2646,7 @@
"sessionId": "{{child-1}}",
"event": {
"type": "turn/end",
"seq": 16,
"seq": 17,
"time": 0,
"data": {
"turn": 1,
@@ -2850,6 +2923,21 @@
}
}
},
{
"method": "session.event",
"payload": {
"sessionId": "{{parent}}",
"event": {
"type": "tool-workflow/run-start",
"seq": 48,
"time": 0,
"data": {
"runId": "{{workflow-run}}",
"name": "advanced-exe-snapshot"
}
}
}
},
{
"method": "subagent.started",
"payload": {
@@ -2986,9 +3074,42 @@
"payload": {
"sessionId": "{{child-2}}",
"event": {
"type": "session/title",
"type": "user/message",
"seq": 6,
"time": 0,
"data": {
"content": [
{
"type": "text",
"text": "Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."
}
],
"source": {
"kind": "plugin",
"plugin": "@deepseek-ai/dsh-system-prompt",
"form": "snapshot",
"sections": [
{
"name": "subagent:delegation",
"text": "You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."
}
]
},
"role": "user",
"id": "{{messageId}}"
},
"surfaceOp": "append"
}
}
},
{
"method": "session.event",
"payload": {
"sessionId": "{{child-2}}",
"event": {
"type": "session/title",
"seq": 7,
"time": 0,
"data": {
"title": "Reply with exactly WORKFLOW_CHILD_OK and",
"messageSeqs": [
@@ -3007,7 +3128,7 @@
"sessionId": "{{child-2}}",
"event": {
"type": "request/header",
"seq": 7,
"seq": 8,
"time": 0,
"data": {
"header": {
@@ -3046,7 +3167,7 @@
"sessionId": "{{child-2}}",
"event": {
"type": "request/context",
"seq": 8,
"seq": 9,
"time": 0,
"data": {
"provider": "deepseek-official",
@@ -3056,13 +3177,31 @@
}
}
},
{
"method": "session.event",
"payload": {
"sessionId": "{{parent}}",
"event": {
"type": "tool-workflow/agent-start",
"seq": 49,
"time": 0,
"data": {
"runId": "{{workflow-run}}",
"seq": 1,
"label": "workflow-child",
"phase": "Delegate",
"childId": "{{child-2}}"
}
}
}
},
{
"method": "session.event",
"payload": {
"sessionId": "{{child-2}}",
"event": {
"type": "assistant/chunk",
"seq": 9,
"seq": 10,
"time": 0,
"data": {
"turn": 1,
@@ -3082,7 +3221,7 @@
"sessionId": "{{child-2}}",
"event": {
"type": "assistant/chunk",
"seq": 10,
"seq": 11,
"time": 0,
"data": {
"turn": 1,
@@ -3102,7 +3241,7 @@
"sessionId": "{{child-2}}",
"event": {
"type": "assistant/chunk",
"seq": 11,
"seq": 12,
"time": 0,
"data": {
"turn": 1,
@@ -3125,7 +3264,7 @@
"sessionId": "{{child-2}}",
"event": {
"type": "assistant/chunk",
"seq": 12,
"seq": 13,
"time": 0,
"data": {
"turn": 1,
@@ -3147,7 +3286,7 @@
"sessionId": "{{child-2}}",
"event": {
"type": "assistant/chunk",
"seq": 13,
"seq": 14,
"time": 0,
"data": {
"turn": 1,
@@ -3168,7 +3307,7 @@
"sessionId": "{{child-2}}",
"event": {
"type": "assistant/message",
"seq": 14,
"seq": 15,
"time": 0,
"data": {
"turn": 1,
@@ -3194,11 +3333,11 @@
}
},
"sourceEventSeqs": [
9,
10,
11,
12,
13
13,
14
],
"surfaceOp": "append"
}
@@ -3210,7 +3349,7 @@
"sessionId": "{{child-2}}",
"event": {
"type": "step/end",
"seq": 15,
"seq": 16,
"time": 0,
"data": {
"turn": 1,
@@ -3225,7 +3364,7 @@
"sessionId": "{{child-2}}",
"event": {
"type": "turn/end",
"seq": 16,
"seq": 17,
"time": 0,
"data": {
"turn": 1,
@@ -3260,13 +3399,44 @@
]
}
},
{
"method": "session.event",
"payload": {
"sessionId": "{{parent}}",
"event": {
"type": "tool-workflow/agent-end",
"seq": 50,
"time": 0,
"data": {
"runId": "{{workflow-run}}",
"seq": 1,
"outcome": "completed"
}
}
}
},
{
"method": "session.event",
"payload": {
"sessionId": "{{parent}}",
"event": {
"type": "tool-workflow/run-end",
"seq": 51,
"time": 0,
"data": {
"runId": "{{workflow-run}}",
"stopReason": "completed"
}
}
}
},
{
"method": "session.event",
"payload": {
"sessionId": "{{parent}}",
"event": {
"type": "tool/result",
"seq": 48,
"seq": 52,
"time": 0,
"data": {
"turn": 1,
@@ -3306,7 +3476,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "step/end",
"seq": 49,
"seq": 53,
"time": 0,
"data": {
"turn": 1,
@@ -3321,7 +3491,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "step/start",
"seq": 50,
"seq": 54,
"time": 0,
"data": {
"turn": 1,
@@ -3336,7 +3506,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/chunk",
"seq": 51,
"seq": 55,
"time": 0,
"data": {
"turn": 1,
@@ -3356,7 +3526,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/chunk",
"seq": 52,
"seq": 56,
"time": 0,
"data": {
"turn": 1,
@@ -3378,7 +3548,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/chunk",
"seq": 53,
"seq": 57,
"time": 0,
"data": {
"turn": 1,
@@ -3403,7 +3573,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/chunk",
"seq": 54,
"seq": 58,
"time": 0,
"data": {
"turn": 1,
@@ -3425,7 +3595,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/chunk",
"seq": 55,
"seq": 59,
"time": 0,
"data": {
"turn": 1,
@@ -3446,7 +3616,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/message",
"seq": 56,
"seq": 60,
"time": 0,
"data": {
"turn": 1,
@@ -3474,11 +3644,11 @@
}
},
"sourceEventSeqs": [
51,
52,
53,
54,
55
55,
56,
57,
58,
59
],
"surfaceOp": "append"
}
@@ -3490,7 +3660,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "tool/call",
"seq": 57,
"seq": 61,
"time": 0,
"data": {
"turn": 1,
@@ -3508,7 +3678,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "tool/result",
"seq": 58,
"seq": 62,
"time": 0,
"data": {
"turn": 1,
@@ -3536,7 +3706,7 @@
}
},
"sourceEventSeqs": [
57
61
],
"surfaceOp": "append"
}
@@ -3548,7 +3718,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "step/end",
"seq": 59,
"seq": 63,
"time": 0,
"data": {
"turn": 1,
@@ -3563,7 +3733,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "step/start",
"seq": 60,
"seq": 64,
"time": 0,
"data": {
"turn": 1,
@@ -3578,7 +3748,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "request/header",
"seq": 61,
"seq": 65,
"time": 0,
"data": {
"header": {
@@ -3616,7 +3786,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/chunk",
"seq": 62,
"seq": 66,
"time": 0,
"data": {
"turn": 1,
@@ -3636,7 +3806,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/chunk",
"seq": 63,
"seq": 67,
"time": 0,
"data": {
"turn": 1,
@@ -3656,7 +3826,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/chunk",
"seq": 64,
"seq": 68,
"time": 0,
"data": {
"turn": 1,
@@ -3679,7 +3849,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/chunk",
"seq": 65,
"seq": 69,
"time": 0,
"data": {
"turn": 1,
@@ -3701,7 +3871,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/chunk",
"seq": 66,
"seq": 70,
"time": 0,
"data": {
"turn": 1,
@@ -3722,7 +3892,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "assistant/message",
"seq": 67,
"seq": 71,
"time": 0,
"data": {
"turn": 1,
@@ -3748,11 +3918,11 @@
}
},
"sourceEventSeqs": [
62,
63,
64,
65,
66
66,
67,
68,
69,
70
],
"surfaceOp": "append"
}
@@ -3764,7 +3934,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "step/end",
"seq": 68,
"seq": 72,
"time": 0,
"data": {
"turn": 1,
@@ -3779,7 +3949,7 @@
"sessionId": "{{parent}}",
"event": {
"type": "turn/end",
"seq": 69,
"seq": 73,
"time": 0,
"data": {
"turn": 1,

View File

@@ -5,14 +5,15 @@
{"type":"subagent/descriptor","seq":3,"time":0,"data":{"version":2,"mode":"one-shot","provider":"spawn","label":"Check direct child"}}
{"type":"step/start","seq":4,"time":0,"data":{"turn":1,"step":1}}
{"type":"user/message","seq":5,"time":0,"data":{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."}],"source":{"kind":"user"},"role":"user","id":"{{messageId}}"},"surfaceOp":"append"}
{"type":"session/title","seq":6,"time":0,"data":{"title":"Reply with exactly DIRECT_CHILD_OK and","messageSeqs":[5],"source":{"kind":"fallback"}}}
{"type":"request/header","seq":7,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"smoke-model","maxTokens":256000,"reasoningEffort":"high"},"adapterDefaults":{"reasoningEffort":true,"maxTokens":true},"system":"{{system}}","tools":["cordis_inspect","cordis_mount","cordis_unmount","run_code","snapshot_double","subagent","task_kill","task_list","task_output","workflow"]},"reason":"initial"}}
{"type":"request/context","seq":8,"time":0,"data":{"provider":"deepseek-official","model":"smoke-model","contextWindow":1000000}}
{"type":"assistant/chunk","seq":9,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"DIRECT_CHILD_OK"}}}
{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DIRECT_CHILD_OK"}}}}
{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":13,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":14,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model"},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[9,10,11,12,13],"surfaceOp":"append"}
{"type":"step/end","seq":15,"time":0,"data":{"turn":1,"step":1}}
{"type":"turn/end","seq":16,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}
{"type":"user/message","seq":6,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"plugin","plugin":"@deepseek-ai/dsh-system-prompt","form":"snapshot","sections":[{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{messageId}}"},"surfaceOp":"append"}
{"type":"session/title","seq":7,"time":0,"data":{"title":"Reply with exactly DIRECT_CHILD_OK and","messageSeqs":[5],"source":{"kind":"fallback"}}}
{"type":"request/header","seq":8,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"smoke-model","maxTokens":256000,"reasoningEffort":"high"},"adapterDefaults":{"reasoningEffort":true,"maxTokens":true},"system":"{{system}}","tools":["cordis_inspect","cordis_mount","cordis_unmount","run_code","snapshot_double","subagent","task_kill","task_list","task_output","workflow"]},"reason":"initial"}}
{"type":"request/context","seq":9,"time":0,"data":{"provider":"deepseek-official","model":"smoke-model","contextWindow":1000000}}
{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"DIRECT_CHILD_OK"}}}
{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DIRECT_CHILD_OK"}}}}
{"type":"assistant/chunk","seq":13,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":14,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":15,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model"},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[10,11,12,13,14],"surfaceOp":"append"}
{"type":"step/end","seq":16,"time":0,"data":{"turn":1,"step":1}}
{"type":"turn/end","seq":17,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}

View File

@@ -5,14 +5,15 @@
{"type":"subagent/descriptor","seq":3,"time":0,"data":{"version":2,"mode":"one-shot","provider":"spawn"}}
{"type":"step/start","seq":4,"time":0,"data":{"turn":1,"step":1}}
{"type":"user/message","seq":5,"time":0,"data":{"content":[{"type":"text","text":"Reply with exactly WORKFLOW_CHILD_OK and nothing else."}],"source":{"kind":"user"},"role":"user","id":"{{messageId}}"},"surfaceOp":"append"}
{"type":"session/title","seq":6,"time":0,"data":{"title":"Reply with exactly WORKFLOW_CHILD_OK and","messageSeqs":[5],"source":{"kind":"fallback"}}}
{"type":"request/header","seq":7,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"smoke-model","maxTokens":256000,"reasoningEffort":"high"},"adapterDefaults":{"reasoningEffort":true,"maxTokens":true},"system":"{{system}}","tools":["cordis_inspect","cordis_mount","cordis_unmount","run_code","snapshot_double","subagent","task_kill","task_list","task_output","workflow"]},"reason":"initial"}}
{"type":"request/context","seq":8,"time":0,"data":{"provider":"deepseek-official","model":"smoke-model","contextWindow":1000000}}
{"type":"assistant/chunk","seq":9,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"WORKFLOW_CHILD_OK"}}}
{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"WORKFLOW_CHILD_OK"}}}}
{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":13,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":14,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"WORKFLOW_CHILD_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model"},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[9,10,11,12,13],"surfaceOp":"append"}
{"type":"step/end","seq":15,"time":0,"data":{"turn":1,"step":1}}
{"type":"turn/end","seq":16,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}
{"type":"user/message","seq":6,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"plugin","plugin":"@deepseek-ai/dsh-system-prompt","form":"snapshot","sections":[{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{messageId}}"},"surfaceOp":"append"}
{"type":"session/title","seq":7,"time":0,"data":{"title":"Reply with exactly WORKFLOW_CHILD_OK and","messageSeqs":[5],"source":{"kind":"fallback"}}}
{"type":"request/header","seq":8,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"smoke-model","maxTokens":256000,"reasoningEffort":"high"},"adapterDefaults":{"reasoningEffort":true,"maxTokens":true},"system":"{{system}}","tools":["cordis_inspect","cordis_mount","cordis_unmount","run_code","snapshot_double","subagent","task_kill","task_list","task_output","workflow"]},"reason":"initial"}}
{"type":"request/context","seq":9,"time":0,"data":{"provider":"deepseek-official","model":"smoke-model","contextWindow":1000000}}
{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"WORKFLOW_CHILD_OK"}}}
{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"WORKFLOW_CHILD_OK"}}}}
{"type":"assistant/chunk","seq":13,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":14,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":15,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"WORKFLOW_CHILD_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model"},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[10,11,12,13,14],"surfaceOp":"append"}
{"type":"step/end","seq":16,"time":0,"data":{"turn":1,"step":1}}
{"type":"turn/end","seq":17,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}

View File

@@ -47,25 +47,29 @@
{"type":"assistant/chunk","seq":45,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
{"type":"assistant/message","seq":46,"time":0,"data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\": \"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\", \"meta\": {\"name\": \"advanced-exe-snapshot\", \"description\": \"exercise one packaged workflow child\"}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model"},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[41,42,43,44,45],"surfaceOp":"append"}
{"type":"tool/call","seq":47,"time":0,"data":{"turn":1,"step":4,"callId":"advanced-workflow","name":"workflow","arguments":"{\"script\": \"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\", \"meta\": {\"name\": \"advanced-exe-snapshot\", \"description\": \"exercise one packaged workflow child\"}}"}}
{"type":"tool/result","seq":48,"time":0,"data":{"turn":1,"step":4,"message":{"source":{"kind":"tool","callId":"advanced-workflow"},"content":[{"type":"tool-result","toolCallId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-exe-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false}],"role":"user","id":"{{messageId}}"}},"sourceEventSeqs":[47],"surfaceOp":"append"}
{"type":"step/end","seq":49,"time":0,"data":{"turn":1,"step":4}}
{"type":"step/start","seq":50,"time":0,"data":{"turn":1,"step":5}}
{"type":"assistant/chunk","seq":51,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
{"type":"assistant/chunk","seq":52,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"tool-call-delta","index":0,"id":"advanced-unmount","name":"cordis_unmount","argumentsDelta":"{\"id\": \"dyn-1\"}"}}}
{"type":"assistant/chunk","seq":53,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-unmount","name":"cordis_unmount","arguments":"{\"id\": \"dyn-1\"}"}}}}
{"type":"assistant/chunk","seq":54,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":55,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
{"type":"assistant/message","seq":56,"time":0,"data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-unmount","name":"cordis_unmount","arguments":"{\"id\": \"dyn-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model"},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[51,52,53,54,55],"surfaceOp":"append"}
{"type":"tool/call","seq":57,"time":0,"data":{"turn":1,"step":5,"callId":"advanced-unmount","name":"cordis_unmount","arguments":"{\"id\": \"dyn-1\"}"}}
{"type":"tool/result","seq":58,"time":0,"data":{"turn":1,"step":5,"message":{"source":{"kind":"tool","callId":"advanced-unmount"},"content":[{"type":"tool-result","toolCallId":"advanced-unmount","content":[{"type":"text","text":"Temporary Plugin dyn-1 was unmounted and removed."}],"isError":false}],"role":"user","id":"{{messageId}}"}},"sourceEventSeqs":[57],"surfaceOp":"append"}
{"type":"step/end","seq":59,"time":0,"data":{"turn":1,"step":5}}
{"type":"step/start","seq":60,"time":0,"data":{"turn":1,"step":6}}
{"type":"request/header","seq":61,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"smoke-model","maxTokens":256000,"reasoningEffort":"high"},"adapterDefaults":{"reasoningEffort":true,"maxTokens":true},"system":"{{system}}","tools":["cordis_inspect","cordis_mount","cordis_unmount","run_code","subagent","task_kill","task_list","task_output","workflow"]},"reason":"change"}}
{"type":"assistant/chunk","seq":62,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":63,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"text-delta","index":0,"text":"ADVANCED_EXECUTABLE_OK"}}}
{"type":"assistant/chunk","seq":64,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ADVANCED_EXECUTABLE_OK"}}}}
{"type":"assistant/chunk","seq":65,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":66,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":67,"time":0,"data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"text","text":"ADVANCED_EXECUTABLE_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model"},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[62,63,64,65,66],"surfaceOp":"append"}
{"type":"step/end","seq":68,"time":0,"data":{"turn":1,"step":6}}
{"type":"turn/end","seq":69,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}
{"type":"tool-workflow/run-start","seq":48,"time":0,"data":{"runId":"{{workflow-run}}","name":"advanced-exe-snapshot"}}
{"type":"tool-workflow/agent-start","seq":49,"time":0,"data":{"runId":"{{workflow-run}}","seq":1,"label":"workflow-child","phase":"Delegate","childId":"{{child-2}}"}}
{"type":"tool-workflow/agent-end","seq":50,"time":0,"data":{"runId":"{{workflow-run}}","seq":1,"outcome":"completed"}}
{"type":"tool-workflow/run-end","seq":51,"time":0,"data":{"runId":"{{workflow-run}}","stopReason":"completed"}}
{"type":"tool/result","seq":52,"time":0,"data":{"turn":1,"step":4,"message":{"source":{"kind":"tool","callId":"advanced-workflow"},"content":[{"type":"tool-result","toolCallId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-exe-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false}],"role":"user","id":"{{messageId}}"}},"sourceEventSeqs":[47],"surfaceOp":"append"}
{"type":"step/end","seq":53,"time":0,"data":{"turn":1,"step":4}}
{"type":"step/start","seq":54,"time":0,"data":{"turn":1,"step":5}}
{"type":"assistant/chunk","seq":55,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
{"type":"assistant/chunk","seq":56,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"tool-call-delta","index":0,"id":"advanced-unmount","name":"cordis_unmount","argumentsDelta":"{\"id\": \"dyn-1\"}"}}}
{"type":"assistant/chunk","seq":57,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-unmount","name":"cordis_unmount","arguments":"{\"id\": \"dyn-1\"}"}}}}
{"type":"assistant/chunk","seq":58,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":59,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
{"type":"assistant/message","seq":60,"time":0,"data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-unmount","name":"cordis_unmount","arguments":"{\"id\": \"dyn-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model"},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[55,56,57,58,59],"surfaceOp":"append"}
{"type":"tool/call","seq":61,"time":0,"data":{"turn":1,"step":5,"callId":"advanced-unmount","name":"cordis_unmount","arguments":"{\"id\": \"dyn-1\"}"}}
{"type":"tool/result","seq":62,"time":0,"data":{"turn":1,"step":5,"message":{"source":{"kind":"tool","callId":"advanced-unmount"},"content":[{"type":"tool-result","toolCallId":"advanced-unmount","content":[{"type":"text","text":"Temporary Plugin dyn-1 was unmounted and removed."}],"isError":false}],"role":"user","id":"{{messageId}}"}},"sourceEventSeqs":[61],"surfaceOp":"append"}
{"type":"step/end","seq":63,"time":0,"data":{"turn":1,"step":5}}
{"type":"step/start","seq":64,"time":0,"data":{"turn":1,"step":6}}
{"type":"request/header","seq":65,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"smoke-model","maxTokens":256000,"reasoningEffort":"high"},"adapterDefaults":{"reasoningEffort":true,"maxTokens":true},"system":"{{system}}","tools":["cordis_inspect","cordis_mount","cordis_unmount","run_code","subagent","task_kill","task_list","task_output","workflow"]},"reason":"change"}}
{"type":"assistant/chunk","seq":66,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":67,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"text-delta","index":0,"text":"ADVANCED_EXECUTABLE_OK"}}}
{"type":"assistant/chunk","seq":68,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ADVANCED_EXECUTABLE_OK"}}}}
{"type":"assistant/chunk","seq":69,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":70,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":71,"time":0,"data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"text","text":"ADVANCED_EXECUTABLE_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model"},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[66,67,68,69,70],"surfaceOp":"append"}
{"type":"step/end","seq":72,"time":0,"data":{"turn":1,"step":6}}
{"type":"turn/end","seq":73,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}

File diff suppressed because one or more lines are too long

View File

@@ -12,8 +12,9 @@ import {
storeGitBlob,
} from './translation-pairing-git.ts'
import {
linksTo,
isTranslationScopeFile,
languageSwitcherTargets,
linksTo,
parseTranslationMarkdown,
requiresSourceLanguageSwitcher,
translationStructureDiff,
@@ -164,15 +165,17 @@ function loadRecordOwners(
function assertMergedPairStructure(paths: TranslationPairPaths, source: Buffer, zh: Buffer): void {
const sourceTree = parseTranslationMarkdown(source.toString('utf8'))
const zhTree = parseTranslationMarkdown(zh.toString('utf8'))
if (requiresSourceLanguageSwitcher(paths.source) && !linksTo(sourceTree, basename(paths.zh))) {
const sourceSwitcherTargets = languageSwitcherTargets(paths.source)
const zhSwitcherTargets = languageSwitcherTargets(paths.zh)
if (requiresSourceLanguageSwitcher(paths.source) && !linksTo(sourceTree, zhSwitcherTargets)) {
throw new Error(`${paths.source} clean merge lost its language-switcher link to ${basename(paths.zh)}`)
}
if (!linksTo(zhTree, basename(paths.source))) {
if (!linksTo(zhTree, sourceSwitcherTargets)) {
throw new Error(`${paths.zh} clean merge lost its language-switcher link to ${basename(paths.source)}`)
}
const divergences = translationStructureDiff(
translationStructureSignature(sourceTree, basename(paths.zh)),
translationStructureSignature(zhTree, basename(paths.source)),
translationStructureSignature(sourceTree, zhSwitcherTargets),
translationStructureSignature(zhTree, sourceSwitcherTargets),
)
if (divergences.length > 0) {
throw new Error(`${paths.source} and ${paths.zh} clean merges diverge structurally: ${divergences.join('; ')}`)

View File

@@ -14,6 +14,8 @@ import {
import {
blobHash,
isTranslationScopeFile,
languageSwitcherTargets,
linksTo,
pairAnchorOfArgument,
parseTranslationMarkdown,
parseTranslationPairingCliArgs,
@@ -151,6 +153,20 @@ describe('translation pairing switchers', () => {
expect(requiresSourceLanguageSwitcher('docs/architecture.md')).toBe(true)
expect(requiresSourceLanguageSwitcher('packages/core/session/README.md')).toBe(true)
})
it('accepts only the canonical public URL for an absolute switcher', () => {
const targets = languageSwitcherTargets('python/sdk/README.zh.md')
const canonical = parseTranslationMarkdown(
'[中文](https://github.com/deepseek-ai/deepseek-harness/blob/master/python/sdk/README.zh.md)',
)
const wrongPath = parseTranslationMarkdown(
'[中文](https://github.com/deepseek-ai/deepseek-harness/blob/master/other/README.zh.md)',
)
expect(linksTo(canonical, targets)).toBe(true)
expect(translationStructureSignature(canonical, targets).links).toEqual([])
expect(linksTo(wrongPath, targets)).toBe(false)
})
})
describe('translation pairing records', () => {

View File

@@ -302,11 +302,19 @@ export function parseTranslationMarkdown(content: string): Nodes {
return fromMarkdown(content, { extensions: [gfm()], mdastExtensions: [gfmFromMarkdown()] })
}
/** Whether the tree contains a link to exactly `target`. */
export function linksTo(tree: Nodes, target: string): boolean {
const PUBLIC_REPOSITORY_BLOB_ROOT = 'https://github.com/deepseek-ai/deepseek-harness/blob/master/'
/** Return the accepted relative and public-repository links to one counterpart. */
export function languageSwitcherTargets(counterpart: string): string[] {
return [basename(counterpart), `${PUBLIC_REPOSITORY_BLOB_ROOT}${counterpart}`]
}
/** Whether the tree contains a link to any accepted target. */
export function linksTo(tree: Nodes, targets: string | readonly string[]): boolean {
const accepted = new Set(typeof targets === 'string' ? [targets] : targets)
let found = false
const visit = (node: Nodes): void => {
if (node.type === 'link' && node.url === target) found = true
if (node.type === 'link' && accepted.has(node.url)) found = true
if ('children' in node) for (const child of node.children) visit(child)
}
visit(tree)
@@ -335,8 +343,14 @@ export function requiresSourceLanguageSwitcher(source: string): boolean {
].includes(source)
}
/** Collect the ordered structural signature, skipping one switcher target. */
export function translationStructureSignature(tree: Nodes, switcherTarget: string): TranslationStructureSignature {
/** Collect the ordered structural signature, skipping accepted switcher targets. */
export function translationStructureSignature(
tree: Nodes,
switcherTargets: string | readonly string[],
): TranslationStructureSignature {
const acceptedSwitchers = new Set(
typeof switcherTargets === 'string' ? [switcherTargets] : switcherTargets,
)
const sig: TranslationStructureSignature = { headings: [], code: [], tables: [], lists: [], links: [] }
const visit = (node: Nodes): void => {
switch (node.type) {
@@ -355,7 +369,7 @@ export function translationStructureSignature(tree: Nodes, switcherTarget: strin
: `bullet:items=${node.children.length}`)
break
case 'link':
if (node.url !== switcherTarget) sig.links.push(node.url)
if (!acceptedSwitchers.has(node.url)) sig.links.push(node.url)
break
default:
// Every other node kind is prose or a container, not part of the signature.

View File

@@ -71,6 +71,7 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
'packages/client/ui-layout': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
'packages/client/ui-sidebar': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
'packages/client/ui-conversation': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
'packages/client/ui-feedback': { kind: 'none', reason: 'Browser-side controls over the message-feedback sidecar; ratings and notes never enter the Session log, model context, or telemetry.' },
'packages/client/ui-tool': { kind: 'none', reason: 'Browser-side Tool presentation layer; renders logged calls without changing model context.' },
'packages/client/ui-deliverables': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
'packages/client/ui-task': { kind: 'none', reason: 'Browser-side read-only projection of ctx.tasks records; dsh-tool-tasks owns the model-facing behavior.' },
@@ -91,6 +92,7 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
'packages/client/ui-settings': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
'packages/client/ui-settings-general': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
'packages/client/ui-models': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
'packages/client/ui-plugins': { kind: 'none', reason: 'Browser-side inventory projection; registers nothing model-facing.' },
'packages/client/locale': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
'packages/client/web': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
'packages/examples/agent-spine-demo': { kind: 'indirect', reason: 'The bundle only mounts model-facing child plugins.' },
@@ -105,6 +107,7 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
'packages/host/directory-picker-native': { kind: 'none', reason: 'The GUI-host picking backend registers nothing model-facing.' },
'packages/host/webserver': { kind: 'none', reason: 'The HTTP carrier bridges browser and API handler and registers nothing model-facing.' },
'packages/host/frontend-static': { kind: 'none', reason: 'The SPA dist server answers browser asset requests and registers nothing model-facing.' },
'packages/host/plugin-inventory': { kind: 'none', reason: 'Host-side read-only Loader projection; registers nothing model-facing.' },
'packages/bundle/base': { kind: 'indirect', reason: 'The bundle is a patch-list carrier; each inserted row\'s package owns its model-facing behavior.' },
'packages/bundle/headless': { kind: 'none', reason: 'The one-shot runner submits the task as an ordinary user message; prompts and tools belong to the composed base and headless bundles.' },
'packages/llm/llm': { kind: 'none', reason: 'The adapter registry forwards already-assembled requests unchanged.' },

View File

@@ -19,6 +19,7 @@ import {
translationPairPaths,
} from './translation-pairing-record.ts'
import {
languageSwitcherTargets,
linksTo,
parseTranslationMarkdown,
parseTranslationPairingCliArgs,
@@ -252,15 +253,17 @@ for (const source of [...pairAnchors].sort()) {
const sourceTree = parseTranslationMarkdown(sourceContent.toString('utf8'))
const zhTree = parseTranslationMarkdown(zhContent.toString('utf8'))
if (!linksTo(zhTree, basename(source))) {
const sourceSwitcherTargets = languageSwitcherTargets(source)
const zhSwitcherTargets = languageSwitcherTargets(zh)
if (!linksTo(zhTree, sourceSwitcherTargets)) {
errors.push(`${zh}: missing language switcher — no link to ${basename(source)}`)
}
if (requiresSourceLanguageSwitcher(source) && !linksTo(sourceTree, basename(zh))) {
if (requiresSourceLanguageSwitcher(source) && !linksTo(sourceTree, zhSwitcherTargets)) {
errors.push(`${source}: missing language switcher — no link back to ${basename(zh)}`)
}
for (const divergence of translationStructureDiff(
translationStructureSignature(sourceTree, basename(zh)),
translationStructureSignature(zhTree, basename(source)),
translationStructureSignature(sourceTree, zhSwitcherTargets),
translationStructureSignature(zhTree, sourceSwitcherTargets),
)) {
errors.push(`${source}${zh}: ${divergence}`)
}