space-architect 5.4.0 → 5.5.0
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.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e170b3f69d5b2a6bdeb9422aedc341df20148e7085ea38b120b43508a9aaf3d0
|
|
4
|
+
data.tar.gz: 8ed8737fdeacf88a4ef1917fcf2a695e3d7f6f679eb1c6745094179bf57a8166
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '059f2419d80fc974f33c66367f9bc3a3c58492ed095d155c7e9aaa07c0c127ef374e236a973dd21c635e0c2eea97f62fafe83e66c03f8c3a6f5109f4745c20c3'
|
|
7
|
+
data.tar.gz: 2ee62770684237d0f60eedc5e752695846ff9dfd95836876b555e94e68683bc1ec4367a2006ea35fb350313b568a1d81d6a13822dea4747364f4710688984002
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,75 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [5.5.0] - 2026-07-22
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`architect jobs list` provenance columns** — the table gains Harness /
|
|
13
|
+
Model / Lane (sourced from the list JSON's existing fields), blank when an
|
|
14
|
+
older row lacks them, so parallel lanes are tellable apart at a glance.
|
|
15
|
+
- **Server: pagination on the jobs, runs, and conversations indexes** — 50
|
|
16
|
+
rows per page with a `?page=N` param and Prev/Next controls; runs and
|
|
17
|
+
conversations were previously unbounded fetches. Conversations order
|
|
18
|
+
newest-updated first, and the index still never loads messages.
|
|
19
|
+
- **Server: job re-run prefill** — `GET /jobs/new?from=<job id>` (owner-gated)
|
|
20
|
+
prefills the new-job form field-for-field from that job's spec via the same
|
|
21
|
+
mapping profile application uses; Jobs/Show gains a "Run again" link.
|
|
22
|
+
- **Server: embedded live run view** — the run stream (SSE + rendering) is
|
|
23
|
+
extracted into a shared `RunStream` component and embedded on Jobs/Show
|
|
24
|
+
whenever the job has a run, so watching a job live no longer requires
|
|
25
|
+
leaving the job page.
|
|
26
|
+
- **Server: browser cancel + honest canceled lifecycle** — Jobs/Show renders a
|
|
27
|
+
Cancel control while a job is queued/running; runs gain a distinct terminal
|
|
28
|
+
status `canceled(4)` (a canceled job's run no longer reports `failed`), and
|
|
29
|
+
a cancel arriving during the env-image build skips the container spawn (and
|
|
30
|
+
secret resolution) entirely.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- **`architect sessions agent install` emits a launchd-proof plist** — the
|
|
35
|
+
agent's ProgramArguments now open with the installing interpreter's absolute
|
|
36
|
+
ruby path (`RbConfig.ruby`) ahead of the absolute bin path, and the agent
|
|
37
|
+
environment carries a homebrew-inclusive PATH, so launchd's bare PATH can no
|
|
38
|
+
longer resolve macOS system Ruby via an env shebang (LoadError, agent exit
|
|
39
|
+
1). Reinstall existing agents to migrate; wrapper-script workarounds are
|
|
40
|
+
obsolete.
|
|
41
|
+
- **`architect dispatch --as-job` requires `--job-model`** — the missing model
|
|
42
|
+
now fails fast at dispatch with an error naming the flag, instead of
|
|
43
|
+
composing a spec the server rejects with a late 422.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- **Server: bulk session syncs no longer strand conversations at pending** —
|
|
48
|
+
transient DB-infrastructure errors (pool timeout, connection loss) inside an
|
|
49
|
+
import now re-raise so the queue's retry re-fires them, instead of being
|
|
50
|
+
swallowed as permanent failures; import concurrency is bounded below the DB
|
|
51
|
+
connection pool so a bulk backfill can't starve it.
|
|
52
|
+
- **Server: NUL bytes can no longer fail imports or live persists** — one
|
|
53
|
+
shared scrub now covers the claude_code, codex, and pi importers and the
|
|
54
|
+
live run persistor (Postgres jsonb rejects NUL outright;
|
|
55
|
+
`PG::UntranslatableCharacter` was failing real claude_code transcripts with
|
|
56
|
+
NUL in tool-block content).
|
|
57
|
+
- **Server: executor hardening** — a requeued job's raw Redis stream is
|
|
58
|
+
deleted at execution start (a surviving stale stream silently corrupted the
|
|
59
|
+
transcript); truncated failure evidence is scrubbed back to valid UTF-8 when
|
|
60
|
+
the byte boundary splits a multibyte character; the default sandbox base
|
|
61
|
+
image is `space-claude-base:v1` everywhere (dev bins previously defaulted to
|
|
62
|
+
`debian:stable-slim`).
|
|
63
|
+
- **Server: models-proxy timeout covers key resolution** — `op://` key
|
|
64
|
+
resolution now runs inside the same 10s budget as the upstream fetch, and
|
|
65
|
+
the providers/models action only rescues the operation's own failure
|
|
66
|
+
classes, so genuine bugs propagate instead of masquerading as
|
|
67
|
+
`upstream_error`.
|
|
68
|
+
- **Server: `parent_session_id` is clearable** — a re-import whose content no
|
|
69
|
+
longer implies a parent now nulls the stored link instead of preserving it
|
|
70
|
+
forever.
|
|
71
|
+
- **Server: theme-aware transcript turn bands** — per-turn tint colors ride
|
|
72
|
+
CSS custom properties with light and dark definitions (bands were
|
|
73
|
+
dark-calibrated and near-invisible in light mode); a mid-fetch form edit no
|
|
74
|
+
longer gets clobbered by the pi-extension sync on the job/profile forms; the
|
|
75
|
+
generated pi extension places `compat` per-model per the upstream types.
|
|
76
|
+
|
|
8
77
|
## [5.4.0] - 2026-07-21
|
|
9
78
|
|
|
10
79
|
### Changed
|
|
@@ -939,6 +939,7 @@ module Space::Architect
|
|
|
939
939
|
resolve_dispatch_harness(lane_entry, model: model, harness: harness, effort: effort, force: force, err: err)
|
|
940
940
|
raise Space::Core::Error, "--as-job only supports the claude-code harness (lane '#{lane}' resolves to '#{resolved_harness}')" \
|
|
941
941
|
unless resolved_harness == "claude-code"
|
|
942
|
+
raise Space::Core::Error, "--job-model is required with --as-job" unless job_model
|
|
942
943
|
|
|
943
944
|
id = iteration_id(entry)
|
|
944
945
|
wt_path = space.path.join(lane_entry["worktree"] || "build/#{id}-#{lane}/wt")
|
|
@@ -349,6 +349,7 @@ module Space::Architect
|
|
|
349
349
|
if as_job
|
|
350
350
|
Jobs.require_credentials!(host, token)
|
|
351
351
|
raise Space::Core::Error, "--backend-url is required with --as-job" unless backend_url
|
|
352
|
+
raise Space::Core::Error, "--job-model is required with --as-job" unless job_model
|
|
352
353
|
raise Space::Core::Error, "--as-job cannot be combined with --push-url/--push-token/--push-host/--detach" \
|
|
353
354
|
if push_url || push_token || push_host || detach
|
|
354
355
|
end
|
|
@@ -884,8 +885,11 @@ module Space::Architect
|
|
|
884
885
|
if jobs.empty?
|
|
885
886
|
terminal.say "No jobs"
|
|
886
887
|
else
|
|
887
|
-
rows = jobs.map
|
|
888
|
-
|
|
888
|
+
rows = jobs.map do |j|
|
|
889
|
+
[j["id"], j["status"], j["run_id"], j["created_at"],
|
|
890
|
+
j["harness"], j["model"], j.dig("provenance", "lane")]
|
|
891
|
+
end
|
|
892
|
+
terminal.say terminal.table(%w[ID Status RunID CreatedAt Harness Model Lane], rows)
|
|
889
893
|
end
|
|
890
894
|
CLI.record_outcome(Outcome.new(exit_code: 0))
|
|
891
895
|
end
|
|
@@ -1012,6 +1016,7 @@ module Space::Architect
|
|
|
1012
1016
|
refresh_interval: interval.to_i,
|
|
1013
1017
|
log_dir: SessionSync.log_dir,
|
|
1014
1018
|
bin_path: SessionSync::BinPath.detect,
|
|
1019
|
+
ruby_bin: RbConfig.ruby,
|
|
1015
1020
|
host: host,
|
|
1016
1021
|
env: {SessionSync::TOKEN_ENV => resolved_token}
|
|
1017
1022
|
)
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
module Space::Architect
|
|
4
4
|
module SessionSync
|
|
5
5
|
# Hand-rolled launchd plist emitter for the session-sync agent, imitating
|
|
6
|
-
# Space::Src::Launchd::Plist's shape.
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
6
|
+
# Space::Src::Launchd::Plist's shape. Under launchd's bare PATH, a bare
|
|
7
|
+
# env-relative ruby binstub shebang resolves to macOS system Ruby instead
|
|
8
|
+
# of the caller's toolchain, so ProgramArguments names the interpreter
|
|
9
|
+
# explicitly (ruby_bin) rather than relying on shebang resolution — no
|
|
10
|
+
# mise wrapping needed, since the sync itself pins no toolchain at run
|
|
11
|
+
# time.
|
|
11
12
|
class Plist
|
|
13
|
+
DEFAULT_PATH = "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
|
|
14
|
+
|
|
12
15
|
HEADER = <<~XML
|
|
13
16
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
14
17
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -22,15 +25,17 @@ module Space::Architect
|
|
|
22
25
|
# @param refresh_interval [Integer] StartInterval in seconds (must be > 0).
|
|
23
26
|
# @param log_dir [String] Absolute directory for stdout/stderr logs.
|
|
24
27
|
# @param bin_path [String] Absolute path to the architect bin script.
|
|
28
|
+
# @param ruby_bin [String] Absolute path to the ruby to run bin_path under.
|
|
25
29
|
# @param host [String] --host value passed to `sessions sync`.
|
|
26
30
|
# @param env [Hash] EnvironmentVariables dict; must contain a non-empty
|
|
27
31
|
# SessionSync::TOKEN_ENV value (resolved by the caller —
|
|
28
|
-
# never resolved here).
|
|
32
|
+
# never resolved here). PATH defaults to DEFAULT_PATH
|
|
33
|
+
# unless the caller supplies its own.
|
|
29
34
|
# @return [String] the full plist XML.
|
|
30
|
-
def call(label:, refresh_interval:, log_dir:, bin_path:, host:, env:)
|
|
35
|
+
def call(label:, refresh_interval:, log_dir:, bin_path:, ruby_bin:, host:, env:)
|
|
31
36
|
raise ArgumentError, "label is required" if label.to_s.empty?
|
|
32
37
|
raise ArgumentError, "refresh_interval must be > 0" unless refresh_interval.is_a?(Integer) && refresh_interval > 0
|
|
33
|
-
%w[log_dir bin_path].each do |k|
|
|
38
|
+
%w[log_dir bin_path ruby_bin].each do |k|
|
|
34
39
|
v = binding.local_variable_get(k)
|
|
35
40
|
raise ArgumentError, "#{k} must be absolute (got #{v.inspect})" unless v.is_a?(String) && File.absolute_path?(v)
|
|
36
41
|
end
|
|
@@ -43,12 +48,13 @@ module Space::Architect
|
|
|
43
48
|
body = +""
|
|
44
49
|
body << key("Label") << string(label) << "\n"
|
|
45
50
|
body << key("ProgramArguments") << "\n" << array([
|
|
51
|
+
ruby_bin,
|
|
46
52
|
bin_path,
|
|
47
53
|
"sessions",
|
|
48
54
|
"sync",
|
|
49
55
|
"--host", host
|
|
50
56
|
])
|
|
51
|
-
body << key("EnvironmentVariables") << "\n" << dict(env)
|
|
57
|
+
body << key("EnvironmentVariables") << "\n" << dict({"PATH" => DEFAULT_PATH}.merge(env.to_h))
|
|
52
58
|
body << key("StartInterval") << integer(refresh_interval) << "\n"
|
|
53
59
|
body << key("RunAtLoad") << boolean(true) << "\n"
|
|
54
60
|
body << key("ProcessType") << string("Background") << "\n"
|
data/lib/space_core/version.rb
CHANGED