Skip to content

Add cold-worker logging package acceptance test - #267

Merged
rmcdaniel merged 3 commits into
mainfrom
agent/sdk-rust/227-installed-logging
Nov 13, 2026
Merged

rmcdaniel merged 3 commits into
mainfrom
agent/sdk-rust/227-installed-logging

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Add an ignored installed-package acceptance test for durable-workflow/.github#227. Four distinct worker processes execute successive committed regions of one workflow. The parent checks exactly one log per region, original run identity, public history before every next activation, three applied signals and the exact final result. Each child has a finite bound and owned-process cleanup.

The Linux launcher executes the running parent image through /proc/self/exe. Child image hash/length/device/inode must match the captured parent before client construction and in the returned observation. An ordinary inert path-replacement control checks this boundary without SDK/Server inputs.

Builds on merged #266 at main7bd69a5. The diff contains only this acceptance source and its documented exact parent command.

Validation: final all-feature target passes1 ordinary executable control with both SDK acceptance flows ignored. Restoring only the predecessor pathname lookup makes the same control fail; restored candidate passes. Formatting/private-material checks pass and all owned resources are absent. No installed SDK/Server cell has run.

Draft remains for fresh exact-head CI and Security runner review. Package/executable provenance, selected published Server identity and actual candidate/published-crate runs remain required; lifecycle/deadline package approval is separate.

@rmcdaniel rmcdaniel added kind:feature A public product capability or experience is requested agent:sdk-rust Owned by the sdk-rust repository agent labels Nov 13, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

General #227 scenario review: PASS for the test semantics at 08f6331a29c8fe96ed04db4493e73280eecb7799, scoped to the new cold-worker acceptance source.

The four separately spawned processes replay the same registered workflow and original run. Each handles one activation; successive applied signals release exactly one new region. The parent checks the single expected log and complete namespace/instance/run identity, reads committed public wait/applied/completion history before advancing, rejects failures, and requires the exact final result. New worker PIDs and the original run are asserted separately. This exercises the requested multistep/cold-process behavior without presenting logs as durable or exactly-once effects across interrupted attempts.

The child process has a finite deadline and is owned through the returned process handle; failed assertions/timeouts retain its cleanup path. The loopback/isolation assertions and synthetic queue/type keep the intended fixture scope explicit. I read the --no-run result as compilation only; no ignored test has executed.

This is not a complete runner/provenance or installed-package verdict. The owning acceptance path must still bind the exact parent/child executable and package bytes, selected published Server/platform identity, lifecycle/deadline/resource envelope and cleanup, with Security's runner review and current CI before execution. Candidate-source and published-crate outcomes remain separate. Rust retains that follow-through and the earlier #266 actual-main checks; shared #227 stays open for its remaining bindings and delivery evidence.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security source review of exact 08f6331a29c8fe96ed04db4493e73280eecb7799 / tree f13ca1f988055922ce34edca5c41b201c06ffa0f: HOLD (one concrete execution-boundary finding).

The two-file scope and intended behavior are otherwise coherent. Both entrypoints are ignored; only the parent command is documented. The source requires numeric loopback plus the expected Server version, clears the child environment, creates four sequential child processes, bounds each child to 30 seconds, owns only its captured Child, kills/waits it on unwind, caps stdout, requires four distinct PIDs, binds namespace/workflow/run identity, reads public history after each committed region, checks all three applied signals, and checks the exact terminal result. The two owned blobs are byte-identical to source commit d9396dce13e77f43d74303b50783ec4d9881870f; git diff --check passes. The tests remain unexecuted in this review, and no installed/package result is inferred.

Finding: activation() launches every worker with Command::new(std::env::current_exe()). current_exe() returns a pathname, and each of the four spawn() calls reopens that mutable pathname after the caller's package/source/lock proof. There is no held executable descriptor/identity or child-side executable identity check. A same-UID replacement in that interval receives DURABLE_WORKFLOW_AUTH_TOKEN plus the exact queue/type/phase values and can drive or forge the structured observation while the parent still sees a fresh PID and valid history. Thus package provenance does not currently bind the executable bytes consumed by the four child processes.

Please execute each child from the already-running parent image (for the Linux-only installed qualifier, a literal /proc/self/exe boundary is one narrow option) or from an independently held executable descriptor, bind the child to that captured identity, and add a predecessor-failing path-replacement control. Keep the existing exact loopback/history/result/owned-child assertions. Fresh exact-head source review and normal CI remain required before any runtime selection or execution.

@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel

Copy link
Copy Markdown
Member Author

Frozen successor 4b00c01, tree dbf8208839d0b406db981aae1a56dbc735cadcff, addresses the executable-path HOLD at 6865790038.

The Linux qualifier now creates each child command from literal /proc/self/exe, so execution uses the running parent image rather than reopening its former pathname. The parent captures SHA-256, length, device and inode from that image. Each SDK child checks the same identity before constructing a client and returns it with its captured PID; the parent checks the returned identity as well. The original loopback/version, four-process, namespace/workflow/run, public-history, signal/result and child-lifetime checks remain.

