Skip to content
Closed
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
01e7fa5
Keep uninstall from deleting what its plan does not disclose (#2099)
Lougarou Oct 30, 2026
2957610
Check the KurrentDB socket the local server actually binds (#2153)
Lougarou Oct 30, 2026
87c3c66
Refuse an unseen confirmation in noninteractive memories import (#2124)
Lougarou Oct 30, 2026
08ca104
Finalize short live sessions without dropping their transcript (#2140)
Lougarou Oct 30, 2026
c34a99e
Remove only what kcap can prove it installed (#2007)
Lougarou Oct 30, 2026
07f2611
Refuse daemon operations that would end their own caller (#2150)
Lougarou Oct 30, 2026
0315a41
Tell an unreachable server apart from a rejected sign-in (#2130)
Lougarou Oct 30, 2026
eaaf813
Hand a stopped hosted agent to its recorded session intact (#2107)
Lougarou Oct 30, 2026
49c28c4
Make repeat and unattended imports report what they did (#2121)
Lougarou Oct 30, 2026
800dc4e
Keep the open session and window state across the tray (#2108)
Lougarou Oct 30, 2026
3d601c3
Name desktop inputs and controls for screen readers (#2115)
Lougarou Oct 30, 2026
a78aee4
Keep config-only harnesses off and point no-agent states at Settings …
Lougarou Oct 30, 2026
dd225dc
Fit the setup wizard to the screen and clarify its confirmations (#1718)
Lougarou Oct 30, 2026
8cfa0c6
Open a tool row to see its recorded command and output (#2110)
Lougarou Oct 30, 2026
068ef73
Polish desktop history labels, rail rows and secondary windows (#2118)
Lougarou Oct 30, 2026
baceb31
Tell an unreachable server from a rejected sign-in or removed install…
Lougarou Oct 30, 2026
90b4cc4
List the pages a session published in desktop Artefacts (#2154)
Lougarou Oct 30, 2026
bea4ddc
Polish CLI tables and diagnostic output (#2131)
Lougarou Oct 30, 2026
ba50674
Ask for local-edition usage-data consent before sending anything (#2156)
Lougarou Oct 30, 2026
664f953
Let setup leave projects out of the history import (#2155)
Lougarou Oct 30, 2026
605766f
Prepare Azure Trusted Signing for Windows releases (#1391)
Lougarou Oct 30, 2026
1014714
Merge main into the testbench fixes
Lougarou Oct 30, 2026
1125ed3
Drop the usings the merge with main left unused
Lougarou Oct 30, 2026
e7462ce
Keep the Codex network claim when restoring config.toml fails (#2147)
Lougarou Oct 30, 2026
6ae336d
Refuse a hosted caller before elevating a Windows service install (#2…
Lougarou Oct 30, 2026
cc8323b
Describe recap --full's per-turn headings in the recap skill (#2125)
Lougarou Oct 30, 2026
970b17a
Keep page titles on one row and list agent ls's columns (#2131)
Lougarou Oct 30, 2026
d8bf42a
Replace the shared skills records atomically (#2007)
Lougarou Oct 30, 2026
766a65f
Check the spool a skipped helper-run hook actually used (#2142)
Lougarou Oct 30, 2026
63aea69
Count rail ages in calendar days, as the day groups do (#2118)
Lougarou Oct 30, 2026
af5bc97
Say an ended server session may have been imported (#2118)
Lougarou Oct 30, 2026
4d7afad
Fit the main window into the screen's work area (#2118)
Lougarou Oct 30, 2026
ff6e196
Name the program that holds the local server's port (#2157)
Lougarou Oct 30, 2026
4da9a46
Open Artefacts page rows through one page viewer (#2154)
Lougarou Oct 30, 2026
94814a6
Fit four tests to agent ls's probe, helper session ids and usage consent
Lougarou Oct 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
65 changes: 64 additions & 1 deletion .github/workflows/cli-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ on:
required: true
type: string
sign:
description: Sign the macOS binaries. Needs the Apple secrets.
description: >-
Sign the release binaries: macOS with the Apple secrets, Windows with Azure Trusted Signing
when its repository variables are set (see RELEASING.md).
type: boolean
default: false

Expand Down Expand Up @@ -55,9 +57,13 @@ jobs:
include: ${{ fromJSON(needs.plan.outputs.matrix) }}
runs-on: ${{ matrix.os }}
container: ${{ matrix.container || '' }}
# The federated credential trusts this environment, so only a Windows leg that signs enters it.
# Keep the condition identical to WINDOWS_SIGN below.
environment: ${{ inputs.sign && startsWith(matrix.rid, 'win-') && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && (vars.AZURE_TRUSTED_SIGNING_ACCOUNT || vars.AZURE_TRUSTED_SIGNING_PROFILE) && 'windows-signing' || '' }}
env:
VERSION: ${{ inputs.version }}
EXE: ${{ startsWith(matrix.rid, 'win-') && '.exe' || '' }}
WINDOWS_SIGN: ${{ inputs.sign && startsWith(matrix.rid, 'win-') && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && (vars.AZURE_TRUSTED_SIGNING_ACCOUNT || vars.AZURE_TRUSTED_SIGNING_PROFILE) && 'true' || 'false' }}
defaults:
run:
shell: bash
Expand Down Expand Up @@ -109,6 +115,37 @@ jobs:
src/Capacitor.App/Packaging/daemon.entitlements
publish/daemon/kcap-daemon publish/daemon/libpty_shim.dylib

- name: Check the Trusted Signing configuration
if: env.WINDOWS_SIGN == 'true'
env:
AZURE_TRUSTED_SIGNING_ENDPOINT: ${{ vars.AZURE_TRUSTED_SIGNING_ENDPOINT }}
AZURE_TRUSTED_SIGNING_ACCOUNT: ${{ vars.AZURE_TRUSTED_SIGNING_ACCOUNT }}
AZURE_TRUSTED_SIGNING_PROFILE: ${{ vars.AZURE_TRUSTED_SIGNING_PROFILE }}
AZURE_TRUSTED_SIGNING_CLIENT_ID: ${{ vars.AZURE_TRUSTED_SIGNING_CLIENT_ID }}
AZURE_TRUSTED_SIGNING_TENANT_ID: ${{ vars.AZURE_TRUSTED_SIGNING_TENANT_ID }}
run: bash scripts/trusted-signing-config.sh

- name: Sign in to Azure for Trusted Signing
if: env.WINDOWS_SIGN == 'true'
uses: azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906 # v3.1.0
with: &azure-login
client-id: ${{ vars.AZURE_TRUSTED_SIGNING_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TRUSTED_SIGNING_TENANT_ID }}
allow-no-subscriptions: true

# Before the digest, like the macOS daemon. The action's dependency cache is off so a signing
# job never restores tooling from a cache another run wrote.
- name: Sign the Windows daemon
if: env.WINDOWS_SIGN == 'true'
uses: azure/artifact-signing-action@c7ab2a863ab5f9a846ddb8265964877ef296ee82 # v2.0.0
with:
endpoint: ${{ vars.AZURE_TRUSTED_SIGNING_ENDPOINT }}
signing-account-name: ${{ vars.AZURE_TRUSTED_SIGNING_ACCOUNT }}
certificate-profile-name: ${{ vars.AZURE_TRUSTED_SIGNING_PROFILE }}
files: ${{ github.workspace }}\publish\daemon\kcap-daemon.exe
exclude-environment-credential: true
cache-dependencies: false

- name: Compute daemon digest
id: daemon-digest
run: |
Expand Down Expand Up @@ -144,6 +181,32 @@ jobs:
bash scripts/sign-macos.sh "$APPLE_SIGNING_IDENTITY" "$KEYCHAIN"
src/Capacitor.App/Packaging/cli.entitlements publish/cli/kcap

# A second sign-in: the AOT publishes after the first can outlast the federated token it holds.
- name: Sign in to Azure for Trusted Signing again
if: env.WINDOWS_SIGN == 'true'
uses: azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906 # v3.1.0
with: *azure-login

# e_sqlite3 stays unsigned: the CLI verifies the downloaded native against a pinned SHA-256.
- name: Sign the Windows CLI and service
if: env.WINDOWS_SIGN == 'true'
uses: azure/artifact-signing-action@c7ab2a863ab5f9a846ddb8265964877ef296ee82 # v2.0.0
with:
endpoint: ${{ vars.AZURE_TRUSTED_SIGNING_ENDPOINT }}
signing-account-name: ${{ vars.AZURE_TRUSTED_SIGNING_ACCOUNT }}
certificate-profile-name: ${{ vars.AZURE_TRUSTED_SIGNING_PROFILE }}
files: |
${{ github.workspace }}\publish\cli\kcap.exe
${{ github.workspace }}\publish\service\kcap-service.exe
exclude-environment-credential: true
cache-dependencies: false

- name: Verify the Windows signatures
if: env.WINDOWS_SIGN == 'true'
run: >
bash scripts/verify-windows-signatures.sh
publish/daemon/kcap-daemon.exe publish/cli/kcap.exe publish/service/kcap-service.exe

- name: Smoke the binaries
if: startsWith(matrix.rid, 'osx-')
run: |
Expand Down
59 changes: 44 additions & 15 deletions .github/workflows/desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ on:
type: string
release:
description: >-
Sign and notarize on macOS, Authenticode-sign on Windows when a certificate is configured,
diff against the published feed and refuse a version already in the bucket. Needs the
Apple, Windows and R2 secrets.
Sign and notarize on macOS, sign with Azure Trusted Signing on Windows when its repository
variables are set (see RELEASING.md), diff against the published feed and refuse a version
already in the bucket. Needs the Apple and R2 secrets.
type: boolean
default: false

Expand All @@ -23,12 +23,16 @@ jobs:
name: Build
runs-on: ${{ startsWith(inputs.rid, 'osx-') && 'macos-latest' || startsWith(inputs.rid, 'win-') && 'windows-latest' || 'ubuntu-latest' }}
timeout-minutes: ${{ startsWith(inputs.rid, 'osx-') && 90 || 60 }}
# The federated credential trusts this environment, so only a Windows release that signs enters
# it. Keep the condition identical to WINDOWS_SIGN below.
environment: ${{ inputs.release && startsWith(inputs.rid, 'win-') && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && (vars.AZURE_TRUSTED_SIGNING_ACCOUNT || vars.AZURE_TRUSTED_SIGNING_PROFILE) && 'windows-signing' || '' }}
env:
# vpk is a framework-dependent global tool built for an older runtime than the pinned SDK.
DOTNET_ROLL_FORWARD: Major
VERSION: ${{ inputs.version }}
RID: ${{ inputs.rid }}
EXE: ${{ startsWith(inputs.rid, 'win-') && '.exe' || '' }}
WINDOWS_SIGN: ${{ inputs.release && startsWith(inputs.rid, 'win-') && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && (vars.AZURE_TRUSTED_SIGNING_ACCOUNT || vars.AZURE_TRUSTED_SIGNING_PROFILE) && 'true' || 'false' }}
defaults:
run:
shell: bash
Expand Down Expand Up @@ -133,14 +137,32 @@ jobs:
|| echo "no previous release to diff against"
bash scripts/desktop-baseline.sh releases "$VERSION"

# Windows signs only once a certificate is configured: an unsigned build still installs and
# updates, but SmartScreen warns on the first download.
- name: Check the Trusted Signing configuration
if: env.WINDOWS_SIGN == 'true'
env:
AZURE_TRUSTED_SIGNING_ENDPOINT: ${{ vars.AZURE_TRUSTED_SIGNING_ENDPOINT }}
AZURE_TRUSTED_SIGNING_ACCOUNT: ${{ vars.AZURE_TRUSTED_SIGNING_ACCOUNT }}
AZURE_TRUSTED_SIGNING_PROFILE: ${{ vars.AZURE_TRUSTED_SIGNING_PROFILE }}
AZURE_TRUSTED_SIGNING_CLIENT_ID: ${{ vars.AZURE_TRUSTED_SIGNING_CLIENT_ID }}
AZURE_TRUSTED_SIGNING_TENANT_ID: ${{ vars.AZURE_TRUSTED_SIGNING_TENANT_ID }}
run: bash scripts/trusted-signing-config.sh "$RUNNER_TEMP/trusted-signing.json"

- name: Sign in to Azure for Trusted Signing
if: env.WINDOWS_SIGN == 'true'
uses: azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906 # v3.1.0
with:
client-id: ${{ vars.AZURE_TRUSTED_SIGNING_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TRUSTED_SIGNING_TENANT_ID }}
allow-no-subscriptions: true

# Windows signs only once Trusted Signing is configured: an unsigned build still installs and
# updates, but SmartScreen warns on the first download. vpk skips a file that is already
# signed; the CLI, daemon and service are also excluded by name, because the bundle must carry
# the bytes npm ships and the daemon digest the CLI embeds.
- name: Pack
env:
RELEASE: ${{ inputs.release }}
APPLE_SIGNING_IDENTITY: ${{ startsWith(inputs.rid, 'osx-') && secrets.APPLE_SIGNING_IDENTITY || '' }}
WINDOWS_CERTIFICATE_PFX: ${{ startsWith(inputs.rid, 'win-') && secrets.WINDOWS_CERTIFICATE_PFX || '' }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ startsWith(inputs.rid, 'win-') && secrets.WINDOWS_CERTIFICATE_PASSWORD || '' }}
run: |
set -euo pipefail
case "$RUNNER_OS" in
Expand All @@ -152,17 +174,14 @@ jobs:
args+=(--signAppIdentity "$APPLE_SIGNING_IDENTITY" --signEntitlements src/Capacitor.App/Packaging/app.entitlements
--signDisableDeep --notaryProfile kcap-notary --keychain "$KEYCHAIN")
fi
if [ "$RELEASE" = true ] && [ "$RUNNER_OS" = Windows ]; then
if [ -n "${WINDOWS_CERTIFICATE_PFX:-}" ]; then
printf '%s' "$WINDOWS_CERTIFICATE_PFX" | base64 -d > "$RUNNER_TEMP/kcap-sign.pfx"
args+=(--signParams "/fd sha256 /td sha256 /tr http://timestamp.digicert.com /f \"$RUNNER_TEMP/kcap-sign.pfx\" /p \"$WINDOWS_CERTIFICATE_PASSWORD\"")
else
echo "::warning::WINDOWS_CERTIFICATE_PFX is not configured; the Windows app ships unsigned"
fi
if [ "$WINDOWS_SIGN" = true ]; then
args+=(--azureTrustedSignFile "$(cygpath -w "$RUNNER_TEMP/trusted-signing.json")"
--signExclude '(^|[\\/])(kcap|kcap-daemon|kcap-service)\.exe$')
elif [ "$RELEASE" = true ] && [ "$RUNNER_OS" = Windows ]; then
echo "::warning::Azure Trusted Signing is not configured; the Windows app ships unsigned"
fi
vpk pack --packId kcap --packVersion "$VERSION" --packTitle "kcap" --packAuthors Kurrent \
--channel "$RID" --outputDir releases "${args[@]}"
rm -f "$RUNNER_TEMP/kcap-sign.pfx"

- name: Assert and smoke the packed bundle
if: runner.os == 'macOS'
Expand Down Expand Up @@ -214,6 +233,16 @@ jobs:
"$install/current/kcap-daemon.exe" --version
"$install/current/kcap-service.exe" --version

- name: Verify the Windows signatures
if: env.WINDOWS_SIGN == 'true'
run: |
set -euo pipefail
install="$(cygpath -u "$LOCALAPPDATA")/kcap"
bash scripts/verify-windows-signatures.sh releases/kcap-win-x64-Setup.exe "$install"/*.exe "$install"/current/*.exe
for f in kcap.exe kcap-daemon.exe kcap-service.exe; do
cmp -s "trio/bin/$f" "$install/current/$f" || { echo "::error::pack changed $f after the CLI build signed it"; exit 1; }
done

# A missing native library or a platform-only call on the startup path ends the process
# within seconds.
- name: Smoke the installed app
Expand Down
6 changes: 4 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ running notes file that every PR edits.
- **Server-origin launch and stop share one serial lane**, sequenced and un-sequenced alike, so
arrival order survives. One lock guards handler admission and the processor's single null→live
transition: there is no second command domain, ever.
- **Codex MCP setup owns only what it created.** Entries it added are tracked in
`mcp-ownership-v1.json`, and uninstall preserves anything it cannot prove it wrote.
- **Codex MCP setup owns only what it created.** Entries it added, and the sandbox network keys it
set with the values they replaced, are tracked in `mcp-ownership-v1.json`; uninstall undoes only
what it can prove it wrote and still holds kcap's value, and says why it keeps the rest. An empty ledger
proves nothing, so it never justifies deleting config.
- **Desktop-app daemon mutations go through one app-lifetime lane** with one shared evidence
predicate: classifying a failure as success is the cardinal sin.
- **Auth commits in one ordered boundary** — claims, then config and provider stamp, then tokens —
Expand Down
Loading
Loading