@kya-os/cli 1.7.0 → 1.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/agent.d.ts +35 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +321 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/build.js +2 -2
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.js +3 -3
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/checkpoint-init.d.ts +32 -0
- package/dist/commands/checkpoint-init.d.ts.map +1 -0
- package/dist/commands/checkpoint-init.js +521 -0
- package/dist/commands/checkpoint-init.js.map +1 -0
- package/dist/commands/claim.js +2 -2
- package/dist/commands/claim.js.map +1 -1
- package/dist/commands/dco.d.ts +59 -0
- package/dist/commands/dco.d.ts.map +1 -1
- package/dist/commands/dco.js +280 -5
- package/dist/commands/dco.js.map +1 -1
- package/dist/commands/dev.js +1 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +18 -24
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/env.js +6 -6
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/identity.js +3 -3
- package/dist/commands/identity.js.map +1 -1
- package/dist/commands/init-stages.d.ts +141 -0
- package/dist/commands/init-stages.d.ts.map +1 -0
- package/dist/commands/init-stages.js +684 -0
- package/dist/commands/init-stages.js.map +1 -0
- package/dist/commands/init.d.ts +46 -16
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +229 -279
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/orchestrator.d.ts +18 -0
- package/dist/commands/orchestrator.d.ts.map +1 -0
- package/dist/commands/orchestrator.js +251 -0
- package/dist/commands/orchestrator.js.map +1 -0
- package/dist/commands/register.d.ts +1 -1
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +35 -7
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/review.d.ts +48 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +220 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/rotate.js +4 -4
- package/dist/commands/rotate.js.map +1 -1
- package/dist/commands/score.d.ts +15 -0
- package/dist/commands/score.d.ts.map +1 -0
- package/dist/commands/score.js +471 -0
- package/dist/commands/score.js.map +1 -0
- package/dist/commands/start.js +3 -3
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/verify.js +6 -6
- package/dist/commands/verify.js.map +1 -1
- package/dist/dco.d.ts +4 -0
- package/dist/dco.d.ts.map +1 -0
- package/dist/dco.js +23 -0
- package/dist/dco.js.map +1 -0
- package/dist/index.js +62 -11
- package/dist/orchestrator/daemon.d.ts +137 -0
- package/dist/orchestrator/daemon.d.ts.map +1 -0
- package/dist/orchestrator/daemon.js +242 -0
- package/dist/orchestrator/daemon.js.map +1 -0
- package/dist/orchestrator/db/dispatches.d.ts +108 -0
- package/dist/orchestrator/db/dispatches.d.ts.map +1 -0
- package/dist/orchestrator/db/dispatches.js +122 -0
- package/dist/orchestrator/db/dispatches.js.map +1 -0
- package/dist/orchestrator/db/index.d.ts +50 -0
- package/dist/orchestrator/db/index.d.ts.map +1 -0
- package/dist/orchestrator/db/index.js +116 -0
- package/dist/orchestrator/db/index.js.map +1 -0
- package/dist/orchestrator/db/journal.d.ts +93 -0
- package/dist/orchestrator/db/journal.d.ts.map +1 -0
- package/dist/orchestrator/db/journal.js +91 -0
- package/dist/orchestrator/db/journal.js.map +1 -0
- package/dist/orchestrator/db/liveness.d.ts +97 -0
- package/dist/orchestrator/db/liveness.d.ts.map +1 -0
- package/dist/orchestrator/db/liveness.js +105 -0
- package/dist/orchestrator/db/liveness.js.map +1 -0
- package/dist/orchestrator/db/mission.d.ts +78 -0
- package/dist/orchestrator/db/mission.d.ts.map +1 -0
- package/dist/orchestrator/db/mission.js +99 -0
- package/dist/orchestrator/db/mission.js.map +1 -0
- package/dist/orchestrator/db/schema.d.ts +14 -0
- package/dist/orchestrator/db/schema.d.ts.map +1 -0
- package/dist/orchestrator/db/schema.js +169 -0
- package/dist/orchestrator/db/schema.js.map +1 -0
- package/dist/orchestrator/db/tickets.d.ts +147 -0
- package/dist/orchestrator/db/tickets.d.ts.map +1 -0
- package/dist/orchestrator/db/tickets.js +238 -0
- package/dist/orchestrator/db/tickets.js.map +1 -0
- package/dist/orchestrator/db/verdicts.d.ts +187 -0
- package/dist/orchestrator/db/verdicts.d.ts.map +1 -0
- package/dist/orchestrator/db/verdicts.js +197 -0
- package/dist/orchestrator/db/verdicts.js.map +1 -0
- package/dist/orchestrator/events.d.ts +69 -0
- package/dist/orchestrator/events.d.ts.map +1 -0
- package/dist/orchestrator/events.js +20 -0
- package/dist/orchestrator/events.js.map +1 -0
- package/dist/orchestrator/github-credential-anchor-sender.d.ts +159 -0
- package/dist/orchestrator/github-credential-anchor-sender.d.ts.map +1 -0
- package/dist/orchestrator/github-credential-anchor-sender.js +313 -0
- package/dist/orchestrator/github-credential-anchor-sender.js.map +1 -0
- package/dist/orchestrator/hub-dispatch.d.ts +120 -0
- package/dist/orchestrator/hub-dispatch.d.ts.map +1 -0
- package/dist/orchestrator/hub-dispatch.js +257 -0
- package/dist/orchestrator/hub-dispatch.js.map +1 -0
- package/dist/orchestrator/hub-observer.d.ts +201 -0
- package/dist/orchestrator/hub-observer.d.ts.map +1 -0
- package/dist/orchestrator/hub-observer.js +474 -0
- package/dist/orchestrator/hub-observer.js.map +1 -0
- package/dist/orchestrator/journal-writer.d.ts +80 -0
- package/dist/orchestrator/journal-writer.d.ts.map +1 -0
- package/dist/orchestrator/journal-writer.js +113 -0
- package/dist/orchestrator/journal-writer.js.map +1 -0
- package/dist/orchestrator/mcp/server.d.ts +136 -0
- package/dist/orchestrator/mcp/server.d.ts.map +1 -0
- package/dist/orchestrator/mcp/server.js +582 -0
- package/dist/orchestrator/mcp/server.js.map +1 -0
- package/dist/orchestrator/mcp/stdio.d.ts +22 -0
- package/dist/orchestrator/mcp/stdio.d.ts.map +1 -0
- package/dist/orchestrator/mcp/stdio.js +51 -0
- package/dist/orchestrator/mcp/stdio.js.map +1 -0
- package/dist/orchestrator/review.d.ts +131 -0
- package/dist/orchestrator/review.d.ts.map +1 -0
- package/dist/orchestrator/review.js +322 -0
- package/dist/orchestrator/review.js.map +1 -0
- package/dist/tui/app.d.ts +33 -0
- package/dist/tui/app.d.ts.map +1 -0
- package/dist/tui/app.js +71 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/components.d.ts +110 -0
- package/dist/tui/components.d.ts.map +1 -0
- package/dist/tui/components.js +118 -0
- package/dist/tui/components.js.map +1 -0
- package/dist/tui/index.d.ts +30 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +95 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/keymap.d.ts +33 -0
- package/dist/tui/keymap.d.ts.map +1 -0
- package/dist/tui/keymap.js +49 -0
- package/dist/tui/keymap.js.map +1 -0
- package/dist/tui/nav.d.ts +29 -0
- package/dist/tui/nav.d.ts.map +1 -0
- package/dist/tui/nav.js +39 -0
- package/dist/tui/nav.js.map +1 -0
- package/dist/tui/sanitize.d.ts +25 -0
- package/dist/tui/sanitize.d.ts.map +1 -0
- package/dist/tui/sanitize.js +36 -0
- package/dist/tui/sanitize.js.map +1 -0
- package/dist/tui/theme.d.ts +32 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +63 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/views/agents.d.ts +67 -0
- package/dist/tui/views/agents.d.ts.map +1 -0
- package/dist/tui/views/agents.js +231 -0
- package/dist/tui/views/agents.js.map +1 -0
- package/dist/tui/views/index.d.ts +93 -0
- package/dist/tui/views/index.d.ts.map +1 -0
- package/dist/tui/views/index.js +150 -0
- package/dist/tui/views/index.js.map +1 -0
- package/dist/tui/views/registry.d.ts +22 -0
- package/dist/tui/views/registry.d.ts.map +1 -0
- package/dist/tui/views/registry.js +110 -0
- package/dist/tui/views/registry.js.map +1 -0
- package/dist/utils/agent/backoff.d.ts +31 -0
- package/dist/utils/agent/backoff.d.ts.map +1 -0
- package/dist/utils/agent/backoff.js +51 -0
- package/dist/utils/agent/backoff.js.map +1 -0
- package/dist/utils/agent/markers.d.ts +87 -0
- package/dist/utils/agent/markers.d.ts.map +1 -0
- package/dist/utils/agent/markers.js +147 -0
- package/dist/utils/agent/markers.js.map +1 -0
- package/dist/utils/agent/review.d.ts +67 -0
- package/dist/utils/agent/review.d.ts.map +1 -0
- package/dist/utils/agent/review.js +305 -0
- package/dist/utils/agent/review.js.map +1 -0
- package/dist/utils/agent/spawn-agent.d.ts +117 -0
- package/dist/utils/agent/spawn-agent.d.ts.map +1 -0
- package/dist/utils/agent/spawn-agent.js +177 -0
- package/dist/utils/agent/spawn-agent.js.map +1 -0
- package/dist/utils/agent/task.d.ts +101 -0
- package/dist/utils/agent/task.d.ts.map +1 -0
- package/dist/utils/agent/task.js +357 -0
- package/dist/utils/agent/task.js.map +1 -0
- package/dist/utils/agent/verify.d.ts +47 -0
- package/dist/utils/agent/verify.d.ts.map +1 -0
- package/dist/utils/agent/verify.js +144 -0
- package/dist/utils/agent/verify.js.map +1 -0
- package/dist/utils/agent-detector.d.ts +48 -0
- package/dist/utils/agent-detector.d.ts.map +1 -0
- package/dist/utils/agent-detector.js +74 -0
- package/dist/utils/agent-detector.js.map +1 -0
- package/dist/utils/agent-profile-stage.d.ts +70 -0
- package/dist/utils/agent-profile-stage.d.ts.map +1 -0
- package/dist/utils/agent-profile-stage.js +153 -0
- package/dist/utils/agent-profile-stage.js.map +1 -0
- package/dist/utils/agent-profiles.d.ts +27 -0
- package/dist/utils/agent-profiles.d.ts.map +1 -0
- package/dist/utils/agent-profiles.js +61 -0
- package/dist/utils/agent-profiles.js.map +1 -0
- package/dist/utils/checkpoint-api.d.ts +86 -0
- package/dist/utils/checkpoint-api.d.ts.map +1 -0
- package/dist/utils/checkpoint-api.js +196 -0
- package/dist/utils/checkpoint-api.js.map +1 -0
- package/dist/utils/checkpoint-env.d.ts +23 -0
- package/dist/utils/checkpoint-env.d.ts.map +1 -0
- package/dist/utils/checkpoint-env.js +59 -0
- package/dist/utils/checkpoint-env.js.map +1 -0
- package/dist/utils/checkpoint-scaffold.d.ts +61 -0
- package/dist/utils/checkpoint-scaffold.d.ts.map +1 -0
- package/dist/utils/checkpoint-scaffold.js +268 -0
- package/dist/utils/checkpoint-scaffold.js.map +1 -0
- package/dist/utils/cli-kit/browser.d.ts +24 -0
- package/dist/utils/cli-kit/browser.d.ts.map +1 -0
- package/dist/utils/cli-kit/browser.js +58 -0
- package/dist/utils/cli-kit/browser.js.map +1 -0
- package/dist/utils/cli-kit/claim-polling.d.ts +18 -0
- package/dist/utils/cli-kit/claim-polling.d.ts.map +1 -0
- package/dist/utils/{claim-polling.js → cli-kit/claim-polling.js} +19 -26
- package/dist/utils/cli-kit/claim-polling.js.map +1 -0
- package/dist/utils/cli-kit/diagnostics.d.ts +9 -0
- package/dist/utils/cli-kit/diagnostics.d.ts.map +1 -0
- package/dist/utils/cli-kit/diagnostics.js +11 -0
- package/dist/utils/cli-kit/diagnostics.js.map +1 -0
- package/dist/utils/cli-kit/fs-safe.d.ts +14 -0
- package/dist/utils/cli-kit/fs-safe.d.ts.map +1 -0
- package/dist/utils/cli-kit/fs-safe.js +20 -0
- package/dist/utils/cli-kit/fs-safe.js.map +1 -0
- package/dist/utils/cli-kit/index.d.ts +15 -0
- package/dist/utils/cli-kit/index.d.ts.map +1 -0
- package/dist/utils/cli-kit/index.js +10 -0
- package/dist/utils/cli-kit/index.js.map +1 -0
- package/dist/utils/cli-kit/json-file.d.ts +21 -0
- package/dist/utils/cli-kit/json-file.d.ts.map +1 -0
- package/dist/utils/cli-kit/json-file.js +51 -0
- package/dist/utils/cli-kit/json-file.js.map +1 -0
- package/dist/utils/cli-kit/marker-block.d.ts +26 -0
- package/dist/utils/cli-kit/marker-block.d.ts.map +1 -0
- package/dist/utils/cli-kit/marker-block.js +61 -0
- package/dist/utils/cli-kit/marker-block.js.map +1 -0
- package/dist/utils/cli-kit/paths.d.ts +15 -0
- package/dist/utils/cli-kit/paths.d.ts.map +1 -0
- package/dist/utils/cli-kit/paths.js +21 -0
- package/dist/utils/cli-kit/paths.js.map +1 -0
- package/dist/utils/cli-kit/secure-storage.d.ts +14 -0
- package/dist/utils/cli-kit/secure-storage.d.ts.map +1 -0
- package/dist/utils/cli-kit/secure-storage.js +20 -0
- package/dist/utils/cli-kit/secure-storage.js.map +1 -0
- package/dist/utils/cli-kit/step-report.d.ts +16 -0
- package/dist/utils/cli-kit/step-report.d.ts.map +1 -0
- package/dist/utils/cli-kit/step-report.js +36 -0
- package/dist/utils/cli-kit/step-report.js.map +1 -0
- package/dist/utils/dco/agent-metadata.d.ts +1 -1
- package/dist/utils/dco/agent-metadata.js +1 -1
- package/dist/utils/dco/agent-metadata.js.map +1 -1
- package/dist/utils/dco/claude-config.d.ts +18 -8
- package/dist/utils/dco/claude-config.d.ts.map +1 -1
- package/dist/utils/dco/claude-config.js +33 -79
- package/dist/utils/dco/claude-config.js.map +1 -1
- package/dist/utils/dco/dispatch.d.ts +134 -0
- package/dist/utils/dco/dispatch.d.ts.map +1 -0
- package/dist/utils/dco/dispatch.js +399 -0
- package/dist/utils/dco/dispatch.js.map +1 -0
- package/dist/utils/dco/fix.d.ts +122 -0
- package/dist/utils/dco/fix.d.ts.map +1 -0
- package/dist/utils/dco/fix.js +560 -0
- package/dist/utils/dco/fix.js.map +1 -0
- package/dist/utils/dco/git-config.d.ts.map +1 -1
- package/dist/utils/dco/git-config.js +5 -3
- package/dist/utils/dco/git-config.js.map +1 -1
- package/dist/utils/dco/github.d.ts +101 -0
- package/dist/utils/dco/github.d.ts.map +1 -1
- package/dist/utils/dco/github.js +133 -0
- package/dist/utils/dco/github.js.map +1 -1
- package/dist/utils/dco/paths.d.ts +1 -8
- package/dist/utils/dco/paths.d.ts.map +1 -1
- package/dist/utils/dco/paths.js +3 -12
- package/dist/utils/dco/paths.js.map +1 -1
- package/dist/utils/dco/render.d.ts +1 -1
- package/dist/utils/dco/render.d.ts.map +1 -1
- package/dist/utils/dco/render.js +4 -21
- package/dist/utils/dco/render.js.map +1 -1
- package/dist/utils/dco/resolve-agent.d.ts +54 -0
- package/dist/utils/dco/resolve-agent.d.ts.map +1 -0
- package/dist/utils/dco/resolve-agent.js +164 -0
- package/dist/utils/dco/resolve-agent.js.map +1 -0
- package/dist/utils/dco/setup.d.ts +10 -7
- package/dist/utils/dco/setup.d.ts.map +1 -1
- package/dist/utils/dco/setup.js +264 -199
- package/dist/utils/dco/setup.js.map +1 -1
- package/dist/utils/dco/signing-key-writer.d.ts +40 -0
- package/dist/utils/dco/signing-key-writer.d.ts.map +1 -0
- package/dist/utils/dco/signing-key-writer.js +76 -0
- package/dist/utils/dco/signing-key-writer.js.map +1 -0
- package/dist/utils/dco/ssh-key.d.ts +50 -0
- package/dist/utils/dco/ssh-key.d.ts.map +1 -1
- package/dist/utils/dco/ssh-key.js +129 -8
- package/dist/utils/dco/ssh-key.js.map +1 -1
- package/dist/utils/dco/status.d.ts +1 -1
- package/dist/utils/dco/status.d.ts.map +1 -1
- package/dist/utils/dco/status.js +3 -3
- package/dist/utils/dco/status.js.map +1 -1
- package/dist/utils/dco/verify.d.ts +170 -0
- package/dist/utils/dco/verify.d.ts.map +1 -0
- package/dist/utils/dco/verify.js +550 -0
- package/dist/utils/dco/verify.js.map +1 -0
- package/dist/utils/dependency-installer.d.ts +37 -0
- package/dist/utils/dependency-installer.d.ts.map +1 -0
- package/dist/utils/dependency-installer.js +32 -0
- package/dist/utils/dependency-installer.js.map +1 -0
- package/dist/utils/github-credential-stage.d.ts +87 -0
- package/dist/utils/github-credential-stage.d.ts.map +1 -0
- package/dist/utils/github-credential-stage.js +168 -0
- package/dist/utils/github-credential-stage.js.map +1 -0
- package/dist/utils/github-credential.d.ts +160 -0
- package/dist/utils/github-credential.d.ts.map +1 -0
- package/dist/utils/github-credential.js +308 -0
- package/dist/utils/github-credential.js.map +1 -0
- package/dist/utils/gitignore.d.ts +17 -0
- package/dist/utils/gitignore.d.ts.map +1 -0
- package/dist/utils/gitignore.js +40 -0
- package/dist/utils/gitignore.js.map +1 -0
- package/dist/utils/hub-config.d.ts +21 -0
- package/dist/utils/hub-config.d.ts.map +1 -0
- package/dist/utils/hub-config.js +28 -0
- package/dist/utils/hub-config.js.map +1 -0
- package/dist/utils/identity-heal.d.ts +16 -0
- package/dist/utils/identity-heal.d.ts.map +1 -0
- package/dist/utils/identity-heal.js +37 -0
- package/dist/utils/identity-heal.js.map +1 -0
- package/dist/utils/init/pipeline.d.ts +74 -0
- package/dist/utils/init/pipeline.d.ts.map +1 -0
- package/dist/utils/init/pipeline.js +96 -0
- package/dist/utils/init/pipeline.js.map +1 -0
- package/dist/utils/poll.d.ts +64 -0
- package/dist/utils/poll.d.ts.map +1 -0
- package/dist/utils/poll.js +76 -0
- package/dist/utils/poll.js.map +1 -0
- package/dist/utils/register-agent-identity.d.ts +67 -0
- package/dist/utils/register-agent-identity.d.ts.map +1 -0
- package/dist/utils/register-agent-identity.js +34 -0
- package/dist/utils/register-agent-identity.js.map +1 -0
- package/dist/utils/review/did-web-key.d.ts +34 -0
- package/dist/utils/review/did-web-key.d.ts.map +1 -0
- package/dist/utils/review/did-web-key.js +104 -0
- package/dist/utils/review/did-web-key.js.map +1 -0
- package/dist/utils/review/load-registry.d.ts +33 -0
- package/dist/utils/review/load-registry.d.ts.map +1 -0
- package/dist/utils/review/load-registry.js +62 -0
- package/dist/utils/review/load-registry.js.map +1 -0
- package/dist/utils/review/verdict-verify.d.ts +43 -0
- package/dist/utils/review/verdict-verify.d.ts.map +1 -0
- package/dist/utils/review/verdict-verify.js +53 -0
- package/dist/utils/review/verdict-verify.js.map +1 -0
- package/dist/utils/review-registry-writer.d.ts +52 -0
- package/dist/utils/review-registry-writer.d.ts.map +1 -0
- package/dist/utils/review-registry-writer.js +79 -0
- package/dist/utils/review-registry-writer.js.map +1 -0
- package/dist/utils/should-install-dependency.d.ts +17 -0
- package/dist/utils/should-install-dependency.d.ts.map +1 -0
- package/dist/utils/should-install-dependency.js +25 -0
- package/dist/utils/should-install-dependency.js.map +1 -0
- package/dist/utils/tool-readiness.d.ts +57 -0
- package/dist/utils/tool-readiness.d.ts.map +1 -0
- package/dist/utils/tool-readiness.js +114 -0
- package/dist/utils/tool-readiness.js.map +1 -0
- package/dist/utils/which.d.ts +2 -0
- package/dist/utils/which.d.ts.map +1 -0
- package/dist/utils/which.js +22 -0
- package/dist/utils/which.js.map +1 -0
- package/dist/version.d.ts +15 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +29 -0
- package/dist/version.js.map +1 -0
- package/package.json +19 -6
- package/dist/utils/claim-polling.d.ts +0 -21
- package/dist/utils/claim-polling.d.ts.map +0 -1
- package/dist/utils/claim-polling.js.map +0 -1
- package/dist/utils/dco/fs-safe.d.ts +0 -14
- package/dist/utils/dco/fs-safe.d.ts.map +0 -1
- package/dist/utils/dco/fs-safe.js +0 -20
- package/dist/utils/dco/fs-safe.js.map +0 -1
|
@@ -1,11 +1,6 @@
|
|
|
1
|
+
import { type StepResult, type StepStatus } from "../cli-kit/index.js";
|
|
1
2
|
import { type GitIdentity } from "./git-config.js";
|
|
2
|
-
export type StepStatus
|
|
3
|
-
export interface StepResult {
|
|
4
|
-
id: string;
|
|
5
|
-
title: string;
|
|
6
|
-
status: StepStatus;
|
|
7
|
-
detail?: string;
|
|
8
|
-
}
|
|
3
|
+
export type { StepStatus, StepResult };
|
|
9
4
|
export interface DcoAgentInfo {
|
|
10
5
|
did: string;
|
|
11
6
|
name: string;
|
|
@@ -25,6 +20,14 @@ export interface DcoSetupOptions {
|
|
|
25
20
|
force?: boolean;
|
|
26
21
|
/** Allow interactive prompts (agent name fallback, scope refresh). */
|
|
27
22
|
interactive?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Wire signing for this EXISTING registered agent instead of resolving
|
|
25
|
+
* identity from this checkout's `.mcpi/`. Skips the identity.json preflight
|
|
26
|
+
* entirely and requires the key to already exist at `signingKeyPath(agent)`
|
|
27
|
+
* (never generated or converted in this mode). See `dco dispatch <slug>`,
|
|
28
|
+
* which derives the same did:web/url/email from the slug.
|
|
29
|
+
*/
|
|
30
|
+
agent?: string;
|
|
28
31
|
}
|
|
29
32
|
export interface DcoSetupResult {
|
|
30
33
|
ok: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/utils/dco/setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/utils/dco/setup.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAOvE,OAAO,EAML,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;AAoBzB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;AAEvC,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gEAAgE;IAChE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAkKD;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC,CAsqBzB"}
|
package/dist/utils/dco/setup.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFile } from "child_process";
|
|
2
|
-
import {
|
|
2
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
3
3
|
import { tmpdir } from "os";
|
|
4
4
|
import { join } from "path";
|
|
5
5
|
import { promisify } from "util";
|
|
@@ -7,8 +7,9 @@ import { readAgentMetadata, writeAgentMetadata } from "./agent-metadata.js";
|
|
|
7
7
|
import { buildAttributionBlock, updateClaudeSettings, upsertClaudeMdBlock, } from "./claude-config.js";
|
|
8
8
|
import { detectSigningConflicts, getGitConfigValue, installTrailerHook, isGitRepo, setGitConfig, } from "./git-config.js";
|
|
9
9
|
import { GhNotInstalledError, GhScopeError, getGhUser, githubNoreplyEmail, isGhAuthenticated, isGhInstalled, listSigningKeys, refreshAuthScope, signingKeyAlreadyUploaded, uploadSigningKey, SCOPE_REFRESH_COMMAND, } from "./github.js";
|
|
10
|
-
import { isValidSlug,
|
|
11
|
-
import {
|
|
10
|
+
import { isValidSlug, signingKeyPath } from "./paths.js";
|
|
11
|
+
import { writeAgentSigningKey } from "./signing-key-writer.js";
|
|
12
|
+
import { sshFingerprintFromPublicKeyLine } from "./ssh-key.js";
|
|
12
13
|
const execFileAsync = promisify(execFile);
|
|
13
14
|
function slugify(value) {
|
|
14
15
|
return value
|
|
@@ -23,11 +24,14 @@ function slugify(value) {
|
|
|
23
24
|
*/
|
|
24
25
|
function sanitizeIdentityValue(value) {
|
|
25
26
|
// eslint-disable-next-line no-control-regex
|
|
26
|
-
return value
|
|
27
|
+
return value
|
|
28
|
+
.replace(/[\u0000-\u001f\u007f]+/g, " ")
|
|
29
|
+
.replace(/\s+/g, " ")
|
|
30
|
+
.trim();
|
|
27
31
|
}
|
|
28
32
|
/**
|
|
29
33
|
* Distinguishes a missing identity from a present-but-unparseable one. The
|
|
30
|
-
* two need different advice: "run
|
|
34
|
+
* two need different advice: "run kya-os register" after a corrupt read would
|
|
31
35
|
* overwrite a potentially recoverable key with a brand new identity.
|
|
32
36
|
*/
|
|
33
37
|
function readIdentityFile(cwd) {
|
|
@@ -110,6 +114,35 @@ async function promptForAgentName() {
|
|
|
110
114
|
]);
|
|
111
115
|
return { name: name.trim(), slug };
|
|
112
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Resolve the human committer's name/email: prefer git config, and only fall
|
|
119
|
+
* back to the authenticated GitHub profile for whichever field git is
|
|
120
|
+
* missing (never both at once, so a configured name survives a missing
|
|
121
|
+
* email or vice versa). Shared by both identity-resolution paths in
|
|
122
|
+
* `runDcoSetup`: this half of Step 2 is identical whether the agent side
|
|
123
|
+
* came from `.mcpi/` or from an explicit agent slug.
|
|
124
|
+
*/
|
|
125
|
+
async function resolveHumanIdentity(cwd) {
|
|
126
|
+
const gitName = await getGitConfigValue("user.name", cwd);
|
|
127
|
+
const gitEmail = await getGitConfigValue("user.email", cwd);
|
|
128
|
+
let ghUser = null;
|
|
129
|
+
if ((!gitName || !gitEmail) &&
|
|
130
|
+
(await isGhInstalled()) &&
|
|
131
|
+
(await isGhAuthenticated())) {
|
|
132
|
+
ghUser = await getGhUser();
|
|
133
|
+
}
|
|
134
|
+
// Use || (not ??) so an explicitly-empty git value is treated as missing,
|
|
135
|
+
// consistent with the truthiness gate above that decides to fetch gh.
|
|
136
|
+
const resolvedName = gitName || (ghUser ? ghUser.name || ghUser.login : undefined);
|
|
137
|
+
const resolvedEmail = gitEmail || (ghUser ? githubNoreplyEmail(ghUser) : undefined);
|
|
138
|
+
if (!resolvedName || !resolvedEmail) {
|
|
139
|
+
throw new Error("Could not resolve your git identity. Set git config user.name and user.email, or authenticate gh.");
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
name: sanitizeIdentityValue(resolvedName),
|
|
143
|
+
email: sanitizeIdentityValue(resolvedEmail),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
113
146
|
/**
|
|
114
147
|
* Orchestrates the full DCO/attribution setup. Steps run in order; the three
|
|
115
148
|
* foundation steps (preflight, identities, key material) abort the run when
|
|
@@ -160,217 +193,252 @@ export async function runDcoSetup(options = {}) {
|
|
|
160
193
|
...laterSteps,
|
|
161
194
|
]);
|
|
162
195
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
identityRead.status === "ok"
|
|
173
|
-
? ".mcpi/identity.json is missing required fields (did, privateKey). Inspect or restore the file before continuing."
|
|
174
|
-
: "No agent identity found in .mcpi/identity.json. Run `mcpi register` first, then re-run `mcpi dco setup`.";
|
|
175
|
-
}
|
|
176
|
-
else if (await isIdentityTrackedByGit(cwd)) {
|
|
177
|
-
preflightFailure =
|
|
178
|
-
".mcpi/identity.json is tracked by git. A committed identity may have been shipped by the repo author; refusing to configure signing with it. Remove it from git history and generate your own identity with `mcpi register`.";
|
|
179
|
-
}
|
|
180
|
-
if (preflightFailure || !identity?.privateKey || !identity?.did) {
|
|
181
|
-
steps.push({
|
|
182
|
-
id: "preflight",
|
|
183
|
-
title: "Preflight checks",
|
|
184
|
-
status: "failed",
|
|
185
|
-
detail: preflightFailure ??
|
|
186
|
-
"No agent identity found in .mcpi/identity.json. Run `mcpi register` first, then re-run `mcpi dco setup`.",
|
|
187
|
-
});
|
|
188
|
-
return abort([
|
|
189
|
-
{ id: "identities", title: "Resolve agent and human identity" },
|
|
190
|
-
{ id: "key-material", title: "Write SSH signing key" },
|
|
191
|
-
...laterSteps,
|
|
192
|
-
]);
|
|
193
|
-
}
|
|
194
|
-
steps.push({ id: "preflight", title: "Preflight checks", status: "done" });
|
|
195
|
-
// Step 2: resolve identities
|
|
196
|
+
// Steps 1-3 (preflight, identity resolution, key material) branch here and
|
|
197
|
+
// rejoin at Step 4: an explicit agent slug wires signing for an EXISTING
|
|
198
|
+
// registered agent and never reads, requires, or writes `.mcpi/` — the
|
|
199
|
+
// identity is derived from the slug alone (the same derivation
|
|
200
|
+
// `dco dispatch <slug>` uses) and the key must already exist on disk,
|
|
201
|
+
// never generated or converted here. `agent`/`human`/`keyMaterial`/
|
|
202
|
+
// `privateKeyPath`/`publicKeyPath` are populated by whichever branch runs;
|
|
203
|
+
// both either abort the whole run or leave all five set by the time
|
|
204
|
+
// Step 4 reads them.
|
|
196
205
|
let agent;
|
|
197
206
|
let human;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
throw new Error("Agent name/slug unknown. Run `mcpi register`, or set AGENT_NAME and AGENT_SLUG.");
|
|
218
|
-
}
|
|
219
|
-
// The interactive prompt validates its own input; values arriving from
|
|
220
|
-
// agent.json or the environment must pass the same shape check because
|
|
221
|
-
// the slug becomes a filename under the keys directory.
|
|
222
|
-
if (!isValidSlug(slug)) {
|
|
223
|
-
throw new Error(`Invalid agent slug "${slug}": must be lowercase letters, numbers, and dashes.`);
|
|
224
|
-
}
|
|
225
|
-
name = sanitizeIdentityValue(name);
|
|
226
|
-
const metadataUrl = boundMetadata?.url
|
|
227
|
-
? sanitizeIdentityValue(boundMetadata.url)
|
|
228
|
-
: undefined;
|
|
207
|
+
let keyMaterial;
|
|
208
|
+
let privateKeyPath;
|
|
209
|
+
let publicKeyPath;
|
|
210
|
+
if (options.agent) {
|
|
211
|
+
if (!isValidSlug(options.agent)) {
|
|
212
|
+
steps.push({
|
|
213
|
+
id: "preflight",
|
|
214
|
+
title: "Preflight checks",
|
|
215
|
+
status: "failed",
|
|
216
|
+
detail: `Invalid agent slug "${options.agent}": must be lowercase letters, numbers, and dashes.`,
|
|
217
|
+
});
|
|
218
|
+
return abort([
|
|
219
|
+
{ id: "identities", title: "Resolve agent and human identity" },
|
|
220
|
+
{ id: "key-material", title: "Write SSH signing key" },
|
|
221
|
+
...laterSteps,
|
|
222
|
+
]);
|
|
223
|
+
}
|
|
224
|
+
steps.push({ id: "preflight", title: "Preflight checks", status: "done" });
|
|
225
|
+
const slug = options.agent;
|
|
229
226
|
agent = {
|
|
230
|
-
did:
|
|
231
|
-
name,
|
|
227
|
+
did: `did:web:knowthat.ai:agents:${slug}`,
|
|
228
|
+
name: slug,
|
|
232
229
|
slug,
|
|
233
|
-
url:
|
|
234
|
-
? metadataUrl
|
|
235
|
-
: `https://knowthat.ai/agents/${slug}`,
|
|
230
|
+
url: `https://knowthat.ai/agents/${slug}`,
|
|
236
231
|
email: `${slug}@agents.knowthat.ai`,
|
|
237
232
|
};
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
(await isGhInstalled()) &&
|
|
249
|
-
(await isGhAuthenticated())) {
|
|
250
|
-
ghUser = await getGhUser();
|
|
251
|
-
}
|
|
252
|
-
// Use || (not ??) so an explicitly-empty git value is treated as missing,
|
|
253
|
-
// consistent with the truthiness gate above that decides to fetch gh.
|
|
254
|
-
const resolvedName = gitName || (ghUser ? ghUser.name || ghUser.login : undefined);
|
|
255
|
-
const resolvedEmail = gitEmail || (ghUser ? githubNoreplyEmail(ghUser) : undefined);
|
|
256
|
-
if (!resolvedName || !resolvedEmail) {
|
|
257
|
-
throw new Error("Could not resolve your git identity. Set git config user.name and user.email, or authenticate gh.");
|
|
258
|
-
}
|
|
259
|
-
human = {
|
|
260
|
-
name: sanitizeIdentityValue(resolvedName),
|
|
261
|
-
email: sanitizeIdentityValue(resolvedEmail),
|
|
262
|
-
};
|
|
263
|
-
result.agent = agent;
|
|
264
|
-
result.human = human;
|
|
265
|
-
// Persist resolved metadata when the bound record was incomplete (prompted,
|
|
266
|
-
// from env, or unbound), so a later non-interactive run resolves the agent
|
|
267
|
-
// without prompting AND the did binding is written for future runs.
|
|
268
|
-
// Best-effort: a cache-write failure must not fail identity resolution.
|
|
269
|
-
if (!options.dryRun &&
|
|
270
|
-
(!boundMetadata?.name || !boundMetadata?.slug || !boundMetadata?.did)) {
|
|
271
|
-
try {
|
|
272
|
-
writeAgentMetadata(cwd, {
|
|
273
|
-
name: agent.name,
|
|
274
|
-
slug: agent.slug,
|
|
275
|
-
url: agent.url,
|
|
276
|
-
did: agent.did,
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
catch (error) {
|
|
280
|
-
result.metadataPersistWarning =
|
|
281
|
-
error instanceof Error ? error.message : String(error);
|
|
282
|
-
}
|
|
233
|
+
try {
|
|
234
|
+
human = await resolveHumanIdentity(cwd);
|
|
235
|
+
result.agent = agent;
|
|
236
|
+
result.human = human;
|
|
237
|
+
steps.push({
|
|
238
|
+
id: "identities",
|
|
239
|
+
title: "Resolve agent and human identity",
|
|
240
|
+
status: "done",
|
|
241
|
+
detail: `agent=${agent.name} (${agent.slug}), human=${human.name} <${human.email}>`,
|
|
242
|
+
});
|
|
283
243
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
]);
|
|
302
|
-
}
|
|
303
|
-
// Step 3: key material
|
|
304
|
-
let keyMaterial;
|
|
305
|
-
// Slug was validated in the identities step; signingKeyPath re-checks and
|
|
306
|
-
// always yields a path inside the keys directory.
|
|
307
|
-
const privateKeyPath = signingKeyPath(agent.slug);
|
|
308
|
-
const publicKeyPath = `${privateKeyPath}.pub`;
|
|
309
|
-
// Only the write branch below sets this; a failure before it (e.g. a bad
|
|
310
|
-
// identity.json that fails conversion) must NOT delete pre-existing keys.
|
|
311
|
-
let startedKeyWrite = false;
|
|
312
|
-
try {
|
|
313
|
-
keyMaterial = convertEd25519ToSshKey(identity.privateKey, `mcpi:${agent.slug}`, { expectedPublicKeyBase64: identity.publicKey });
|
|
314
|
-
result.privateKeyPath = privateKeyPath;
|
|
315
|
-
result.fingerprint = keyMaterial.fingerprint;
|
|
316
|
-
// Compare BOTH files against the (now deterministic) expected material, so
|
|
317
|
-
// a corrupt/truncated private key with an intact .pub is detected and
|
|
318
|
-
// rewritten rather than left in place to fail signing forever.
|
|
319
|
-
const privUpToDate = existsSync(privateKeyPath) &&
|
|
320
|
-
readFileSync(privateKeyPath, "utf-8") === keyMaterial.privateKeyPem;
|
|
321
|
-
const pubUpToDate = existsSync(publicKeyPath) &&
|
|
322
|
-
readFileSync(publicKeyPath, "utf-8").trim() === keyMaterial.publicKeyLine;
|
|
323
|
-
if (privUpToDate && pubUpToDate) {
|
|
244
|
+
catch (error) {
|
|
245
|
+
steps.push({
|
|
246
|
+
id: "identities",
|
|
247
|
+
title: "Resolve agent and human identity",
|
|
248
|
+
status: "failed",
|
|
249
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
250
|
+
});
|
|
251
|
+
return abort([
|
|
252
|
+
{ id: "key-material", title: "Write SSH signing key" },
|
|
253
|
+
...laterSteps,
|
|
254
|
+
]);
|
|
255
|
+
}
|
|
256
|
+
// Slug was validated above; signingKeyPath re-checks and always yields a
|
|
257
|
+
// path inside the keys directory.
|
|
258
|
+
privateKeyPath = signingKeyPath(agent.slug);
|
|
259
|
+
publicKeyPath = `${privateKeyPath}.pub`;
|
|
260
|
+
if (!existsSync(privateKeyPath) || !existsSync(publicKeyPath)) {
|
|
324
261
|
steps.push({
|
|
325
262
|
id: "key-material",
|
|
326
263
|
title: "Write SSH signing key",
|
|
327
|
-
status: "
|
|
328
|
-
detail: `
|
|
264
|
+
status: "failed",
|
|
265
|
+
detail: `No key for agent "${agent.slug}" at ${privateKeyPath}; run setup in the repo that registered it, or check the slug.`,
|
|
329
266
|
});
|
|
267
|
+
return abort(laterSteps);
|
|
330
268
|
}
|
|
331
|
-
|
|
269
|
+
try {
|
|
270
|
+
const publicKeyLine = readFileSync(publicKeyPath, "utf-8").trim();
|
|
271
|
+
const fingerprint = sshFingerprintFromPublicKeyLine(publicKeyLine);
|
|
272
|
+
keyMaterial = { publicKeyLine, fingerprint };
|
|
273
|
+
result.privateKeyPath = privateKeyPath;
|
|
274
|
+
result.fingerprint = fingerprint;
|
|
332
275
|
steps.push({
|
|
333
276
|
id: "key-material",
|
|
334
277
|
title: "Write SSH signing key",
|
|
335
|
-
status: "
|
|
336
|
-
detail: `
|
|
278
|
+
status: "done",
|
|
279
|
+
detail: `Using existing key at ${privateKeyPath} (${fingerprint})`,
|
|
337
280
|
});
|
|
338
281
|
}
|
|
339
|
-
|
|
340
|
-
mkdirSync(keysDir(), { recursive: true, mode: 0o700 });
|
|
341
|
-
startedKeyWrite = true;
|
|
342
|
-
// mode on write avoids any window where the key exists with loose
|
|
343
|
-
// permissions; the chmod covers overwrites of a pre-existing file,
|
|
344
|
-
// where the mode option is ignored.
|
|
345
|
-
writeFileSync(privateKeyPath, keyMaterial.privateKeyPem, { mode: 0o600 });
|
|
346
|
-
chmodSync(privateKeyPath, 0o600);
|
|
347
|
-
writeFileSync(publicKeyPath, keyMaterial.publicKeyLine + "\n", {
|
|
348
|
-
mode: 0o644,
|
|
349
|
-
});
|
|
350
|
-
chmodSync(publicKeyPath, 0o644);
|
|
282
|
+
catch (error) {
|
|
351
283
|
steps.push({
|
|
352
284
|
id: "key-material",
|
|
353
285
|
title: "Write SSH signing key",
|
|
354
|
-
status: "
|
|
355
|
-
detail:
|
|
286
|
+
status: "failed",
|
|
287
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
356
288
|
});
|
|
289
|
+
return abort(laterSteps);
|
|
357
290
|
}
|
|
358
291
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
if (
|
|
364
|
-
|
|
365
|
-
|
|
292
|
+
else {
|
|
293
|
+
const identityRead = readIdentityFile(cwd);
|
|
294
|
+
const identity = identityRead.status === "ok" ? identityRead.identity : null;
|
|
295
|
+
let preflightFailure = null;
|
|
296
|
+
if (identityRead.status === "corrupt") {
|
|
297
|
+
preflightFailure =
|
|
298
|
+
".mcpi/identity.json exists but could not be parsed. Do NOT re-run `kya-os register` (it would overwrite the identity); inspect or restore the file first.";
|
|
299
|
+
}
|
|
300
|
+
else if (!identity?.privateKey || !identity?.did) {
|
|
301
|
+
preflightFailure =
|
|
302
|
+
identityRead.status === "ok"
|
|
303
|
+
? ".mcpi/identity.json is missing required fields (did, privateKey). Inspect or restore the file before continuing."
|
|
304
|
+
: "No agent identity found in .mcpi/identity.json. Run `kya-os register` first, then re-run `dco setup`.";
|
|
305
|
+
}
|
|
306
|
+
else if (await isIdentityTrackedByGit(cwd)) {
|
|
307
|
+
preflightFailure =
|
|
308
|
+
".mcpi/identity.json is tracked by git. A committed identity may have been shipped by the repo author; refusing to configure signing with it. Remove it from git history and generate your own identity with `kya-os register`.";
|
|
309
|
+
}
|
|
310
|
+
if (preflightFailure || !identity?.privateKey || !identity?.did) {
|
|
311
|
+
steps.push({
|
|
312
|
+
id: "preflight",
|
|
313
|
+
title: "Preflight checks",
|
|
314
|
+
status: "failed",
|
|
315
|
+
detail: preflightFailure ??
|
|
316
|
+
"No agent identity found in .mcpi/identity.json. Run `kya-os register` first, then re-run `dco setup`.",
|
|
317
|
+
});
|
|
318
|
+
return abort([
|
|
319
|
+
{ id: "identities", title: "Resolve agent and human identity" },
|
|
320
|
+
{ id: "key-material", title: "Write SSH signing key" },
|
|
321
|
+
...laterSteps,
|
|
322
|
+
]);
|
|
366
323
|
}
|
|
324
|
+
steps.push({ id: "preflight", title: "Preflight checks", status: "done" });
|
|
325
|
+
try {
|
|
326
|
+
const metadata = readAgentMetadata(cwd);
|
|
327
|
+
if (metadata?.did && metadata.did !== identity.did) {
|
|
328
|
+
throw new Error(`.mcpi/agent.json is for a different agent (${metadata.did}) than .mcpi/identity.json (${identity.did}). Fix or remove agent.json before continuing.`);
|
|
329
|
+
}
|
|
330
|
+
// Only trust agent.json for attribution when it is cryptographically bound
|
|
331
|
+
// to this identity (its did matches identity.json). Unbound metadata (no
|
|
332
|
+
// did, e.g. planted in an untrusted repo) is ignored so it cannot spoof the
|
|
333
|
+
// agent name/slug/url; the resolved values are then persisted with the real
|
|
334
|
+
// did, healing the binding for later runs.
|
|
335
|
+
const boundMetadata = metadata && metadata.did === identity.did ? metadata : null;
|
|
336
|
+
let name = boundMetadata?.name ?? process.env.AGENT_NAME;
|
|
337
|
+
let slug = boundMetadata?.slug ?? process.env.AGENT_SLUG;
|
|
338
|
+
if ((!name || !slug) && interactive && !options.dryRun) {
|
|
339
|
+
const prompted = await promptForAgentName();
|
|
340
|
+
name = name ?? prompted.name;
|
|
341
|
+
slug = slug ?? prompted.slug;
|
|
342
|
+
}
|
|
343
|
+
if (!name || !slug) {
|
|
344
|
+
throw new Error("Agent name/slug unknown. Run `kya-os register`, or set AGENT_NAME and AGENT_SLUG.");
|
|
345
|
+
}
|
|
346
|
+
// The interactive prompt validates its own input; values arriving from
|
|
347
|
+
// agent.json or the environment must pass the same shape check because
|
|
348
|
+
// the slug becomes a filename under the keys directory.
|
|
349
|
+
if (!isValidSlug(slug)) {
|
|
350
|
+
throw new Error(`Invalid agent slug "${slug}": must be lowercase letters, numbers, and dashes.`);
|
|
351
|
+
}
|
|
352
|
+
name = sanitizeIdentityValue(name);
|
|
353
|
+
const metadataUrl = boundMetadata?.url
|
|
354
|
+
? sanitizeIdentityValue(boundMetadata.url)
|
|
355
|
+
: undefined;
|
|
356
|
+
agent = {
|
|
357
|
+
did: identity.did,
|
|
358
|
+
name,
|
|
359
|
+
slug,
|
|
360
|
+
url: metadataUrl && isTrustedAgentUrl(metadataUrl)
|
|
361
|
+
? metadataUrl
|
|
362
|
+
: `https://knowthat.ai/agents/${slug}`,
|
|
363
|
+
email: `${slug}@agents.knowthat.ai`,
|
|
364
|
+
};
|
|
365
|
+
// Resolve the human name and email INDEPENDENTLY, each preferring the
|
|
366
|
+
// configured git value and only falling back to gh for the field that is
|
|
367
|
+
// missing. Resolving them together would let a missing email drop a
|
|
368
|
+
// configured name (or vice versa) in favor of the GitHub profile.
|
|
369
|
+
// Reading gh here is unrelated to the key upload, so it stays available
|
|
370
|
+
// even under --skip-github (which only suppresses the upload).
|
|
371
|
+
human = await resolveHumanIdentity(cwd);
|
|
372
|
+
result.agent = agent;
|
|
373
|
+
result.human = human;
|
|
374
|
+
// Persist resolved metadata when the bound record was incomplete (prompted,
|
|
375
|
+
// from env, or unbound), so a later non-interactive run resolves the agent
|
|
376
|
+
// without prompting AND the did binding is written for future runs.
|
|
377
|
+
// Best-effort: a cache-write failure must not fail identity resolution.
|
|
378
|
+
if (!options.dryRun &&
|
|
379
|
+
(!boundMetadata?.name || !boundMetadata?.slug || !boundMetadata?.did)) {
|
|
380
|
+
try {
|
|
381
|
+
writeAgentMetadata(cwd, {
|
|
382
|
+
name: agent.name,
|
|
383
|
+
slug: agent.slug,
|
|
384
|
+
url: agent.url,
|
|
385
|
+
did: agent.did,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
catch (error) {
|
|
389
|
+
result.metadataPersistWarning =
|
|
390
|
+
error instanceof Error ? error.message : String(error);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
steps.push({
|
|
394
|
+
id: "identities",
|
|
395
|
+
title: "Resolve agent and human identity",
|
|
396
|
+
status: "done",
|
|
397
|
+
detail: `agent=${agent.name} (${agent.slug}), human=${human.name} <${human.email}>`,
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
steps.push({
|
|
402
|
+
id: "identities",
|
|
403
|
+
title: "Resolve agent and human identity",
|
|
404
|
+
status: "failed",
|
|
405
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
406
|
+
});
|
|
407
|
+
return abort([
|
|
408
|
+
{ id: "key-material", title: "Write SSH signing key" },
|
|
409
|
+
...laterSteps,
|
|
410
|
+
]);
|
|
411
|
+
}
|
|
412
|
+
// Slug was validated in the identities step. The conversion, idempotency,
|
|
413
|
+
// and cleanup-on-failure logic live in writeAgentSigningKey, shared with
|
|
414
|
+
// kya-os init's agent-profile stage so both write through the exact same
|
|
415
|
+
// path.
|
|
416
|
+
const keyResult = writeAgentSigningKey(agent.slug,
|
|
417
|
+
// Narrowed property access (not the bare `identity` object) so TS sees
|
|
418
|
+
// these as `string`, matching the preflight check above.
|
|
419
|
+
{ privateKey: identity.privateKey, publicKey: identity.publicKey }, { dryRun: options.dryRun });
|
|
420
|
+
privateKeyPath = keyResult.privateKeyPath;
|
|
421
|
+
if (keyResult.status === "failed") {
|
|
422
|
+
steps.push({
|
|
423
|
+
id: "key-material",
|
|
424
|
+
title: "Write SSH signing key",
|
|
425
|
+
status: "failed",
|
|
426
|
+
detail: keyResult.detail,
|
|
427
|
+
});
|
|
428
|
+
return abort(laterSteps);
|
|
429
|
+
}
|
|
430
|
+
keyMaterial = {
|
|
431
|
+
fingerprint: keyResult.fingerprint,
|
|
432
|
+
publicKeyLine: keyResult.publicKeyLine,
|
|
433
|
+
};
|
|
434
|
+
result.privateKeyPath = privateKeyPath;
|
|
435
|
+
result.fingerprint = keyResult.fingerprint;
|
|
367
436
|
steps.push({
|
|
368
437
|
id: "key-material",
|
|
369
438
|
title: "Write SSH signing key",
|
|
370
|
-
status:
|
|
371
|
-
detail:
|
|
439
|
+
status: keyResult.status,
|
|
440
|
+
detail: keyResult.detail,
|
|
372
441
|
});
|
|
373
|
-
return abort(laterSteps);
|
|
374
442
|
}
|
|
375
443
|
// Step 4: GitHub upload
|
|
376
444
|
if (options.skipGithub) {
|
|
@@ -388,7 +456,7 @@ export async function runDcoSetup(options = {}) {
|
|
|
388
456
|
id: "github-upload",
|
|
389
457
|
title: "Upload signing key to GitHub",
|
|
390
458
|
status: "action-required",
|
|
391
|
-
detail: "GitHub CLI not found. Install from https://cli.github.com, run `gh auth login`, then re-run `
|
|
459
|
+
detail: "GitHub CLI not found. Install from https://cli.github.com, run `gh auth login`, then re-run `dco setup`.",
|
|
392
460
|
});
|
|
393
461
|
}
|
|
394
462
|
else if (!(await isGhAuthenticated())) {
|
|
@@ -396,7 +464,7 @@ export async function runDcoSetup(options = {}) {
|
|
|
396
464
|
id: "github-upload",
|
|
397
465
|
title: "Upload signing key to GitHub",
|
|
398
466
|
status: "action-required",
|
|
399
|
-
detail: "Not authenticated. Run `gh auth login`, then re-run `
|
|
467
|
+
detail: "Not authenticated. Run `gh auth login`, then re-run `dco setup`.",
|
|
400
468
|
});
|
|
401
469
|
}
|
|
402
470
|
else {
|
|
@@ -438,7 +506,7 @@ export async function runDcoSetup(options = {}) {
|
|
|
438
506
|
id: "github-upload",
|
|
439
507
|
title: "Upload signing key to GitHub",
|
|
440
508
|
status: "action-required",
|
|
441
|
-
detail: "Upload declined. Re-run `
|
|
509
|
+
detail: "Upload declined. Re-run `dco setup` when you are ready to upload the key.",
|
|
442
510
|
});
|
|
443
511
|
}
|
|
444
512
|
else {
|
|
@@ -458,7 +526,7 @@ export async function runDcoSetup(options = {}) {
|
|
|
458
526
|
id: "github-upload",
|
|
459
527
|
title: "Upload signing key to GitHub",
|
|
460
528
|
status: "action-required",
|
|
461
|
-
detail: `${error.message} Then re-run \`
|
|
529
|
+
detail: `${error.message} Then re-run \`dco setup\`.`,
|
|
462
530
|
});
|
|
463
531
|
}
|
|
464
532
|
else if (error instanceof GhNotInstalledError) {
|
|
@@ -626,12 +694,7 @@ export async function runDcoSetup(options = {}) {
|
|
|
626
694
|
else {
|
|
627
695
|
try {
|
|
628
696
|
const block = buildAttributionBlock({
|
|
629
|
-
agentName: agent.name,
|
|
630
|
-
agentUrl: agent.url,
|
|
631
697
|
includeTrailerInstructions: hookFallback,
|
|
632
|
-
humanName: human.name,
|
|
633
|
-
humanEmail: human.email,
|
|
634
|
-
agentEmail: agent.email,
|
|
635
698
|
});
|
|
636
699
|
const md = upsertClaudeMdBlock(cwd, block, { dryRun: options.dryRun });
|
|
637
700
|
const settings = updateClaudeSettings(cwd, { dryRun: options.dryRun });
|
|
@@ -680,7 +743,9 @@ export async function runDcoSetup(options = {}) {
|
|
|
680
743
|
"Trailer instructions would be added to the CLAUDE.md attribution block instead.";
|
|
681
744
|
}
|
|
682
745
|
else {
|
|
683
|
-
outcome = `Trailers were NOT added to CLAUDE.md (${options.skipClaude
|
|
746
|
+
outcome = `Trailers were NOT added to CLAUDE.md (${options.skipClaude
|
|
747
|
+
? "--skip-claude"
|
|
748
|
+
: "the Claude Code step did not complete"}); add Signed-off-by / Co-authored-by manually or re-run without --skip-claude.`;
|
|
684
749
|
}
|
|
685
750
|
if (trailerStep) {
|
|
686
751
|
trailerStep.detail = `${hookFallbackDetail} ${outcome}`;
|
|
@@ -701,7 +766,7 @@ export async function runDcoSetup(options = {}) {
|
|
|
701
766
|
const verifyDir = mkdtempSync(join(tmpdir(), "mcpi-dco-verify-"));
|
|
702
767
|
const payloadPath = join(verifyDir, "payload");
|
|
703
768
|
try {
|
|
704
|
-
writeFileSync(payloadPath, "
|
|
769
|
+
writeFileSync(payloadPath, "dco verification payload\n");
|
|
705
770
|
await execFileAsync("ssh-keygen", [
|
|
706
771
|
"-Y",
|
|
707
772
|
"sign",
|