@akira-tl/forgerelay 0.6.1 → 0.7.1

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.
Files changed (63) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +38 -0
  3. package/capabilities/subagents/GUIDE.md +100 -40
  4. package/dist/activity/lifecycle.js +1 -1
  5. package/dist/activity/mcp-query-tools.js +1 -0
  6. package/dist/activity/query-service.js +1 -0
  7. package/dist/capabilities.js +1 -1
  8. package/dist/capability-registry.js +34 -0
  9. package/dist/cli.js +80 -165
  10. package/dist/composite-activity.js +155 -0
  11. package/dist/composite-workspaces.js +197 -0
  12. package/dist/db/migrations.js +14 -0
  13. package/dist/db/schema.js +6 -0
  14. package/dist/remote-workspace-relay.js +16 -0
  15. package/dist/server.js +698 -172
  16. package/dist/{local-agent-targets.js → subagents/cli-target.js} +6 -6
  17. package/dist/{local-agent-profiles.js → subagents/profiles.js} +13 -5
  18. package/dist/subagents/providers/adapters/acp.js +148 -0
  19. package/dist/subagents/providers/adapters/claude.js +75 -0
  20. package/dist/{local-agent-runtime.js → subagents/providers/adapters/codex.js} +10 -4
  21. package/dist/subagents/providers/adapters/opencode.js +137 -0
  22. package/dist/subagents/providers/adapters/pi.js +232 -0
  23. package/dist/{local-agent-availability.js → subagents/providers/availability.js} +24 -10
  24. package/dist/subagents/providers/continuation.js +11 -0
  25. package/dist/subagents/providers/contract.js +1 -0
  26. package/dist/subagents/providers/registry.js +26 -0
  27. package/dist/subagents/providers/shared.js +40 -0
  28. package/dist/subagents/sessions/capability.js +214 -0
  29. package/dist/subagents/sessions/delivery-mailbox.js +115 -0
  30. package/dist/subagents/sessions/execution.js +171 -0
  31. package/dist/subagents/sessions/manager.js +107 -0
  32. package/dist/subagents/sessions/mcp/audit.js +85 -0
  33. package/dist/subagents/sessions/mcp/runtime.js +19 -0
  34. package/dist/{local-agent-store.js → subagents/sessions/store.js} +75 -39
  35. package/dist/ui/.vite/manifest.json +33 -33
  36. package/dist/ui/activity-panel-app.html +3 -3
  37. package/dist/ui/assets/{activity-panel-app-CjZVvVNc.js → activity-panel-app-E1ju2dqI.js} +1 -1
  38. package/dist/ui/assets/{heavy-payload-vGgBRvNX.js → heavy-payload-CeW-n9w5.js} +1 -1
  39. package/dist/ui/assets/{review-payload-4erWKckt.js → review-payload-B9CO298v.js} +1 -1
  40. package/dist/ui/assets/{scrollbar-CaOPzUJd.js → scrollbar-C2twAENW.js} +1 -1
  41. package/dist/ui/assets/workspace-app-BztEvZIC.js +5 -0
  42. package/dist/ui/assets/{workspace-app-DkAiSl_0.js → workspace-app-CwbJnb_w.js} +1 -1
  43. package/dist/ui/assets/workspace-app-YnUST8IP.css +1 -0
  44. package/dist/ui/assets/workspace-app-rKuhdae8.js +1 -0
  45. package/dist/ui/assets/workspace-lifecycle-app-CEfMdudP.js +1 -0
  46. package/dist/ui/workspace-app.html +4 -4
  47. package/dist/ui/workspace-lifecycle-app.html +4 -4
  48. package/dist/workspaces.js +3 -3
  49. package/docs/chatgpt-coding-workflow.md +2 -9
  50. package/docs/configuration.md +23 -0
  51. package/docs/debugging.md +7 -0
  52. package/docs/roadmap.md +42 -7
  53. package/package.json +2 -2
  54. package/scripts/debug/runtime.mjs +23 -1
  55. package/scripts/debug/runtime.test.mjs +14 -2
  56. package/scripts/debug/serve.mjs +4 -4
  57. package/scripts/release/release-gate.test.mjs +2 -2
  58. package/dist/local-agent-adapters.js +0 -653
  59. package/dist/ui/assets/workspace-app-CcrHAUIn.css +0 -1
  60. package/dist/ui/assets/workspace-app-DJmkPYJC.js +0 -1
  61. package/dist/ui/assets/workspace-app-QyauBrJX.js +0 -5
  62. package/dist/ui/assets/workspace-lifecycle-app-BIXEo53I.js +0 -1
  63. /package/dist/{local-agent-path.js → subagents/providers/path.js} +0 -0
@@ -0,0 +1 @@
1
+ .forgerelay-panel{border:1px solid var(--tool-card-border);background:var(--tool-card-header-bg);width:100%;color:var(--color-text-primary,#f5f5f6);border-radius:12px;overflow:hidden}.workspace-panel{background:var(--tool-card-header-bg);width:100%}.workspace-panel-header{grid-template-columns:22px minmax(0,1fr) auto;align-items:center;gap:10px;min-height:58px;padding:9px 12px;display:grid}.workspace-panel-icon{background:color-mix(in srgb, var(--tool-accent) 9%, transparent);width:22px;height:22px;color:color-mix(in srgb, var(--tool-accent) 72%, var(--color-text-tertiary,#a3a3aa));border-radius:6px;place-items:center;display:grid}.workspace-panel-icon-svg{stroke-width:1.8px;width:14px;height:14px}.workspace-panel-title-group{gap:2px;min-width:0;display:grid}.workspace-panel-title{font-size:var(--font-text-sm-size,14px);font-weight:600;line-height:1.3}.workspace-panel-subtitle,.workspace-panel-mode{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,11px);line-height:1.35}.workspace-panel-subtitle{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.workspace-panel-mode{border:1px solid color-mix(in srgb, var(--tool-card-divider) 76%, transparent);white-space:nowrap;border-radius:999px;padding:2px 7px}.workspace-panel .workspace-details{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg);max-height:none}.workspace-panel-pending-dot{background:var(--color-text-info,#38bdf8);width:8px;height:8px;box-shadow:0 0 0 3px color-mix(in srgb, var(--color-text-info,#38bdf8) 12%, transparent);border-radius:999px;justify-self:center}.activity-panel{border:1px solid var(--tool-card-border);background:var(--tool-card-header-bg);width:100%;color:var(--color-text-primary,#f5f5f6);border-radius:12px;overflow:hidden}.forgerelay-panel .activity-panel{border:0;border-top:1px solid var(--tool-card-divider);border-radius:0}.activity-panel-header{width:100%;min-height:58px;color:inherit;cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:14px minmax(0,1fr) auto 20px;align-items:center;gap:10px;padding:9px 12px;display:grid}.activity-panel-header:hover{background:var(--tool-card-hover-bg)}.activity-panel-header:focus-visible{outline:2px solid color-mix(in srgb, var(--color-text-info,#38bdf8) 72%, transparent);outline-offset:-2px}.activity-panel-header-pending{cursor:default}.activity-panel-header-pending:hover{background:0 0}.activity-panel-pending-spacer{width:20px}.activity-panel-status{background:var(--color-text-info,#38bdf8);width:8px;height:8px;box-shadow:0 0 0 3px color-mix(in srgb, var(--color-text-info,#38bdf8) 12%, transparent);border-radius:9999px;justify-self:center}.activity-panel-status.state-done{background:var(--color-success-text,#6fda83);box-shadow:0 0 0 3px color-mix(in srgb, var(--color-success-text,#6fda83) 12%, transparent)}.activity-panel-status.state-error{background:var(--color-danger-text,#ee7676);box-shadow:0 0 0 3px color-mix(in srgb, var(--color-danger-text,#ee7676) 12%, transparent)}.activity-panel-title-group{gap:2px;min-width:0;display:grid}.activity-panel-title{font-size:var(--font-text-sm-size,14px);font-weight:600;line-height:1.3}.activity-panel-subtitle,.activity-panel-count{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,11px);line-height:1.35}.activity-panel-count{white-space:nowrap}.activity-panel-body{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg);display:grid}.activity-viewport{overscroll-behavior:contain;max-height:420px;overflow:hidden auto}.activity-list{display:grid}.activity-group+.activity-group{border-top:1px solid var(--tool-card-divider)}.activity-group.grouped>.activity-row.parent{background:color-mix(in srgb, var(--color-background-secondary,#272727) 54%, transparent)}.activity-children{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 72%, transparent);display:grid}.activity-row{--activity-accent:var(--color-text-secondary,#b6b6bd);--activity-phase:var(--color-text-tertiary,#a3a3aa);width:100%;min-height:46px;color:inherit;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:28px minmax(0,1fr) auto 16px;align-items:center;gap:10px;padding:7px 12px;display:grid}.activity-row.interactive{cursor:pointer}.activity-row.interactive:hover{background:var(--tool-card-hover-bg)}.activity-row.interactive:focus-visible{outline:2px solid color-mix(in srgb, var(--activity-accent) 68%, transparent);outline-offset:-2px}.activity-row.child{padding-left:34px;position:relative}.activity-row.child:before{background:color-mix(in srgb, var(--activity-accent) 26%, var(--tool-card-divider));content:"";width:1px;position:absolute;top:0;bottom:0;left:20px}.activity-row.child+.activity-row.child{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 52%, transparent)}.activity-row.kind-read{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 32%, #06b6d4 68%)}.activity-row.kind-write{--activity-accent:var(--color-success-text,#6fda83)}.activity-row.kind-edit,.activity-row.kind-rename{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 28%, #d99742 72%)}.activity-row.kind-delete{--activity-accent:var(--color-danger-text,#ee7676)}.activity-row.kind-shell{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 42%, #64748b 58%)}.activity-row.kind-shell-result{--activity-accent:color-mix(in srgb, var(--color-success-text,#6fda83) 72%, var(--color-text-secondary,#b6b6bd))}.activity-row.kind-capability{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 34%, #3b82f6 66%)}.activity-row.kind-batch{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 34%, #8b5cf6 66%)}.activity-row.phase-executing{--activity-phase:var(--color-text-info,#38bdf8)}.activity-row.phase-returned{--activity-phase:var(--color-warning-text,#e6b566)}.activity-row.phase-done{--activity-phase:var(--color-success-text,#6fda83)}.activity-row.phase-error{--activity-phase:var(--color-danger-text,#ee7676)}.activity-row.shell-result{box-shadow:inset 2px 0 0 color-mix(in srgb, var(--activity-accent) 68%, transparent)}.activity-icon{border:1px solid color-mix(in srgb, var(--activity-accent) 18%, transparent);background:color-mix(in srgb, var(--activity-accent) 9%, transparent);width:28px;height:28px;color:var(--activity-accent);border-radius:7px;place-items:center;display:grid}.activity-icon-svg{stroke-width:1.8px;width:15px;height:15px}.activity-main{gap:4px;min-width:0;display:grid}.activity-title-line{align-items:baseline;gap:8px;min-width:0;display:flex}.activity-title{color:var(--color-text-primary,#f5f5f6);font-size:var(--font-text-sm-size,12px);flex:none;font-weight:600;line-height:1.35}.activity-member{color:var(--color-text-secondary,#d4d4d8);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,10px);flex:none;line-height:1.4}.activity-target{min-width:0;color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,11px);text-overflow:ellipsis;white-space:nowrap;line-height:1.4;overflow:hidden}.activity-meta{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);font-variant-numeric:tabular-nums;white-space:nowrap;justify-content:flex-end;align-items:center;gap:8px;display:inline-flex}.activity-phase{color:var(--activity-phase);align-items:center;gap:5px;display:inline-flex}.activity-phase:before{content:"";background:currentColor;border-radius:9999px;width:6px;height:6px}.activity-progress-wrap{grid-template-columns:auto minmax(48px,110px);align-items:center;gap:8px;max-width:220px;display:grid}.activity-progress-counts{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);font-variant-numeric:tabular-nums;white-space:nowrap}.activity-progress-track{background:color-mix(in srgb, var(--activity-accent) 14%, var(--tool-card-divider));border-radius:9999px;height:3px;display:block;overflow:hidden}.activity-progress-fill{border-radius:inherit;background:var(--activity-accent);height:100%;display:block}.activity-empty,.activity-refresh-error{color:var(--color-text-secondary,#b7b7bf);font-size:var(--font-text-sm-size,12px);padding:12px}.activity-refresh-error{border-top:1px solid var(--tool-card-divider);color:var(--color-danger-text,#ee7676)}.activity-detail-chevron,.activity-detail-spacer,.activity-detail-chevron.chevron{width:16px;height:16px}.activity-detail-chevron .icon-svg{width:13px;height:13px}.activity-entry.expanded>.activity-row{background:color-mix(in srgb, var(--activity-accent) 6%, transparent)}.activity-detail{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 72%, transparent);background:color-mix(in srgb, var(--color-background-primary,#101114) 90%, transparent);display:grid}.activity-detail-section+.activity-detail-section{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 62%, transparent)}.activity-detail-label{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);letter-spacing:.02em;padding:8px 12px 0;font-weight:600}.activity-detail-section.error .activity-detail-label,.activity-detail-section.error .activity-detail-value{color:var(--color-danger-text,#ee7676)}.activity-detail-value{max-height:260px;color:var(--color-text-secondary,#c7c7ce);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,11px);white-space:pre-wrap;overflow-wrap:break-word;margin:0;padding:6px 12px 10px;line-height:1.5;overflow:auto}.activity-detail-status{color:var(--color-text-secondary,#b7b7bf);font-size:var(--font-text-sm-size,12px);padding:10px 12px}.activity-detail-status.error{color:var(--color-danger-text,#ee7676)}.activity-terminal{background:var(--color-background-primary,#101114)}.activity-terminal-command,.activity-terminal-output{color:var(--color-text-primary,#f5f5f6);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,11px);white-space:pre-wrap;overflow-wrap:break-word;background:0 0;border:0;border-radius:0;margin:0;line-height:1.55}.activity-terminal-command{border-bottom:1px solid color-mix(in srgb, var(--tool-card-divider) 74%, transparent);color:var(--color-text-secondary,#c7c7ce);padding:9px 12px}.activity-terminal-output{max-height:320px;padding:10px 12px;overflow:auto}.activity-terminal-meta{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 74%, transparent);color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);font-variant-numeric:tabular-nums;padding:7px 12px}.activity-terminal-meta.status-running{color:var(--color-text-info,#38bdf8)}.activity-terminal-meta.status-done{color:var(--color-success-text,#6fda83)}.activity-terminal-meta.status-failed{color:var(--color-danger-text,#ee7676)}@media (width<=520px){.activity-panel-header{grid-template-columns:12px minmax(0,1fr) auto 18px;gap:8px;min-height:54px;padding:8px 10px}.activity-panel-subtitle,.activity-panel-count{font-size:10px}.activity-row{grid-template-columns:26px minmax(0,1fr) 18px;gap:6px 8px;min-height:48px;padding:8px 10px}.activity-row.child{padding-left:28px}.activity-row.child:before{left:16px}.activity-icon{align-self:start;width:26px;height:26px}.activity-title-line{gap:2px;display:grid}.activity-meta{grid-column:2;justify-content:flex-start}.activity-detail-chevron,.activity-detail-spacer{grid-area:1/3/span 2}.activity-progress-wrap{grid-template-columns:auto minmax(40px,1fr);max-width:none}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);color:var(--color-text-primary,#f5f5f6);--tool-card-border:color-mix(in srgb, var(--color-border-primary,#414141) 74%, transparent);--tool-card-header-bg:color-mix(in srgb, var(--color-background-secondary,#272727) 88%, transparent);--tool-card-body-bg:color-mix(in srgb, var(--color-background-primary,#181818) 94%, transparent);--tool-card-hover-bg:color-mix(in srgb, var(--color-background-tertiary,#343434) 46%, transparent);--tool-card-divider:color-mix(in srgb, var(--color-border-primary,#414141) 66%, transparent);--tool-accent:var(--color-text-secondary,#b6b6bd);--scrollbar-thumb:color-mix(in srgb, var(--color-text-tertiary,#8a8a8a) 56%, transparent);--scrollbar-thumb-hover:color-mix(in srgb, var(--color-text-secondary,#a8a8a8) 82%, transparent);background:0 0}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}*{box-sizing:border-box}html,body{background:0 0;margin:0;overflow:hidden}.shell{width:100%;padding:0;overflow:hidden}.empty,.tool-card{--tool-accent-soft:color-mix(in srgb, var(--tool-accent) 12%, transparent);border:1px solid var(--tool-card-border);background:var(--tool-card-header-bg);width:100%;box-shadow:none;color:var(--color-text-primary,#f5f5f6);border-radius:12px;overflow:hidden}.tool-card.workspace,.tool-card.directory{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 34%, #3b82f6 66%)}.tool-card.read,.tool-card.search{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 32%, #06b6d4 68%)}.tool-card.write{--tool-accent:var(--color-success-text,#6fda83)}.tool-card.edit,.tool-card.review{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 28%, #d99742 72%)}.tool-card.delete{--tool-accent:var(--color-danger-text,#ee7676)}.tool-card.shell{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 42%, #64748b 58%)}.tool-card.state-success{--tool-accent:var(--color-success-text,#6fda83)}.tool-card.state-error{--tool-accent:var(--color-danger-text,#ee7676)}.tool-card.state-running{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 30%, #38bdf8 70%)}@supports selector(::-webkit-scrollbar){.pretty-scrollbar::-webkit-scrollbar{width:12px;height:12px}.pretty-scrollbar::-webkit-scrollbar-button{width:0;height:0;display:none}.pretty-scrollbar::-webkit-scrollbar-track{background:0 0}.pretty-scrollbar::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb);background-clip:content-box;border:4px solid #0000;border-radius:9999px}.pretty-scrollbar::-webkit-scrollbar-thumb:hover{background-color:var(--scrollbar-thumb-hover)}.pretty-scrollbar::-webkit-scrollbar-thumb:active{background-color:var(--scrollbar-thumb-hover)}.pretty-scrollbar::-webkit-scrollbar-corner{background:0 0}}.empty{color:var(--color-text-secondary,#b6b6bd);font-size:var(--font-text-sm-size,13px);padding:14px 16px}.tool-header{width:100%;min-height:64px;color:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:11px;grid-template-columns:40px minmax(0,1fr) auto 20px;align-items:center;gap:12px;padding:10px 12px;display:grid}.tool-header:focus-visible,.review-diff-file-header:focus-visible,.review-more:focus-visible{outline:2px solid color-mix(in srgb, var(--tool-accent) 72%, transparent);outline-offset:-2px}.tool-header:hover:not(:disabled){background:var(--tool-card-hover-bg)}.tool-header:disabled{cursor:default}.tool-icon{border:1px solid color-mix(in srgb, var(--tool-accent) 18%, transparent);background:var(--tool-accent-soft);width:40px;height:40px;color:var(--tool-accent);border-radius:10px;place-items:center;display:grid}.icon-svg{stroke-width:1.8px;width:20px;height:20px;display:block}.tool-main{gap:2px;min-width:0;display:grid}.tool-title{color:var(--color-text-primary,#f5f5f6);font-size:var(--font-text-sm-size,14px);font-weight:550;line-height:1.3}.tool-label{color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,12px);text-overflow:ellipsis;white-space:nowrap;line-height:1.4;overflow:hidden}.stats{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,12px);font-variant-numeric:tabular-nums;white-space:nowrap;align-items:center;gap:5px;display:inline-flex}.header-meta{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-sm-size,12px);text-align:right;white-space:nowrap;line-height:1.35}.header-meta.empty{width:0}.add{color:var(--color-success-text,#6fda83)}.remove{color:var(--color-danger-text,#ee7676)}.chevron{width:20px;height:20px;color:var(--color-text-tertiary,#a3a3aa);border-radius:7px;place-items:center;transition:background .14s,color .14s,transform .14s;display:grid}.tool-header:hover:not(:disabled) .chevron{color:var(--color-text-primary,#f5f5f6)}.chevron .icon-svg{width:15px;height:15px}.chevron.expanded{transform:rotate(180deg)}.chevron.loading{transform:none}.chevron.loading .icon-svg{fill:none;stroke-linecap:round;stroke-dasharray:38 14;animation:.7s linear infinite payload-spinner}@keyframes payload-spinner{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.chevron.loading .icon-svg{animation:none}}.tool-body{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg)}.workspace-details{max-height:420px;display:grid;overflow:auto}.workspace-rows{padding:4px 0;display:grid}.workspace-row{grid-template-columns:22px minmax(116px,.24fr) minmax(0,1fr);align-items:center;gap:10px;min-height:40px;padding:7px 12px;display:grid}.workspace-row-icon{background:color-mix(in srgb, var(--tool-accent) 9%, transparent);width:22px;height:22px;color:color-mix(in srgb, var(--tool-accent) 72%, var(--color-text-tertiary,#a3a3aa));border-radius:6px;place-items:center;display:grid}.workspace-row-icon-svg{stroke-width:1.8px;width:14px;height:14px}.workspace-key{min-height:22px;color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-sm-size,12px);align-items:center;font-weight:500;display:flex}.workspace-value{min-width:0;color:var(--color-text-secondary,#c7c7ce);font-size:var(--font-text-sm-size,12px);text-overflow:ellipsis;white-space:nowrap;line-height:1.45;overflow:hidden}.workspace-value.mono{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace)}.workspace-base-value{align-items:center;gap:7px;min-width:0;display:flex}.workspace-base-value .workspace-value{flex:0 auto}.workspace-base-warning{width:18px;height:18px;color:var(--color-warning-text,#e6b566);cursor:help;flex:none;place-items:center;display:grid}.workspace-base-warning-svg{stroke-width:2px;width:14px;height:14px}.workspace-chip-list{flex-wrap:nowrap;align-items:center;gap:6px;min-width:0;display:flex;overflow:hidden}.workspace-chip{border:1px solid color-mix(in srgb, var(--tool-accent) 16%, var(--tool-card-divider));background:color-mix(in srgb, var(--tool-accent) 7%, transparent);max-width:100%;min-height:24px;color:var(--color-text-secondary,#c7c7ce);text-overflow:ellipsis;white-space:nowrap;border-radius:9999px;flex:none;align-items:center;gap:5px;padding:3px 8px;font-size:11px;line-height:1.25;display:inline-flex;overflow:hidden}.workspace-chip-logo{object-fit:contain;flex:none;width:13px;height:13px;display:block}.workspace-chip-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.workspace-agent-profile{border:0;border-bottom:1px solid color-mix(in srgb, var(--tool-accent) 34%, var(--tool-card-divider));max-width:100%;min-height:24px;color:var(--color-text-secondary,#c7c7ce);white-space:nowrap;background:0 0;border-radius:0;align-items:center;gap:5px;padding:3px 2px 4px;font-size:11px;line-height:1.25;display:inline-flex;overflow:hidden}.workspace-agent-profile-logo{object-fit:contain;flex:none;width:14px;height:14px;display:block}.workspace-agent-profile:hover{border-bottom-color:var(--tool-accent);color:var(--color-text-primary,#f5f5f6)}.workspace-agent-profile.muted{color:var(--color-text-tertiary,#a3a3aa);opacity:.72;border-bottom-style:dashed}.workspace-provider-logo{cursor:help;flex:none;place-items:center;width:20px;height:24px;display:inline-grid}.workspace-provider-logo-image{object-fit:contain;width:16px;height:16px;display:block}.workspace-provider-logo.muted{opacity:.62}.workspace-chip.muted{color:var(--color-text-tertiary,#a3a3aa);opacity:.72;border-style:dashed}.workspace-skills-row,.workspace-instructions-row,.workspace-agents-row{align-items:start}.workspace-skills-list,.workspace-agents-list{flex-wrap:wrap;overflow:visible}.workspace-instruction-status{border-radius:5px;flex:none;place-items:center;width:18px;height:18px;display:grid}.workspace-instruction-status.loaded{background:color-mix(in srgb, var(--color-success-text,#6fda83) 12%, transparent);color:var(--color-success-text,#6fda83)}.workspace-instruction-status.available{background:color-mix(in srgb, var(--color-text-tertiary,#a3a3aa) 9%, transparent);color:var(--color-text-tertiary,#a3a3aa)}.workspace-instruction-status-svg{stroke-width:1.9px;width:12px;height:12px}.workspace-instruction-list{border:1px solid var(--tool-card-divider);background:color-mix(in srgb, var(--tool-card-body-bg) 88%, transparent);border-radius:9px;min-width:0;display:grid;overflow:hidden}.workspace-instructions-content{min-width:0;display:block}.workspace-instructions-toggle{border:0;border-top:1px solid var(--tool-card-divider);background:color-mix(in srgb, var(--tool-card-body-bg) 72%, transparent);width:100%;min-height:32px;color:var(--tool-accent);cursor:pointer;font:inherit;font-size:var(--font-text-sm-size,11px);white-space:nowrap;border-radius:0 0 9px 9px;justify-content:center;align-items:center;padding:6px 10px;font-weight:550;line-height:1.25;display:flex}.workspace-instructions-toggle:hover{background:var(--tool-card-hover-bg)}.workspace-instructions-toggle:focus-visible{outline:2px solid color-mix(in srgb, var(--tool-accent) 72%, transparent);outline-offset:2px}.workspace-instruction-item+.workspace-instruction-item{border-top:1px solid var(--tool-card-divider)}.workspace-instruction-header{width:100%;min-width:0;color:inherit;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:22px minmax(0,1fr) 18px;align-items:center;gap:9px;padding:8px 10px;display:grid}.workspace-instruction-header.interactive{cursor:pointer}.workspace-instruction-header.interactive:hover{background:var(--tool-card-hover-bg)}.workspace-instruction-header.interactive:focus-visible{outline:2px solid color-mix(in srgb, var(--tool-accent) 72%, transparent);outline-offset:-2px}.workspace-instruction-text{gap:2px;min-width:0;display:grid}.workspace-instruction-name{min-width:0;color:var(--color-text-primary,#f5f5f6);font-size:var(--font-text-sm-size,12px);text-overflow:ellipsis;white-space:nowrap;font-weight:550;overflow:hidden}.workspace-instruction-path{min-width:0;color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:1.35;overflow:hidden}.workspace-instruction-chevron{width:18px;height:18px;color:var(--color-text-tertiary,#a3a3aa);place-items:center;transition:transform .14s;display:grid}.workspace-instruction-item.expanded .workspace-instruction-chevron{transform:rotate(180deg)}.workspace-instruction-chevron-svg{width:14px;height:14px}.workspace-instruction-preview{border-top:1px solid var(--tool-card-divider);background:color-mix(in srgb, var(--color-background-primary,#101114) 92%, transparent);max-height:300px;color:var(--color-text-secondary,#c7c7ce);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);white-space:pre-wrap;overflow-wrap:break-word;margin:0;padding:10px 12px;font-size:11px;line-height:1.55;overflow:auto}.workspace-instruction-preview[hidden]{display:none}.review-header{grid-template-columns:40px minmax(0,1fr) auto 20px}.review-title-group{gap:3px;min-width:0;display:grid}.review-summary{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg);display:grid}.review-diff-file-stats{align-items:center;gap:8px;display:flex}.review-empty{color:var(--color-text-secondary,#b7b7bf);font-size:var(--font-text-sm-size,13px)}.review-more{border:0;border-top:1px solid var(--tool-card-divider);width:100%;min-height:40px;color:var(--color-text-tertiary,#a3a3aa);cursor:pointer;font:inherit;font-size:var(--font-text-sm-size,12px);text-align:left;background:0 0;padding:0 12px}.review-more:hover{background:var(--tool-card-hover-bg);color:var(--color-text-primary,#f5f5f6)}.review-diff{max-height:520px;display:grid;overflow:hidden auto}.review-diff-files{gap:0;padding:0;display:grid}.review-diff-file{border:0;border-radius:0;overflow:hidden}.review-diff-file+.review-diff-file{border-top:1px solid var(--tool-card-divider)}.review-diff-file-header{width:100%;min-height:42px;color:var(--color-text-primary,#f5f5f6);cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:22px minmax(0,1fr) auto;align-items:center;gap:10px;padding:0 12px;display:grid}.review-file-kind{background:color-mix(in srgb, var(--color-text-tertiary,#a3a3aa) 10%, transparent);width:20px;height:20px;color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);border-radius:6px;align-self:center;place-items:center;font-size:10px;font-weight:700;display:grid}.review-file-kind.added{background:color-mix(in srgb, var(--color-success-text,#6fda83) 12%, transparent);color:var(--color-success-text,#6fda83)}.review-file-kind.edited,.review-file-kind.renamed,.review-file-kind.renamed-edited{background:color-mix(in srgb, var(--color-warning-text,#e6b566) 12%, transparent);color:var(--color-warning-text,#e6b566)}.review-file-kind.deleted{background:color-mix(in srgb, var(--color-danger-text,#ee7676) 12%, transparent);color:var(--color-danger-text,#ee7676)}.review-single-file{overflow:hidden}.review-diff-file-header:hover{background:var(--tool-card-hover-bg)}.review-diff-file-name,.review-diff-file-stats{text-overflow:ellipsis;white-space:nowrap;font-size:13px;line-height:20px;overflow:hidden}.review-diff-file-name{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace)}.review-diff-file-name.renamed{text-overflow:clip;align-items:center;gap:6px;min-width:0;display:flex}.review-diff-file-path{text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:calc(50% - 10px);overflow:hidden}.review-diff-file-path.previous{color:var(--color-text-tertiary,#a3a3aa)}.review-diff-file-path.current{color:var(--color-text-primary,#f5f5f6)}.review-diff-file-arrow{color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);flex:none}.review-diff-file-stats{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-sm-size,12px);font-variant-numeric:tabular-nums;justify-content:flex-end;overflow:visible}.status{font-size:var(--font-text-sm-size,12px);padding:10px 12px}.status.muted{color:var(--color-text-secondary,#b7b7bf)}.status.error{color:var(--color-danger-text,#ee7676)}.pierre-diff,.pierre-file{--diffs-bg:var(--tool-payload-bg,var(--color-background-primary,#101114));--diffs-light-bg:var(--color-background-primary,#fff);--diffs-dark-bg:var(--tool-payload-bg,var(--color-background-primary,#101114));--diffs-font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);--diffs-header-font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);--diffs-font-size:var(--font-text-sm-size,12px);--diffs-line-height:20px;border-bottom-right-radius:8px;border-bottom-left-radius:8px;max-height:420px;display:block;overflow:auto}.text-payload{max-height:420px;color:var(--color-text-secondary,#c7c7ce);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-sm-size,12px);white-space:pre-wrap;overflow-wrap:break-word;margin:0;padding:10px 12px;line-height:1.55;overflow:auto}.text-payload.bash{color:var(--color-text-primary,#f5f5f6);background:var(--color-background-primary,#101114)}@media (width<=520px){.tool-header{grid-template-columns:36px minmax(0,1fr) auto 18px;gap:9px;min-height:58px;padding:9px 10px}.tool-icon{border-radius:9px;width:36px;height:36px}.chevron{width:18px;height:18px}.review-header{grid-template-columns:36px minmax(0,1fr) auto 18px}.workspace-row{grid-template-columns:22px minmax(0,1fr);gap:2px 8px;padding-block:8px}.workspace-row-icon{grid-row:1/span 2;align-self:start}.workspace-row>.workspace-key,.workspace-row>.workspace-value,.workspace-row>.workspace-chip-list,.workspace-row>.workspace-instructions-content{grid-column:2}}
@@ -0,0 +1 @@
1
+ import"./workspace-app-CwbJnb_w.js";import"./workspace-app-BztEvZIC.js";document.documentElement.dataset.forgerelayApp=`historical-tool-card`;
@@ -0,0 +1 @@
1
+ import"./workspace-app-CwbJnb_w.js";import"./workspace-app-BztEvZIC.js";document.documentElement.dataset.forgerelayApp=`workspace-lifecycle-compatibility`;
@@ -4,11 +4,11 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>ForgeRelay Diff</title>
7
- <script type="module" crossorigin src="./assets/workspace-app-DJmkPYJC.js"></script>
7
+ <script type="module" crossorigin src="./assets/workspace-app-rKuhdae8.js"></script>
8
8
  <link rel="modulepreload" crossorigin href="./assets/chunk-EyZ2wyi3.js">
9
- <link rel="modulepreload" crossorigin href="./assets/workspace-app-DkAiSl_0.js">
10
- <link rel="modulepreload" crossorigin href="./assets/workspace-app-QyauBrJX.js">
11
- <link rel="stylesheet" crossorigin href="./assets/workspace-app-CcrHAUIn.css">
9
+ <link rel="modulepreload" crossorigin href="./assets/workspace-app-CwbJnb_w.js">
10
+ <link rel="modulepreload" crossorigin href="./assets/workspace-app-BztEvZIC.js">
11
+ <link rel="stylesheet" crossorigin href="./assets/workspace-app-YnUST8IP.css">
12
12
  </head>
13
13
  <body>
14
14
  <main id="app" class="shell">
@@ -4,11 +4,11 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>ForgeRelay Workspace Lifecycle</title>
7
- <script type="module" crossorigin src="./assets/workspace-lifecycle-app-BIXEo53I.js"></script>
7
+ <script type="module" crossorigin src="./assets/workspace-lifecycle-app-CEfMdudP.js"></script>
8
8
  <link rel="modulepreload" crossorigin href="./assets/chunk-EyZ2wyi3.js">
9
- <link rel="modulepreload" crossorigin href="./assets/workspace-app-DkAiSl_0.js">
10
- <link rel="modulepreload" crossorigin href="./assets/workspace-app-QyauBrJX.js">
11
- <link rel="stylesheet" crossorigin href="./assets/workspace-app-CcrHAUIn.css">
9
+ <link rel="modulepreload" crossorigin href="./assets/workspace-app-CwbJnb_w.js">
10
+ <link rel="modulepreload" crossorigin href="./assets/workspace-app-BztEvZIC.js">
11
+ <link rel="stylesheet" crossorigin href="./assets/workspace-app-YnUST8IP.css">
12
12
  </head>
13
13
  <body>
14
14
  <main id="app" class="shell">
@@ -7,7 +7,7 @@ import { HookRunner } from "./hooks.js";
7
7
  import { closeManagedWorktree, createManagedWorktree, resolveManagedWorktreeBase, } from "./git-worktrees.js";
8
8
  import { AccessDeniedError, assertAllowedPath, isPathInsideRoot, resolveAllowedPath, } from "./roots.js";
9
9
  import { loadWorkspaceSkills, markSkillActivated, resolveSkillReadPath, } from "./skills.js";
10
- import { loadLocalAgentProfiles, } from "./local-agent-profiles.js";
10
+ import { loadSubagentProfiles, } from "./subagents/profiles.js";
11
11
  const WORKSPACE_STALE_REMINDER_MS = 2 * 24 * 60 * 60 * 1_000;
12
12
  const WORKSPACE_SESSION_IDLE_TTL_MS = 30 * 24 * 60 * 60 * 1_000;
13
13
  const WORKSPACE_GC_INTERVAL_MS = 60 * 60 * 1_000;
@@ -634,7 +634,7 @@ export class WorkspaceRegistry {
634
634
  async reusedWorkspaceContext(workspace) {
635
635
  Object.assign(workspace, this.loadSkillsForWorkspace(workspace.root));
636
636
  workspace.capabilityGuides = loadCapabilityGuides(this.config);
637
- workspace.agentProfiles = await loadLocalAgentProfiles(this.config, workspace.root);
637
+ workspace.agentProfiles = await loadSubagentProfiles(this.config, workspace.root);
638
638
  workspace.scannedInstructionDirs.clear();
639
639
  workspace.knownInstructionPathsByDir.clear();
640
640
  workspace.loadedInstructionRealPaths.clear();
@@ -800,7 +800,7 @@ export class WorkspaceRegistry {
800
800
  worktree: input.worktree,
801
801
  ...this.loadSkillsForWorkspace(input.root),
802
802
  capabilityGuides: loadCapabilityGuides(this.config),
803
- agentProfiles: await loadLocalAgentProfiles(this.config, input.root),
803
+ agentProfiles: await loadSubagentProfiles(this.config, input.root),
804
804
  activatedSkillDirs: new Set(),
805
805
  activatedCapabilityGuideDirs: new Set(),
806
806
  scannedInstructionDirs: new Set(),
@@ -235,16 +235,9 @@ ForgeRelay-owned `subagents` capability guide when delegation is actually needed
235
235
  new setups. Existing user-authored or previously seeded Skills remain normal
236
236
  user configuration and are not deleted.
237
237
 
238
- The current model-facing delegation workflow is:
238
+ Host 正常委派通过现有 `capability` Gateway 中的 `subagent.session` 完成,不增加新的 Core MCP tool。支持的生命周期操作包括 `start`、`resume`、`status`、`list`、`stop` 和 `delete`;具体参数与 provider continuation 能力以 `subagents` capability guide 为准。
239
239
 
240
- ```bash
241
- forgerelay agents ls
242
- forgerelay agents run <profile-or-provider-or-id> "<prompt>"
243
- forgerelay agents show <id>
244
- ```
245
-
246
- A first-class MCP subagent interface is planned so this CLI indirection can be
247
- removed.
240
+ `forgerelay agents` CLI 继续保留给本地诊断和兼容场景,但 first-class MCP 路径不会通过 `bash -> forgerelay agents ...` 间接执行。Subagent Session 绑定实际 Execution Workspace,provider 原生 session/thread 保存 conversation history,ForgeRelay 只持久化必要的 ownership、continuation 和当前执行协调元数据。
248
241
 
249
242
  ## Tool modes
250
243
 
@@ -305,6 +305,25 @@ switching a logical workspace therefore does not by itself cause unchanged proje
305
305
  context to be injected again, while changed context produces a new fingerprint and
306
306
  is delivered on the next `auto` open.
307
307
 
308
+ Composite Workspaces use the same `open_workspace` entry point with
309
+ `kind="composite"` and a human-readable `name`. They have no filesystem root of
310
+ their own and may contain zero or more named members. Member management also stays
311
+ on `open_workspace` through `action="member"`; an added member either references an
312
+ existing `workspaceId` or reuses the normal local/managed/relay Workspace open
313
+ definition (`path`, optional `relay`, `mode`, and worktree options). Every Composite
314
+ open returns its `kind`, name, and member purposes regardless of
315
+ `context="auto"|"full"|"none"`. To receive one member's heavy project bootstrap,
316
+ reopen the Composite with `memberName=<name>`; this does not create an implicit
317
+ current member. Core work calls against a Composite require an explicit `member`
318
+ and retain the `cws_...` ID as the Host-facing Workspace identity.
319
+
320
+ Composite member purpose text is descriptive only. ForgeRelay never routes by tool
321
+ type, hardware role, load, or availability, and a missing/offline member never falls
322
+ back to another member or local execution. Member filesystems, Git state, processes,
323
+ Hooks, Skills, language services, and Activity facts remain owned by the underlying
324
+ Workspace. The Composite Activity Panel only aggregates their presentation into one
325
+ Host Turn.
326
+
308
327
  Use `open_workspace(action="list")` only when the Agent needs to continue an older
309
328
  logical workspace, choose among multiple handles, or organize workspace state. The
310
329
  inventory is paginated (50 records by default, at most 100) and can filter by
@@ -321,6 +340,10 @@ or externally removed managed-worktree root can therefore remain diagnostically
321
340
  files. For a managed-worktree-backed workspace, `close_workspace` requires
322
341
  `commitMessage` and runs the existing safe worktree finalize lifecycle: close Hooks,
323
342
  commit when needed, fast-forward-only integration, cleanup, and alias invalidation.
343
+ For a Composite Workspace, the same tool means dissolve: it removes only the
344
+ Composite identity, membership, and Composite-facing panel/lifecycle state. It does
345
+ not close members, finalize member worktrees, interrupt member processes, delete
346
+ files, or remove remote registrations and relayed Workspace routes.
324
347
 
325
348
  Hot workspace/session activity timestamps are coalesced in memory and flushed to the
326
349
  SQLite state database in a transaction at most every five minutes; normal shutdown
package/docs/debugging.md CHANGED
@@ -50,6 +50,13 @@ To relocate the entire interactive debug config explicitly, use:
50
50
  FORGERELAY_DEBUG_CONFIG_DIR=/path/to/debug-config npm run dev
51
51
  ```
52
52
 
53
+ The selected debug config is authoritative for its own `host` and `port`; the
54
+ launcher reports endpoints derived from that file instead of assuming `7677`.
55
+ This makes parallel isolated instances straightforward: give each instance its
56
+ own config, state, and worktree directories and configure different ports (for
57
+ example `7677` for a Gateway and `6768` for an Execution ForgeRelay), then launch
58
+ each with its own `FORGERELAY_DEBUG_CONFIG_DIR`.
59
+
53
60
  ## Run a local MCP Apps Host
54
61
 
55
62
  Use MCP Inspector as the fast local Host for MCP App/resource iteration:
package/docs/roadmap.md CHANGED
@@ -250,16 +250,51 @@ fake-LSP coverage remains the primary cross-platform protocol/lifecycle gate, wh
250
250
  `rust-analyzer`, `gopls`, and `clangd` only when those external executables are
251
251
  already present and otherwise reports explicit skips without installing them.
252
252
 
253
- ## 0.5 — First-class subagent MCP
253
+ ## 0.5 — Durable Activity and batch execution
254
254
 
255
- ForgeRelay already owns provider adapters and resumable local agent sessions.
256
- The next step is to remove the current `bash -> forgerelay agents ...` indirection
257
- for MCP hosts.
255
+ 0.5 established the execution-history substrate used by the later MCP App and
256
+ multi-workspace features:
257
+
258
+ - immutable local Audit Events and restart-safe Activity Records;
259
+ - durable Bash output plus late `bash_result` delivery;
260
+ - Host Turn snapshots with lazy detail/output queries for MCP Apps;
261
+ - native bulk read/edit/delete and heterogeneous `batch.execute` orchestration;
262
+ - parent/child Activity relationships and bounded capability batch policies;
263
+ - Windows-safe Activity/SQLite cleanup and release-test hardening.
264
+
265
+ Activity remains an observation of semantic ForgeRelay operations rather than a
266
+ second task/session runtime. Files, processes, Git state, and audit truth continue
267
+ to belong to the Workspace that actually executes the operation.
268
+
269
+ ## 0.6 — Host UI, Workspace Relay, and Composite Workspace
270
+
271
+ 0.6 turned the Activity substrate into a Host-facing multi-environment workflow:
258
272
 
259
- First-class subagent operations should reuse the Capability Gateway established in 0.3 rather than add another top-level MCP tool. The exact registered names, action semantics and provider/session contract remain 0.5 design work. The parent agent will continue choosing from available provider/profile metadata while ForgeRelay owns provider-backed worker lifecycle state.
273
+ - **0.6.0** one ForgeRelay Panel per Host Turn, MCP Inspector/debug lifecycle,
274
+ virtual `skills://` loading, bounded process waits, and release-candidate support;
275
+ - **0.6.1** — Workspace Relay, authenticated direct/SSH-routed remote execution,
276
+ restart-safe relay identity/routes, and remote Activity/bootstrap forwarding;
277
+ - **0.6.2** — Composite Workspace as a first-class Workspace kind with named local,
278
+ managed-worktree, and relayed members, explicit member routing, aggregated
279
+ Composite Activity, and `close_workspace` dissolution that preserves members.
280
+
281
+ The 0.6 contract keeps execution ownership explicit: Gateway ForgeRelay presents
282
+ and routes; the selected member Workspace and its Execution ForgeRelay own files,
283
+ Git state, processes, Hooks, Skills, Language services, Activity, and Audit facts.
284
+ Workspace Relay is not file synchronization or failover, and Composite Workspace
285
+ never silently chooses a member.
286
+
287
+ ## Later: first-class subagent MCP
288
+
289
+ ForgeRelay already owns provider adapters and resumable local agent sessions. A
290
+ future release may remove the current `bash -> forgerelay agents ...` indirection
291
+ for MCP hosts.
260
292
 
261
- This is intentionally provider-backed delegation, not an attempt to emulate a
262
- host-native subagent implementation.
293
+ First-class subagent operations should reuse the Capability Gateway rather than
294
+ add another top-level MCP tool. The parent agent should continue choosing from
295
+ available provider/profile metadata while ForgeRelay owns provider-backed worker
296
+ lifecycle state. This remains provider-backed delegation, not an attempt to
297
+ emulate a Host-native subagent implementation.
263
298
 
264
299
  ## Worktree and history refinements
265
300
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akira-tl/forgerelay",
3
- "version": "0.6.1",
3
+ "version": "0.7.1",
4
4
  "description": "Local development control plane for MCP coding agents.",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/Akira-TL/forgerelay#readme",
@@ -47,7 +47,7 @@
47
47
  "release:publish": "node scripts/release/publish.mjs",
48
48
  "postinstall": "node scripts/fix-node-pty-permissions.mjs",
49
49
  "start": "node dist/cli.js serve",
50
- "test": "node --test scripts/debug/runtime.test.mjs scripts/release-proof.test.mjs scripts/release/release-gate.test.mjs scripts/release/release-version.test.mjs && tsx src/oauth/router.test.ts && tsx src/remote-auth-cli.test.ts && tsx src/remote-ssh-auth-cli.test.ts && tsx src/remote-workspace-relay.test.ts && tsx src/remote-workspace-relay-process.test.ts && tsx src/config.test.ts && tsx src/lsp/language-server-config.test.ts && tsx src/lsp/normalization/hover.test.ts && tsx src/lsp/references.server.test.ts && tsx src/lsp/operations/document-symbols.server.test.ts && tsx src/lsp/operations/workspace-symbols.server.test.ts && tsx src/lsp/operations/diagnostics-push.server.test.ts && tsx src/lsp/operations/diagnostics-pull.server.test.ts && tsx src/lsp/operations/request-hardening.server.test.ts && tsx src/lsp/operations/recovery.server.test.ts && tsx src/lsp/operations/lifecycle.server.test.ts && tsx src/lsp/runtime/semantic-requests.test.ts && tsx src/logger.test.ts && tsx src/proxy-trust.test.ts && tsx src/mcp-app-template.test.ts && tsx src/hooks.test.ts && tsx src/capability-registry.test.ts && tsx src/mcp/server-instructions.test.ts && tsx src/request-meta.test.ts && tsx src/incoming-artifacts.test.ts && tsx src/artifact-download.test.ts && tsx src/ui/card-types.test.ts && tsx src/ui/workspace-lifecycle-app.test.ts && tsx src/ui/activity/model.test.ts && tsx src/ui/patch-display.test.ts && tsx src/ui/tool-display.test.ts && tsx src/apply-patch.test.ts && tsx src/process-platform.test.ts && tsx src/process-sessions.test.ts && tsx src/mcp-sessions.test.ts && tsx src/server-shutdown.test.ts && tsx src/local-agent-runtime.test.ts && tsx src/local-agent-adapters.test.ts && tsx src/local-agent-availability.test.ts && tsx src/local-agent-profiles.test.ts && tsx src/local-agent-targets.test.ts && tsx src/local-agent-store.test.ts && tsx src/roots.test.ts && tsx src/file-mutations.test.ts && tsx src/operations/edit-preflight.test.ts && tsx src/skills.test.ts && tsx src/db/migrations.test.ts && tsx src/workspace-store.test.ts && tsx src/activity/audit-store.test.ts && tsx src/activity/bash-output-store.test.ts && tsx src/activity/lifecycle.test.ts && tsx src/activity/query-service.test.ts && tsx src/operations/core-operation-executor.test.ts && tsx src/operations/bulk-mutation.test.ts && tsx src/operations/batch/scheduler.test.ts && tsx src/operations/batch/executor-policy.test.ts && tsx src/workspaces.test.ts && tsx src/workspace-conversation.test.ts && tsx src/review-checkpoints.test.ts && tsx src/lsp/code-intelligence.server.test.ts && npm run build:app && tsx src/server.test.ts && tsx src/oauth-store.test.ts && tsx src/cli.test.ts",
50
+ "test": "node --test scripts/debug/runtime.test.mjs scripts/release-proof.test.mjs scripts/release/release-gate.test.mjs scripts/release/release-version.test.mjs && tsx src/oauth/router.test.ts && tsx src/remote-auth-cli.test.ts && tsx src/remote-ssh-auth-cli.test.ts && tsx src/remote-workspace-relay.test.ts && tsx src/remote-workspace-relay-process.test.ts && tsx src/config.test.ts && tsx src/lsp/language-server-config.test.ts && tsx src/lsp/normalization/hover.test.ts && tsx src/lsp/references.server.test.ts && tsx src/lsp/operations/document-symbols.server.test.ts && tsx src/lsp/operations/workspace-symbols.server.test.ts && tsx src/lsp/operations/diagnostics-push.server.test.ts && tsx src/lsp/operations/diagnostics-pull.server.test.ts && tsx src/lsp/operations/request-hardening.server.test.ts && tsx src/lsp/operations/recovery.server.test.ts && tsx src/lsp/operations/lifecycle.server.test.ts && tsx src/lsp/runtime/semantic-requests.test.ts && tsx src/logger.test.ts && tsx src/proxy-trust.test.ts && tsx src/mcp-app-template.test.ts && tsx src/hooks.test.ts && tsx src/capability-registry.test.ts && tsx src/mcp/server-instructions.test.ts && tsx src/request-meta.test.ts && tsx src/incoming-artifacts.test.ts && tsx src/artifact-download.test.ts && tsx src/ui/card-types.test.ts && tsx src/ui/workspace-lifecycle-app.test.ts && tsx src/ui/activity/model.test.ts && tsx src/ui/patch-display.test.ts && tsx src/ui/tool-display.test.ts && tsx src/apply-patch.test.ts && tsx src/process-platform.test.ts && tsx src/process-sessions.test.ts && tsx src/mcp-sessions.test.ts && tsx src/server-shutdown.test.ts && tsx src/subagents/providers/adapters/codex.test.ts && tsx src/subagents/providers/registry.test.ts && tsx src/subagents/providers/availability.test.ts && tsx src/subagents/profiles.test.ts && tsx src/subagents/cli-target.test.ts && tsx src/subagents/sessions/store.test.ts && tsx src/subagents/sessions/manager.test.ts && tsx src/subagents/sessions/mcp/capability.server.test.ts && tsx src/subagents/sessions/mcp/continuation.server.test.ts && tsx src/roots.test.ts && tsx src/file-mutations.test.ts && tsx src/operations/edit-preflight.test.ts && tsx src/skills.test.ts && tsx src/db/migrations.test.ts && tsx src/workspace-store.test.ts && tsx src/activity/audit-store.test.ts && tsx src/activity/bash-output-store.test.ts && tsx src/activity/lifecycle.test.ts && tsx src/activity/query-service.test.ts && tsx src/operations/core-operation-executor.test.ts && tsx src/operations/bulk-mutation.test.ts && tsx src/operations/batch/scheduler.test.ts && tsx src/operations/batch/executor-policy.test.ts && tsx src/workspaces.test.ts && tsx src/workspace-conversation.test.ts && tsx src/review-checkpoints.test.ts && tsx src/lsp/code-intelligence.server.test.ts && npm run build:app && tsx src/server.test.ts && tsx src/oauth-store.test.ts && tsx src/cli.test.ts",
51
51
  "typecheck": "tsc -p tsconfig.json --noEmit",
52
52
  "release:check": "node scripts/release-version.mjs check",
53
53
  "release:tag-check": "node scripts/release-version.mjs tag",
@@ -22,6 +22,27 @@ export function interactiveDebugConfigDir({ env = process.env, home = homedir()
22
22
  return resolve(join(home, ".forgerelay", "debug"));
23
23
  }
24
24
 
25
+ export function interactiveDebugUrls(configDir) {
26
+ let config = {};
27
+ try {
28
+ config = JSON.parse(readFileSync(join(configDir, "config.json"), "utf8"));
29
+ } catch {
30
+ // Keep the historical debug defaults when the selected config has not been created yet.
31
+ }
32
+ const configuredHost = typeof config.host === "string" && config.host.trim()
33
+ ? config.host.trim()
34
+ : "127.0.0.1";
35
+ const host = configuredHost === "0.0.0.0" || configuredHost === "::"
36
+ ? "127.0.0.1"
37
+ : configuredHost;
38
+ const port = Number.isInteger(config.port) && config.port > 0 && config.port <= 65_535
39
+ ? config.port
40
+ : 7677;
41
+ const displayHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
42
+ const baseUrl = `http://${displayHost}:${port}`;
43
+ return { baseUrl, mcpUrl: `${baseUrl}/mcp` };
44
+ }
45
+
25
46
  function interactiveDebugOwnerToken(configDir) {
26
47
  const authPath = join(configDir, "auth.json");
27
48
  let auth;
@@ -45,6 +66,7 @@ export function createInteractiveDebugEnvironment({
45
66
  } = {}) {
46
67
  const configDir = interactiveDebugConfigDir({ env, home });
47
68
  const ownerToken = interactiveDebugOwnerToken(configDir);
69
+ const { baseUrl, mcpUrl } = interactiveDebugUrls(configDir);
48
70
  mkdirSync(debugRoot, { recursive: true });
49
71
 
50
72
  const debugEnv = { ...env };
@@ -67,7 +89,7 @@ export function createInteractiveDebugEnvironment({
67
89
  }
68
90
  debugEnv.FORGERELAY_CONFIG_DIR = configDir;
69
91
 
70
- return { ownerToken, configDir, env: debugEnv };
92
+ return { ownerToken, configDir, baseUrl, mcpUrl, env: debugEnv };
71
93
  }
72
94
 
73
95
  export function createDebugEnvironment({
@@ -4,7 +4,11 @@ import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import test from "node:test";
6
6
 
7
- import { createInteractiveDebugEnvironment, interactiveDebugConfigDir } from "./runtime.mjs";
7
+ import {
8
+ createInteractiveDebugEnvironment,
9
+ interactiveDebugConfigDir,
10
+ interactiveDebugUrls,
11
+ } from "./runtime.mjs";
8
12
 
9
13
  async function withDebugConfig(t) {
10
14
  const home = await mkdtemp(join(tmpdir(), "forgerelay-interactive-debug-"));
@@ -45,6 +49,12 @@ test("interactive debug uses one dedicated persisted config under ~/.forgerelay/
45
49
  assert.equal(result.ownerToken, "debug-owner-password-123456");
46
50
  assert.equal(result.configDir, configDir);
47
51
  assert.equal(result.env.FORGERELAY_CONFIG_DIR, configDir);
52
+ assert.equal(result.baseUrl, "http://127.0.0.1:7677");
53
+ assert.equal(result.mcpUrl, "http://127.0.0.1:7677/mcp");
54
+ assert.deepEqual(interactiveDebugUrls(configDir), {
55
+ baseUrl: "http://127.0.0.1:7677",
56
+ mcpUrl: "http://127.0.0.1:7677/mcp",
57
+ });
48
58
  assert.equal(result.env.HOST, undefined);
49
59
  assert.equal(result.env.PORT, undefined);
50
60
  assert.equal(result.env.FORGERELAY_PUBLIC_BASE_URL, undefined);
@@ -60,7 +70,7 @@ test("interactive debug config directory may be explicitly relocated without fal
60
70
  const { home } = await withDebugConfig(t);
61
71
  const customDir = join(home, "custom-debug-config");
62
72
  await mkdir(customDir, { recursive: true });
63
- await writeFile(join(customDir, "config.json"), "{}\n");
73
+ await writeFile(join(customDir, "config.json"), JSON.stringify({ host: "127.0.0.1", port: 6768 }) + "\n");
64
74
  await writeFile(join(customDir, "auth.json"), JSON.stringify({ ownerToken: "custom-debug-password-123456" }) + "\n");
65
75
 
66
76
  const result = createInteractiveDebugEnvironment({
@@ -71,4 +81,6 @@ test("interactive debug config directory may be explicitly relocated without fal
71
81
  assert.equal(result.configDir, customDir);
72
82
  assert.equal(result.ownerToken, "custom-debug-password-123456");
73
83
  assert.equal(result.env.FORGERELAY_CONFIG_DIR, customDir);
84
+ assert.equal(result.baseUrl, "http://127.0.0.1:6768");
85
+ assert.equal(result.mcpUrl, "http://127.0.0.1:6768/mcp");
74
86
  });
@@ -1,12 +1,12 @@
1
1
  import { spawn } from "node:child_process";
2
- import { createInteractiveDebugEnvironment, debugBaseUrl, debugMcpUrl, repoRoot } from "./runtime.mjs";
2
+ import { createInteractiveDebugEnvironment, repoRoot } from "./runtime.mjs";
3
3
 
4
- const { configDir, env } = createInteractiveDebugEnvironment();
4
+ const { configDir, baseUrl, mcpUrl, env } = createInteractiveDebugEnvironment();
5
5
 
6
6
  console.error("[forgerelay:debug] local debug server");
7
7
  console.error(`[forgerelay:debug] debug config: ${configDir}/config.json`);
8
- console.error(`[forgerelay:debug] health: ${debugBaseUrl}/healthz`);
9
- console.error(`[forgerelay:debug] MCP: ${debugMcpUrl}`);
8
+ console.error(`[forgerelay:debug] health: ${baseUrl}/healthz`);
9
+ console.error(`[forgerelay:debug] MCP: ${mcpUrl}`);
10
10
  console.error(`[forgerelay:debug] Owner password loaded from ${configDir}/auth.json`);
11
11
  console.error("[forgerelay:debug] all runtime state is under .forgerelay-debug/");
12
12
 
@@ -79,7 +79,7 @@ test("release runtime and local parity share the checked-in Node contract", asyn
79
79
  test("cloud verification produces one reusable npm package on Linux", async () => {
80
80
  const workflow = await readFile(resolve(repoRoot, ".github/workflows/ci.yml"), "utf8");
81
81
  assert.match(workflow, /if:\s*runner\.os == 'Linux'[\s\S]*run:\s*npm run release:pack/);
82
- assert.match(workflow, /uses:\s*actions\/upload-artifact@v4/);
82
+ assert.match(workflow, /uses:\s*actions\/upload-artifact@v7/);
83
83
  assert.match(workflow, /name:\s*npm-package/);
84
84
  assert.match(workflow, /include-hidden-files:\s*true/);
85
85
  assert.match(workflow, /overwrite:\s*true/);
@@ -89,7 +89,7 @@ test("release workflow is tag-only and promotes the verified npm artifact withou
89
89
  const workflow = await readFile(resolve(repoRoot, ".github/workflows/release.yml"), "utf8");
90
90
  assert.doesNotMatch(workflow, /workflow_dispatch:/);
91
91
  assert.match(workflow, /needs:\s*verify/);
92
- assert.match(workflow, /uses:\s*actions\/download-artifact@v5/);
92
+ assert.match(workflow, /uses:\s*actions\/download-artifact@v7/);
93
93
  assert.match(workflow, /name:\s*npm-package/);
94
94
  assert.match(workflow, /run:\s*npm run release:publish/);
95
95
  assert.match(workflow, /npm install --global npm@11\.19\.1/);