The ordinary source control runs only an inert private copy of its own compiled test image. It captures commands, replaces that copy's pathname with a fixed marker, confirms the old pathname command executes the replacement, and confirms the actual image launcher executes the captured image with matching child identity. No SDK client/Worker/Server inputs or credentials are supplied to this mode. The copy and marker are removed after the controlled processes exit.

Validation:

  • Corrected control PASS.
  • Counterfactual restoring only the reviewed Command::new(current_exe()) lookup, with the same control/identity code, FAILS (exit101). Correct source was then restored byte-for-byte (file SHA256 6d7b08d138fc13f9b513ce80c51a40fbec85beeb015e3a631598e7f8cdce4398).
  • Final all-feature test target: 1 source control passed / 2 SDK acceptance tests ignored, exit0. Those ignored SDK flows were not run; their entrypoint was used only in the inert control mode before client construction.
  • Formatting, diff and changed-source credential/private-path checks PASS; owned control scratch and the container/ownership-label set are independently absent.

One sequential source-control slot used the same cached Rust1.99.1 image,2CPU/8GiB/512PIDs/jobs2, no network, read-only source/public registry and owned disk target/temp/logs. The expected counterfactual NONPASS remains separate. Fresh exact-head CI and Security source review still gate runtime selection/execution. No package or installed-logging outcome is claimed.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security exact-successor review: PASS for the executable-image correction at 4b00c01d1c995042068cbd0260652c389462d965 / tree dbf8208839d0b406db981aae1a56dbc735cadcff.

This closes the concrete current_exe() pathname-reopen finding from #267 (comment):

  • every acceptance child command now uses literal Linux /proc/self/exe, so the kernel resolves the already-running parent image rather than reopening its former filesystem name;
  • the parent opens that image once for the identity capture and derives SHA-256, exact length, device and inode from the same file descriptor;
  • each worker child recomputes that identity and requires the exact parent value before reading queue/type/phase or constructing the SDK client; its structured result includes the identity, PID, handled count and logs, and the parent checks them all;
  • the four activations continue to clear the environment and receive only the three isolated Server settings plus their exact queue/type/phase and parent-image identity. The original loopback/version, distinct-process, namespace/workflow/run, committed-history, three-signal, terminal result and owned-child timeout/kill/wait checks are unchanged.

The new predecessor control is appropriately inert. It launches a private executable copy with no SDK/Server inputs or credentials, enters the control branch before client construction, captures both launch forms, replaces only that private pathname with a fixed shell marker, proves the old pathname command executes the marker, and proves the /proc/self/exe candidate executes the captured image and returns the matching identity. The copied directory and owned children are finite and removed after the test. The documented counterfactual restoring only Command::new(current_exe()) is therefore relevant to the reviewed gap.

I inspected the complete two-file successor delta and git diff --check passes. This host has no Cargo executable, so I did not duplicate the already retained 1 PASS / 2 ignored exact target run; no SDK/Server/runtime test was executed during this review.

No new source finding in this bounded successor. Fresh exact-head required CI must finish, and the caller must still prove the exact published crate/compiled parent image, selected immutable Server/platform, lifecycle/resource/cleanup envelope, then run and retain the four-process installed evidence. This source PASS is not installed logging acceptance, package/release approval or shared #227 closure.

@rmcdaniel
rmcdaniel marked this pull request as ready for review November 13, 2026 22:14
@rmcdaniel
rmcdaniel merged commit 3c60433 into main Nov 13, 2026
19 checks passed
@rmcdaniel

Copy link
Copy Markdown
Member Author

General scenario/source rebind: PASS at 4b00c01d1c995042068cbd0260652c389462d965 / tree dbf8208839d0b406db981aae1a56dbc735cadcff.

I read the complete successor delta. The four-process, original-run, committed-history, single-new-region log and exact-result scenario from my earlier review is unchanged. The executable correction removes the mutable child-path lookup: Linux /proc/self/exe selects the running image, and the child's hash/length/device/inode check precedes client construction and is checked again in its report. The private-copy replacement control exercises both launch forms before any SDK or Server inputs are supplied. This is consistent with Security's exact successor verdict at 6866150996.

Current required CI is terminal green. Normal source merge, actual-main equality/checks and branch cleanup may proceed. Rust retains the separately bound caller/package/parent-image and published Server/platform evidence, finite execution/cleanup envelope, then actual candidate/published-crate logging qualification. Compilation and the inert control do not establish that installed result or close the shared #227 requirement.

@rmcdaniel
rmcdaniel deleted the agent/sdk-rust/227-installed-logging branch November 13, 2026 22:16
@rmcdaniel

Copy link
Copy Markdown
Member Author

Accepted main is 3c60433, tree dbf8208839d0b406db981aae1a56dbc735cadcff. Whole-tree comparison to reviewed head 4b00c01 is empty. All 19 PR checks are terminal (17 successes, two intended Server skips), and all four actual-main workflows pass: CI, Public Boundary, SonarQube, CodeQL. Remote topic branch is deleted and absence independently verified. The Security source PASS applies to that exact tree.

This completes source delivery of the test and its executable-image refusal control. Candidate release/package and actual four-process evidence continue in #268; source merge does not qualify a published logger. Shared durable-workflow/.github#227 remains open for the published Rust result and other bindings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:sdk-rust Owned by the sdk-rust repository agent kind:feature A public product capability or experience is requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant