GitHub remote dry-run rule
The initial package exports the GitHub remote orchestration rule in dry-run
mode. Running the free rule here distributes the entire scriptmodule.
$ run-function CommonsBase_Remote.GitHub.F_DryRunPlan@0.2.0 -f ${RUNTIME}/GitHub-0.2.0.plan.txt dry_run=true timestamp=20260527165106 repo=github.com/OWNER/REPO cmd=get-bundle commandvsl='get-bundle MlFront_Std.Sample.Abc@1.0.0' 'argv[]=get-bundle' 'argv[]=MlFront_Std.Sample.Abc@1.0.0'
\test(pass)
\dk.asset(path: "dry-run.txt", value-id: "atrrfkfvw2xzmtpbzzgucakqw4atdt2jtz7hbrgyjpt5hrjy7ioza", byteSize: "794")\;
The remote command (host side)
`dk0 remote UI_MODULE@VERSION [OPTION=VALUE...] [REPOSITORY] INNER_COMMAND...`
is thin sugar in the `dk0` host (`ShellRemote.ml`) over a plain
`dk0 run <rule>` of this orchestration rule. The host does not run the inner
command locally; it only forwards it. Concretely, `remote`:
1. **Resolves the rule.** The `UI_MODULE@VERSION` is expanded to the full rule
id: a bare name like `GitHub@0.1.0` becomes
`CommonsBase_Remote.GitHub.Run@0.1.0` (the `_Remote` library suffix and the
`.Run` rule are added when missing).
2. **Splits arguments.** Leading `OPTION=VALUE` pairs are separated from the
inner command, an optional `REPOSITORY` before a recognized inner command is
detected, and the inner command name is checked against the supported list
(`get-object`, `run-object`, `run-function`, `run-rule`, `enter-object`,
`merge-object`, `get-asset`, `run-asset`, `get-bundle`, `test`, `lua`,
`dialog`, `exec`, `run`).
3. **Computes a requested trace key** for commands that produce
dependency-bearing values (`get-object`, `run-object`, `run-function`,
`run-rule`, `enter-object`, `merge-object`). Bundles and assets have no
dependencies, so they carry no requested trace key.
4. **Builds the rule request parameters** and runs
`dk0 run CommonsBase_Remote.GitHub.Run@... <params>`, where the params are:
- `cmd=<inner command name>` and `commandvsl=<inner command as one quoted
line>` (the human-readable audit line),
- `requested_trace_key_id=...` / `requested_trace_key_description=...` when
applicable,
- the forwarded `OPTION=VALUE` remote options, `repo=<REPOSITORY>`, and
`project_root=<absolute project directory>`,
- **`argv[]=<token>` for every token of the inner command.** The argv is
forwarded verbatim; the runner's `dk0` re-parses it and resolves any
`$(...)`/`${...}` subshells and variables against the **remote** workspace,
never the local one. Local argument expansion is intentionally not applied
to the `remote` path.
So everything below happens inside the `Run` rule, driven by those request
parameters.
GitHub remote execution flow
The GitHub remote rule is designed so the user's project tree is only an input
source. All remote-session git operations happen in the isolated commit
directory `.dk/r/c` with commands such as `git -C .dk/r/c fetch`,
`git -C .dk/r/c add`, and `git -C .dk/r/c push`. The user's project may have a
different git remote, or may not be a git checkout at all.
Consumer validation workflow
When validating GitHub remote behavior from another project, do not point `dk0`
at an unreleased local checkout with an ad hoc include path like
`-I some/source/CommonsBase_Remote/etc/dk/v`. The reviewed workflow is:
1. (Diskuv owns this step) Release `CommonsBase_Remote` from its package repository with the normal
commit, tag, push, and GitHub release flow.
2. In the consumer project, import that released package with:
```text
./dk0 add github-l2 dkpkg/CommonsBase_Remote
- Run the consumer's
dk0 remote ... smoke against the imported release.
That keeps the validation path aligned with how end users consume the GitHub remote package.
The detailed orchestration has three phases:
Bootstrap and local staging
- Ensure the repository exists and has the remote-session branches
dk-session-root and dk-session-<i>. - Ensure the repository has trusted recipient metadata:
DK_SESSION_KEY stays in a GitHub secret.dk_session_recipient and dk_session_recipient_sig stay in GitHub repository variables.- The local orchestrator verifies the recipient signature before encrypting any staged payload.
- Populate the isolated commit directory
.dk/r/c from the user project, including copies of:dk.udk0 and dk0.cmd- optional
etc/dk/{d,i,v}
- Use
.dk/r/c/t/{k,c,d} as the isolated key, cache, and data directories for local dk0 operations in the commit directory. - Commit the signify verify public key into
.dk/r/c so the GitHub runner can verify signed manifests without depending on GitHub variables for that key. - Run local
dk0 update inside .dk/r/c to materialize the workspace inputs needed by the remote command. - If a retry left
.dk/r/c dirty, stash that leftover residue before the branch sync step so git pull --rebase can proceed on a clean tree. - Rebuild
.dk/r/c/.git at the start of each submit attempt: if stale git metadata exists, delete it, then run git -C .dk/r/c init and continue from that freshly initialized repository. This avoids falling back into the outer consumer repository when UI-runtime filesystem probes lag behind the just-created .git directory. Only .dk/r/c may have its git remote or session branches changed by this rule. - Resolve the local
dk0 wrapper by absolute path from the staged snapshot when invoking it from UI submit code, since the rule runtime cwd may differ from the user project root. - When the local submit-side bootstrap needs
CommonsBase_Std.Coreutils, invoke the staged snapshot dk0 wrapper while pointing -I at the live project etc/dk/i directory so imported package metadata stays visible before .dk/r/c/etc/dk/i has been fully materialized. - Resolve host tools (
git, gh) by probing the requested program first, then on Windows falling back to generated wrapper commands that extend PATH with known install directories when direct lookup fails. - Identify local assets whose mirrors are all strictly inside the user project directory (via
request.ui.assets, which rejects any local origin that escapes the project root) and stage their source files for encryption.
Stage release publication
- Pick a free session branch by shuffling session numbers and skipping any session whose GitHub workflow is already running.
- Append the audited command line to the session audit file in
.dk/r/c. - Commit the stage control files in
.dk/r/c, including the audit line, the argument transport, the signed stage manifest, and .github/workflows/dk-session.<i>.yml. - Tag and push
0.1.<TS>-stage. - GitHub Actions creates a prerelease for the stage tag whose description is the audited command line.
- After the stage prerelease exists, the local orchestrator encrypts each local asset's source file for the verified
dk_session_recipient and uploads the ciphertext to that release. A committed manifest (covered by the signed INDEX) maps each encrypted blob to its local source path, and the runner is told to --trust-local-package each owning package.
Exec publication and result retrieval
- Commit the execution payload in
.dk/r/c, including the copied workspace files, the signed INDEX, the committed signify verify public key, and the workflow file. - Tag and push
0.1.<TS>-exec. - GitHub Actions verifies
INDEX.sig and the INDEX checksums with the committed signify public key, then removes that public key (the matching secret is never shipped) so the runner's dk0 generates its own ephemeral build keypair, runs the requested value command or test/lua/run command, and writes a single combined result file dk-session-result.txt (the remote exit code plus delimited stdout/stderr — one always-non-empty file, because GitHub cannot upload zero-byte release assets). It uploads that file to the exec prerelease. - The local orchestrator waits for the exec workflow run matching the pushed commit (
headSha), downloads dk-session-result.txt, prints the remote stdout/stderr, and propagates the remote exit code. - For local-asset commands, GitHub Actions decrypts each staged source with the
DK_SESSION_KEY secret into its project-relative path (per the signed manifest, rejecting absolute or parent-relative paths) before running, so remote get-asset/run-object/get-bundle of local assets resolve their content. Commands needing only the committed workspace (e.g. lua, test) ship no encrypted assets.
Files needed in the project tree
| Path | Why needed |
|---|
dk.u | Lists all the project directories needed remotely |
dk0 / dk0.cmd | Wrappers for local asset creation and remote command execution |
Files placed into the project tree
The current reviewed layout places only the remote-control directory in the user project tree.
| Path | Why it is in the project tree |
|---|
.dk/r/.gitignore | Keeps the remote-control subtree out of the user's main git repository. |
.dk/r/c/ | Isolated commit directory used as the remote-session git repository. Every remote git command is scoped with git -C .dk/r/c .... |
.dk/r/c/.git/ | Git metadata for the isolated commit repository. This is intentionally separate from any repository the user may have at the project root. |
.dk/r/c/.gitignore | Well-defined ignore policy for local-only isolated-repo state: it ignores .local, t/k/build.sec, t/c/, and t/d/ so local secrets, cache, and valuestore data are never staged by the remote-session repo. |
.dk/r/c/dk.u | Copy of the user's workspace file so the remote session can reproduce the selected workspace inputs without reading from the original project tree at execution time. |
.dk/r/c/dk0 | POSIX wrapper copied from the user's project so GitHub Actions can invoke the same public wrapper logic inside the isolated commit repository. |
.dk/r/c/dk0.cmd | Windows wrapper copied from the user's project for parity with the committed remote-session payload. |
.dk/r/c/etc/dk/d/ | Optional copy of distribution metadata required by the selected workspace. |
.dk/r/c/etc/dk/i/ | Optional copy of import metadata required by the selected workspace. |
.dk/r/c/etc/dk/v/ | Optional copy of value metadata required by the selected workspace. |
.dk/r/c/.github/workflows/dk-session.<i>.yml | Required by GitHub Actions. The workflow must live at this exact path inside the isolated commit repository. |
.dk/r/c/t/k/ | Isolated temporary key material used by commit-repo-local staging. |
.dk/r/c/t/c/ | Isolated cache directory for commit-repo-local dk0 update and staging operations. |
.dk/r/c/t/d/ | Isolated data directory that holds the local valuestore used to create the staged a* and b* release assets. |
.dk/r/c/.local/ | Local-only binaries like coreutils |
The user's original dk.u, dk0, dk0.cmd, and optional etc/dk/{d,i,v} remain the source inputs. The copies under .dk/r/c are the remote-session payload.