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: 20aaf646a8056b8d5975cb789f55a49f9f9c0ca5deca38f9866a0e3e220e8904
4
- data.tar.gz: a89104abc977aaeae263c09f922800252867df448050262c557d6f60780275f0
3
+ metadata.gz: e170b3f69d5b2a6bdeb9422aedc341df20148e7085ea38b120b43508a9aaf3d0
4
+ data.tar.gz: 8ed8737fdeacf88a4ef1917fcf2a695e3d7f6f679eb1c6745094179bf57a8166
5
5
  SHA512:
6
- metadata.gz: f0a104ab6b75ec7170e5c4bc7a57c4406f002e167ba13b3d913d21a97f3c020a13d3912d2f2fada42edcd0ffeac876a8fdff2fe0c38ad163f617700927767493
7
- data.tar.gz: ea287608ae6cb4a560d3b38e51e4d8b0c3d4dc04985e429046fe83b1588c8f7dd34608a7ede28ed45457ff8e0456226d4130ddfb6b9541dde875cc3976898a1b
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 { |j| [j["id"], j["status"], j["run_id"], j["created_at"]] }
888
- terminal.say terminal.table(%w[ID Status RunID CreatedAt], rows)
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. Unlike that emitter, this one does
7
- # NOT wrap the invocation in mise/ruby toolchain resolution: the
8
- # `architect` executable is a rubygems binstub (or the dev exe/architect
9
- # script, which sets up Bundler itself) and needs no toolchain pinning to
10
- # run non-interactively, so ProgramArguments invokes it directly.
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"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Space
4
4
  module Core
5
- VERSION = "5.4.0"
5
+ VERSION = "5.5.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: space-architect
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.4.0
4
+ version: 5.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Jacobs