Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/scripts/pitot_e2e_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "scripts"))
from pitot_adapter_supervisor import ContractError, validate_manifest
from installation_identity import validate_identity_evidence


MANIFEST = json.loads((ROOT / "adapter-verification.json").read_text(encoding="utf-8"))
Expand Down Expand Up @@ -126,6 +127,7 @@ def validate_result(
"version",
"executable",
"executable_sha256",
"installation",
"installer",
"runtime",
}:
Expand All @@ -137,9 +139,12 @@ def validate_result(
):
raise ValueError("CLI receipt does not match supervised manifest")
if not all(
isinstance(item, str) and item and "\0" not in item for item in cli.values()
isinstance(item, str) and item and "\0" not in item
for key, item in cli.items()
if key != "installation"
):
raise ValueError("invalid CLI receipt values")
validate_identity_evidence(agent, platform, cli["installation"])
cells = [
cell
for cell in ENDPOINT_PROVENANCE["cells"]
Expand All @@ -150,6 +155,8 @@ def validate_result(
if len(cells) != 1:
raise ValueError("missing supervised platform provenance")
fixture = cells[0]
if cli["installation"] != fixture.get("installation"):
raise ValueError("installed-code identity does not match binary capture")
if cli["executable_sha256"] != fixture["executable_sha256"]:
raise ValueError("CLI executable digest does not match binary capture")
if value["protocol"] != fixture["dialect"] or not re.fullmatch(
Expand All @@ -169,6 +176,7 @@ def validate_result(
"request": fixture["request"],
"response": fixture["response"],
"executable_sha256": fixture["executable_sha256"],
"installation": fixture["installation"],
}
if value["endpoint"] != expected_endpoint:
raise ValueError(
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/pitot-e2e-agent.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ jobs:
${{ runner.temp }}/pitot-e2e/deepseek-native-session.zstd
if-no-files-found: error
retention-days: 14
- name: Upload safe installation diagnostic
if: failure()
uses: actions/upload-artifact@v4
with:
name: pitot-install-probe-${{ inputs.agent }}-${{ inputs.platform }}
path: ${{ runner.temp }}/pitot-e2e/install.probe.json
if-no-files-found: ignore
retention-days: 14
- name: Upload endpoint provenance candidate
if: always() && inputs.capture
uses: actions/upload-artifact@v4
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,5 +165,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Verify native installation identity
run: python -m unittest discover -s tests -p test_installation_identity.py
- name: Build and verify installed SDK artifacts
run: python scripts/check_sdk_packages.py
40 changes: 20 additions & 20 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,25 +121,24 @@ name/export errors (E9, F821, F822, F823); formatting remains a separate gate.

## Refreshing agent endpoint provenance

The installer selects its own release location or npm global launcher rather
than rediscovering the agent on PATH. It records the raw version output only
after the complete product banner matches the literal catalog pin and the
entrypoint bytes stay unchanged across the version probe. An unexpected banner
is a verification failure that needs investigation; mentioning the pin is
insufficient.

Before creating runtime or fixture effects, the driver checks the receipt's
schema, selected agent/platform/runtime/installer, owned absolute path, current
file digest and freshly observed version output. It checks the file digest
again immediately before and after the verification session. A failed or
timed-out version probe, malformed receipt or changed file cannot produce a
successful verification result.

These are observations of the entrypoint and its self-reported version on a
trusted runner. They do not authenticate a publisher, freeze the file against
concurrent changes, or cover all programs and package files delegated to by an
npm or Windows launcher. Historical endpoint captures retain their original
scope; this check does not upgrade their identity evidence.
Codex, Qwen and DeepSeek install into fresh, owned npm prefixes. Their receipts
bind the package tree (names, types, bytes and platform metadata), the selected
Node binary and version, and the package's JavaScript entrypoint. Version probes
and verification sessions invoke that absolute Node/JavaScript pair. Qwen's
managed-update pin keeps execution in the recorded package; a seeded external
update proves the selection test can detect an unpinned launch.

The driver validates the receipt before creating session fixtures and rechecks
installation identity around execution. A changed package or Node binary,
malformed receipt, unexpected version banner, or failed probe rejects admission.
Bounded failed-probe streams remain local; public diagnostics contain only
failure reasons, byte counts and digests. Other agents retain entrypoint-only
identity checks.

These are observations on a trusted runner, not publisher authentication or an
atomic filesystem snapshot. POSIX mode bits and Windows readonly attributes are
recorded; Windows ACLs, operating-system libraries and changes between checks
are outside the guarantee. Historical captures retain their original scope.

Protocol documentation is not a verification authority. When a pinned agent
version changes, dispatch the existing **Pitot E2E** workflow with
Expand Down Expand Up @@ -169,7 +168,8 @@ the selected current attempt; a partial rerun cannot borrow earlier cells.
Local JSON files cannot authorize a capture refresh. Acquisition or validation
failure preserves the accepted file; success replaces it atomically.

The schema4 record keeps wire cells and their hash meaning, and adds the
The schema5 record adds portable installation identity to the wire cells and
retains the
`capture-direct/v1` producer profile to the source run, job/check-run IDs and
artifact digests. Its sorted file hashes cover the capture orchestration,
proxies, witness and canary helpers, catalog-declared integrations, agent
Expand Down
5 changes: 5 additions & 0 deletions cmd/pitot/deepseek_acp.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ func runDeepSeekACP(ctx context.Context, args []string, stdout, stderr io.Writer
options.Prompt = value
case "--exec":
options.Executable = value
case "--entrypoint":
if len(options.Arguments) != 0 {
return errors.New("pitot: duplicate DeepSeek entrypoint")
}
options.Arguments = []string{value}
case "--cwd":
options.Cwd = value
case "--model":
Expand Down
43 changes: 43 additions & 0 deletions cmd/pitot/deepseek_acp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

import (
"context"
"io"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
)

func TestDeepSeekExplicitNodeEntrypoint(t *testing.T) {
root := t.TempDir()
name := "node"
if runtime.GOOS == "windows" {
name += ".exe"
}
node := filepath.Join(root, name)
if err := os.WriteFile(node, []byte("owned runtime placeholder"), 0o700); err != nil {
t.Fatal(err)
}
entry := filepath.Join(root, "package with spaces", "工具.js")
program, arguments, err := deepSeekCommand(node, []string{entry})
if err != nil || program != node || len(arguments) != 1 || arguments[0] != entry {
t.Fatalf("command = %q %q, error = %v", program, arguments, err)
}
for _, args := range [][]string{{"relative.js"}, {filepath.Join(root, "entry.txt")}, {entry, "--extra"}} {
if _, _, err := deepSeekCommand(node, args); err == nil {
t.Fatalf("accepted unsupported entrypoint arguments %q", args)
}
}
if _, _, err := deepSeekCommand(filepath.Join(root, "dsh"), []string{entry}); err == nil {
t.Fatal("accepted a JS entrypoint with a non-Node executable")
}
}

func TestDeepSeekRejectsDuplicateEntrypointBeforeLaunch(t *testing.T) {
err := runDeepSeekACP(context.Background(), []string{"--runtime", "r", "--prompt", "p", "--entrypoint", "first.js", "--entrypoint", "second.js"}, io.Discard, io.Discard)
if err == nil || !strings.Contains(err.Error(), "duplicate DeepSeek entrypoint") {
t.Fatalf("duplicate entrypoint error = %v", err)
}
}
2 changes: 1 addition & 1 deletion cmd/pitot/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ usage:
pitot init --host HOST [--force]
pitot dev --host HOST -- AGENT [ARGS...]
pitot acp devin --runtime PATH --prompt TEXT [--exec PATH] [--model MODEL] [--agent-type TYPE] [--cwd PATH]
pitot acp deepseek --runtime PATH --prompt TEXT [--exec PATH] [--cwd PATH] [--model MODEL] [--base-url URL --api-key-env NAME] [--session-dir PATH]
pitot acp deepseek --runtime PATH --prompt TEXT [--exec PATH] [--entrypoint JS_PATH] [--cwd PATH] [--model MODEL] [--base-url URL --api-key-env NAME] [--session-dir PATH]
pitot doctor [--host HOST] [--fix]
pitot run [--config PATH] [--strict] --runtime PATH
pitot hook HOST [--runtime PATH]
Expand Down
22 changes: 16 additions & 6 deletions scripts/pitot_adapter_supervisor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@


ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "tests"))
from installation_identity import validate_identity_evidence

MANIFEST = Path("adapter-verification.json")
ENDPOINT_PROVENANCE = Path("tests/endpoint-provenance.json")
README = Path("README.md")
Expand Down Expand Up @@ -209,14 +212,14 @@ def validate_endpoint_provenance(root: Path, manifest: dict[str, object]) -> Non
raise ContractError(f"cannot load {ENDPOINT_PROVENANCE}: {error}") from error
validate_endpoint_value(value, manifest)
if (
value["schema_version"] in {3, 4}
value["schema_version"] in {3, 4, 5}
and value["source"]["catalog_sha256"]
!= hashlib.sha256((root / MANIFEST).read_bytes()).hexdigest()
):
raise ContractError(
"endpoint capture source catalog digest differs from current manifest"
)
if value["schema_version"] == 4:
if value["schema_version"] in {4, 5}:
from pitot_capture_source import validate_current_producers

try:
Expand All @@ -233,15 +236,15 @@ def validate_endpoint_value(value: object, manifest: dict[str, object]) -> None:
"capture_policy",
"cells",
}
if isinstance(value, dict) and value.get("schema_version") in {3, 4}:
if isinstance(value, dict) and value.get("schema_version") in {3, 4, 5}:
required.add("source")
if not isinstance(value, dict) or set(value) != required:
raise ContractError(
"endpoint provenance must contain schema_version, capture_policy, and cells"
)
if (
type(value["schema_version"]) is not int
or value["schema_version"] not in {2, 3, 4}
or value["schema_version"] not in {2, 3, 4, 5}
or value["capture_policy"] != "pinned_real_cli_capture"
):
raise ContractError("endpoint provenance must require pinned real-CLI capture")
Expand Down Expand Up @@ -274,13 +277,20 @@ def validate_endpoint_value(value: object, manifest: dict[str, object]) -> None:
"provenance",
"capture_sha256",
}
if value["schema_version"] == 5:
required.add("installation")
for cell in cells:
agent_id, platform = cell["agent"], cell["platform"]
if set(cell) != required:
raise ContractError(
f"endpoint fixture {agent_id}/{platform} has an invalid schema"
)
agent = declared[agent_id]
if value["schema_version"] == 5:
try:
validate_identity_evidence(agent_id, platform, cell["installation"])
except ValueError as error:
raise ContractError(str(error)) from error
if (
cell["version"] != agent["version"]
or cell["runtime"] != agent["runtime"][platform]
Expand Down Expand Up @@ -379,15 +389,15 @@ def validate_endpoint_value(value: object, manifest: dict[str, object]) -> None:
raise ContractError(
f"endpoint fixture {agent_id}/{platform} has a fabricated capture digest"
)
if value["schema_version"] in {3, 4}:
if value["schema_version"] in {3, 4, 5}:
from pitot_capture_source import validate_source_index

try:
validate_source_index(
value["source"],
cells,
manifest,
producer_binding=value["schema_version"] == 4,
producer_binding=value["schema_version"] in {4, 5},
)
except (ValueError, KeyError, TypeError) as error:
raise ContractError(f"invalid endpoint capture source: {error}") from error
Expand Down
6 changes: 5 additions & 1 deletion scripts/pitot_capture_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
"tests/e2e_unified_runner.sh",
"tests/install_real_agent.py",
"tests/agent_identity.py",
"tests/installation_identity.py",
"cmd/pitot/deepseek_acp.go",
"internal/deepseekacp/version.go",
"internal/deepseekacp/client.go",
"scripts/pitot_capture_source.py",
"scripts/pitot_adapter_supervisor.py",
".github/scripts/pitot_e2e_report.py",
Expand Down Expand Up @@ -788,7 +792,7 @@ def collect(
"local producer changed during collection",
)
value = {
"schema_version": 4,
"schema_version": 5,
"capture_policy": "pinned_real_cli_capture",
"cells": cells,
"source": {
Expand Down
Loading
Loading