space-architect 1.3.0 → 2.0.0.rc1
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 +4 -4
- data/CHANGELOG.md +103 -0
- data/README.md +248 -155
- data/exe/architect +1 -1
- data/exe/space +2 -2
- data/exe/src +13 -0
- data/lib/space_architect/architect_mission.rb +84 -53
- data/lib/space_architect/cli/architect.rb +92 -132
- data/lib/space_architect/cli/research.rb +94 -0
- data/lib/space_architect/cli/space.rb +25 -31
- data/lib/space_architect/cli/src.rb +20 -14
- data/lib/space_architect/cli.rb +22 -22
- data/lib/space_architect/dispatcher.rb +5 -1
- data/lib/space_architect/harness.rb +123 -16
- data/lib/space_architect/research/mux.rb +127 -0
- data/lib/space_architect/research/registry.rb +70 -0
- data/lib/space_architect/research/renderer.rb +101 -0
- data/lib/space_architect/research/run.rb +7 -0
- data/lib/space_architect/research/supervisor.rb +108 -0
- data/lib/space_architect/research.rb +13 -0
- data/lib/space_architect/run_creator.rb +53 -0
- data/lib/space_architect/skill_installer.rb +81 -79
- data/lib/space_architect.rb +5 -20
- data/lib/{space_architect → space_core}/atomic_write.rb +1 -1
- data/lib/space_core/cli/base_command.rb +19 -0
- data/lib/space_core/cli/config.rb +49 -0
- data/lib/space_core/cli/current.rb +16 -0
- data/lib/space_core/cli/help.rb +110 -0
- data/lib/space_core/cli/helpers.rb +115 -0
- data/lib/space_core/cli/init.rb +29 -0
- data/lib/space_core/cli/list.rb +24 -0
- data/lib/space_core/cli/new.rb +38 -0
- data/lib/space_core/cli/path.rb +16 -0
- data/lib/space_core/cli/repeatable_options.rb +75 -0
- data/lib/space_core/cli/repo.rb +76 -0
- data/lib/space_core/cli/shell.rb +125 -0
- data/lib/space_core/cli/show.rb +21 -0
- data/lib/space_core/cli/status.rb +33 -0
- data/lib/space_core/cli/use.rb +17 -0
- data/lib/space_core/cli.rb +171 -0
- data/lib/{space_architect → space_core}/config.rb +1 -1
- data/lib/{space_architect → space_core}/errors.rb +1 -1
- data/lib/{space_architect → space_core}/git_client.rb +1 -1
- data/lib/{space_architect → space_core}/mise_client.rb +1 -1
- data/lib/{space_architect → space_core}/repo_reference.rb +1 -1
- data/lib/{space_architect → space_core}/repo_resolver.rb +1 -1
- data/lib/{space_architect → space_core}/shell_integration.rb +1 -1
- data/lib/{space_architect → space_core}/slugger.rb +1 -1
- data/lib/{space_architect → space_core}/space.rb +1 -1
- data/lib/{space_architect → space_core}/space_store.rb +12 -12
- data/lib/{space_architect → space_core}/state.rb +1 -1
- data/lib/{space_architect → space_core}/terminal.rb +1 -1
- data/lib/space_core/version.rb +7 -0
- data/lib/{space_architect → space_core}/warnings.rb +1 -1
- data/lib/{space_architect → space_core}/xdg.rb +1 -1
- data/lib/space_core.rb +24 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/clone.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/config.rb +7 -7
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/daemon.rb +46 -30
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/options.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/org.rb +9 -9
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/repo.rb +9 -9
- data/lib/space_src/cli/shell.rb +122 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/status.rb +7 -7
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/sync.rb +17 -17
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli.rb +42 -11
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cloner.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/contract.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/duration.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/model.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/store.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/forge/client.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/forge/github.rb +4 -4
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/launchd/agent.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/launchd/plist.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/log_rotator.rb +1 -1
- data/lib/space_src/migration.rb +43 -0
- data/lib/space_src/nav.rb +98 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/paths.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/client.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/git.rb +4 -4
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/status.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/shell.rb +1 -1
- data/lib/space_src/shell_integration.rb +321 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/state/lock.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/state/store.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/sync/engine.rb +12 -12
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/sync/repo_plan.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/interactive_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/json_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/mode.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/plain_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/version.rb +2 -2
- data/lib/space_src.rb +37 -0
- data/skill/architect/SKILL.md +2 -2
- data/skill/architect/research.md +46 -37
- metadata +115 -67
- data/lib/space_architect/cli/config.rb +0 -61
- data/lib/space_architect/cli/current.rb +0 -22
- data/lib/space_architect/cli/helpers.rb +0 -117
- data/lib/space_architect/cli/init.rb +0 -35
- data/lib/space_architect/cli/list.rb +0 -30
- data/lib/space_architect/cli/new.rb +0 -43
- data/lib/space_architect/cli/options.rb +0 -12
- data/lib/space_architect/cli/path.rb +0 -22
- data/lib/space_architect/cli/repo.rb +0 -88
- data/lib/space_architect/cli/shell.rb +0 -137
- data/lib/space_architect/cli/show.rb +0 -27
- data/lib/space_architect/cli/status.rb +0 -39
- data/lib/space_architect/cli/use.rb +0 -23
- data/lib/space_architect/version.rb +0 -5
- data/vendor/repo-tender/lib/space_architect/pristine.rb +0 -44
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "pathname"
|
|
5
|
+
|
|
6
|
+
module Space::Src
|
|
7
|
+
# Generates the standalone `src` fish shell integration and completions.
|
|
8
|
+
# All paths resolved through Space::Src::Paths (no external core deps).
|
|
9
|
+
module ShellIntegration
|
|
10
|
+
FISH_TEMPLATE = <<~'FISH'
|
|
11
|
+
# Generated by space-src. Do not edit by hand.
|
|
12
|
+
|
|
13
|
+
function src --wraps src --description "Navigate source checkouts"
|
|
14
|
+
if not set -q __src_compat_checked
|
|
15
|
+
set -g __src_compat_checked 1
|
|
16
|
+
set -l __src_installed_version __SRC_VERSION__
|
|
17
|
+
set -l __src_binary_version (command src --version 2>/dev/null)
|
|
18
|
+
if test "$__src_binary_version" != "$__src_installed_version"
|
|
19
|
+
echo "space-src: shell integration version $__src_installed_version does not match binary version $__src_binary_version; re-run 'src shell fish install'" >&2
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
switch "$argv[1]"
|
|
24
|
+
case repo org sync status config daemon clone shell
|
|
25
|
+
command src $argv
|
|
26
|
+
return $status
|
|
27
|
+
case '*'
|
|
28
|
+
set -l __src_output (command src $argv)
|
|
29
|
+
set -l __src_status $status
|
|
30
|
+
|
|
31
|
+
if test (count $__src_output) -gt 0
|
|
32
|
+
printf "%s\n" $__src_output
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if test $__src_status -eq 0
|
|
36
|
+
set -l __src_target $__src_output[-1]
|
|
37
|
+
set __src_target (string replace -r "^~(?=/|$)" $HOME -- $__src_target)
|
|
38
|
+
if test -d "$__src_target"
|
|
39
|
+
cd "$__src_target"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
return $__src_status
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
FISH
|
|
47
|
+
|
|
48
|
+
FISH_COMPLETIONS = <<~'FISH'
|
|
49
|
+
# Generated by space-src. Do not edit by hand.
|
|
50
|
+
|
|
51
|
+
function __src_complete_command
|
|
52
|
+
set -l tokens (commandline -opc)
|
|
53
|
+
set -l index 2
|
|
54
|
+
|
|
55
|
+
while test $index -le (count $tokens)
|
|
56
|
+
set -l token $tokens[$index]
|
|
57
|
+
|
|
58
|
+
switch "$token"
|
|
59
|
+
case "-*"
|
|
60
|
+
set index (math $index + 1)
|
|
61
|
+
continue
|
|
62
|
+
case "*"
|
|
63
|
+
echo $token
|
|
64
|
+
return 0
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
function __src_complete_needs_command
|
|
70
|
+
test -z "(__src_complete_command)"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
function __src_complete_using_command
|
|
74
|
+
contains -- (__src_complete_command) $argv
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
function __src_complete_first_argument_after
|
|
78
|
+
set -l commands $argv
|
|
79
|
+
set -l tokens (commandline -opc)
|
|
80
|
+
set -l index 2
|
|
81
|
+
set -l matched_command 0
|
|
82
|
+
|
|
83
|
+
while test $index -le (count $tokens)
|
|
84
|
+
set -l token $tokens[$index]
|
|
85
|
+
|
|
86
|
+
switch "$token"
|
|
87
|
+
case "-*"
|
|
88
|
+
set index (math $index + 1)
|
|
89
|
+
continue
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
if test $matched_command -eq 0
|
|
93
|
+
if contains -- "$token" $commands
|
|
94
|
+
set matched_command 1
|
|
95
|
+
else
|
|
96
|
+
return 1
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
echo $token
|
|
100
|
+
return 0
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
set index (math $index + 1)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
return 1
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
function __src_complete_has_first_argument_after
|
|
110
|
+
set -q argv[1]; or return 1
|
|
111
|
+
set -l first_argument (__src_complete_first_argument_after $argv)
|
|
112
|
+
test -n "$first_argument"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
function __src_complete_second_argument_after
|
|
116
|
+
set -q argv[1]; or return 1
|
|
117
|
+
set -l command $argv[1]
|
|
118
|
+
set -l tokens (commandline -opc)
|
|
119
|
+
set -l index 2
|
|
120
|
+
set -l matched_command 0
|
|
121
|
+
set -l matched_first_argument 0
|
|
122
|
+
|
|
123
|
+
while test $index -le (count $tokens)
|
|
124
|
+
set -l token $tokens[$index]
|
|
125
|
+
|
|
126
|
+
switch "$token"
|
|
127
|
+
case "-*"
|
|
128
|
+
set index (math $index + 1)
|
|
129
|
+
continue
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
if test $matched_command -eq 0
|
|
133
|
+
test "$token" = "$command"; or return 1
|
|
134
|
+
set matched_command 1
|
|
135
|
+
else if test $matched_first_argument -eq 0
|
|
136
|
+
set matched_first_argument 1
|
|
137
|
+
else
|
|
138
|
+
echo $token
|
|
139
|
+
return 0
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
set index (math $index + 1)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
return 1
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
function __src_complete_has_second_argument_after
|
|
149
|
+
set -q argv[1]; or return 1
|
|
150
|
+
set -l second_argument (__src_complete_second_argument_after $argv)
|
|
151
|
+
test -n "$second_argument"
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
function __src_complete_first_argument_is
|
|
155
|
+
set -q argv[1]; or return 1
|
|
156
|
+
set -l expected $argv[1]
|
|
157
|
+
set -e argv[1]
|
|
158
|
+
test "$(__src_complete_first_argument_after $argv)" = "$expected"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
function __src_complete_checkouts
|
|
162
|
+
command src shell complete checkouts 2>/dev/null
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
function __src_complete_shells
|
|
166
|
+
command src shell complete shells 2>/dev/null
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
complete -c src -f -n "__src_complete_needs_command" -a clone -d "Clone a repo into the source tree"
|
|
170
|
+
complete -c src -f -n "__src_complete_needs_command" -a config -d "Show or update config"
|
|
171
|
+
complete -c src -f -n "__src_complete_needs_command" -a daemon -d "Manage the background sync daemon"
|
|
172
|
+
complete -c src -f -n "__src_complete_needs_command" -a org -d "Manage tracked GitHub orgs"
|
|
173
|
+
complete -c src -f -n "__src_complete_needs_command" -a repo -d "Manage tracked repos"
|
|
174
|
+
complete -c src -f -n "__src_complete_needs_command" -a shell -d "Manage shell integration"
|
|
175
|
+
complete -c src -f -n "__src_complete_needs_command" -a status -d "Show sync status"
|
|
176
|
+
complete -c src -f -n "__src_complete_needs_command" -a sync -d "Sync all tracked repos"
|
|
177
|
+
complete -c src -f -n "__src_complete_needs_command" -a "(__src_complete_checkouts)" -d "Checkout"
|
|
178
|
+
|
|
179
|
+
complete -c src -f -n "__src_complete_using_command config; and not __src_complete_has_first_argument_after config" -a path -d "Print config path"
|
|
180
|
+
complete -c src -f -n "__src_complete_using_command config; and not __src_complete_has_first_argument_after config" -a show -d "Show config"
|
|
181
|
+
|
|
182
|
+
complete -c src -f -n "__src_complete_using_command org; and not __src_complete_has_first_argument_after org" -a add -d "Add a GitHub org"
|
|
183
|
+
complete -c src -f -n "__src_complete_using_command org; and not __src_complete_has_first_argument_after org" -a remove -d "Remove a GitHub org"
|
|
184
|
+
complete -c src -f -n "__src_complete_using_command org; and not __src_complete_has_first_argument_after org" -a list -d "List tracked orgs"
|
|
185
|
+
|
|
186
|
+
complete -c src -f -n "__src_complete_using_command repo; and not __src_complete_has_first_argument_after repo" -a add -d "Add a repo"
|
|
187
|
+
complete -c src -f -n "__src_complete_using_command repo; and not __src_complete_has_first_argument_after repo" -a remove -d "Remove a repo"
|
|
188
|
+
complete -c src -f -n "__src_complete_using_command repo; and not __src_complete_has_first_argument_after repo" -a list -d "List repos"
|
|
189
|
+
|
|
190
|
+
complete -c src -f -n "__src_complete_using_command daemon; and not __src_complete_has_first_argument_after daemon" -a install -d "Install launchd agent"
|
|
191
|
+
complete -c src -f -n "__src_complete_using_command daemon; and not __src_complete_has_first_argument_after daemon" -a uninstall -d "Uninstall launchd agent"
|
|
192
|
+
complete -c src -f -n "__src_complete_using_command daemon; and not __src_complete_has_first_argument_after daemon" -a start -d "Start the agent"
|
|
193
|
+
complete -c src -f -n "__src_complete_using_command daemon; and not __src_complete_has_first_argument_after daemon" -a stop -d "Stop the agent"
|
|
194
|
+
complete -c src -f -n "__src_complete_using_command daemon; and not __src_complete_has_first_argument_after daemon" -a restart -d "Restart the agent"
|
|
195
|
+
complete -c src -f -n "__src_complete_using_command daemon; and not __src_complete_has_first_argument_after daemon" -a status -d "Show agent status"
|
|
196
|
+
|
|
197
|
+
complete -c src -f -n "__src_complete_using_command shell; and not __src_complete_has_first_argument_after shell" -a init -d "Print shell integration"
|
|
198
|
+
complete -c src -f -n "__src_complete_using_command shell; and not __src_complete_has_first_argument_after shell" -a fish -d "Manage fish integration and completions"
|
|
199
|
+
complete -c src -f -n "__src_complete_using_command shell; and not __src_complete_has_first_argument_after shell" -a complete -d "Print completion candidates"
|
|
200
|
+
|
|
201
|
+
complete -c src -f -n "__src_complete_first_argument_is fish shell; and not __src_complete_has_second_argument_after shell" -a install -d "Install fish integration and completions"
|
|
202
|
+
complete -c src -f -n "__src_complete_first_argument_is fish shell; and not __src_complete_has_second_argument_after shell" -a uninstall -d "Remove fish integration and completions"
|
|
203
|
+
complete -c src -f -n "__src_complete_first_argument_is fish shell; and not __src_complete_has_second_argument_after shell" -a path -d "Print fish integration paths"
|
|
204
|
+
|
|
205
|
+
complete -c src -f -n "__src_complete_first_argument_is init shell; and not __src_complete_has_second_argument_after shell" -a "(__src_complete_shells)" -d "Shell"
|
|
206
|
+
complete -c src -f -n "__src_complete_first_argument_is complete shell; and not __src_complete_has_second_argument_after shell" -a "checkouts shells" -d "Completion kind"
|
|
207
|
+
FISH
|
|
208
|
+
|
|
209
|
+
def self.for(shell)
|
|
210
|
+
case shell.to_s
|
|
211
|
+
when "fish"
|
|
212
|
+
FISH_TEMPLATE.gsub("__SRC_VERSION__", Space::Src::VERSION)
|
|
213
|
+
else
|
|
214
|
+
raise "Unsupported shell '#{shell}'. Expected: fish"
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def self.completions_for(shell)
|
|
219
|
+
case shell.to_s
|
|
220
|
+
when "fish"
|
|
221
|
+
FISH_COMPLETIONS
|
|
222
|
+
else
|
|
223
|
+
raise "Unsupported shell '#{shell}'. Expected: fish"
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def self.path_for(shell, env: ENV)
|
|
228
|
+
case shell.to_s
|
|
229
|
+
when "fish"
|
|
230
|
+
Pathname(Paths.new(environment: env).config_home).join("fish", "functions", "src.fish")
|
|
231
|
+
else
|
|
232
|
+
raise "Unsupported shell '#{shell}'. Expected: fish"
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def self.completions_path_for(shell, env: ENV)
|
|
237
|
+
case shell.to_s
|
|
238
|
+
when "fish"
|
|
239
|
+
Pathname(Paths.new(environment: env).config_home).join("fish", "completions", "src.fish")
|
|
240
|
+
else
|
|
241
|
+
raise "Unsupported shell '#{shell}'. Expected: fish"
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def self.install(shell, env: ENV, force: false)
|
|
246
|
+
fn_result = write_managed_file(
|
|
247
|
+
path: path_for(shell, env:),
|
|
248
|
+
content: self.for(shell),
|
|
249
|
+
force: force,
|
|
250
|
+
description: "fish function"
|
|
251
|
+
)
|
|
252
|
+
co_result = write_managed_file(
|
|
253
|
+
path: completions_path_for(shell, env:),
|
|
254
|
+
content: completions_for(shell),
|
|
255
|
+
force: force,
|
|
256
|
+
description: "fish completions"
|
|
257
|
+
)
|
|
258
|
+
fn_result.merge(
|
|
259
|
+
completions_action: co_result.fetch(:action),
|
|
260
|
+
completions_path: co_result.fetch(:path)
|
|
261
|
+
)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def self.uninstall(shell, env: ENV, force: false)
|
|
265
|
+
fn_result = remove_managed_file(
|
|
266
|
+
path: path_for(shell, env:),
|
|
267
|
+
content: self.for(shell),
|
|
268
|
+
force: force,
|
|
269
|
+
description: "fish function"
|
|
270
|
+
)
|
|
271
|
+
co_result = remove_managed_file(
|
|
272
|
+
path: completions_path_for(shell, env:),
|
|
273
|
+
content: completions_for(shell),
|
|
274
|
+
force: force,
|
|
275
|
+
description: "fish completions"
|
|
276
|
+
)
|
|
277
|
+
fn_result.merge(
|
|
278
|
+
completions_action: co_result.fetch(:action),
|
|
279
|
+
completions_path: co_result.fetch(:path)
|
|
280
|
+
)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def self.managed_src?(content)
|
|
284
|
+
content.include?("Generated by space-src")
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
private_class_method def self.write_managed_file(path:, content:, force:, description:)
|
|
288
|
+
existing = File.read(path) if File.exist?(path)
|
|
289
|
+
|
|
290
|
+
if existing && existing != content && !force && !managed_src?(existing)
|
|
291
|
+
raise "Refusing to overwrite existing #{description} at #{path}. Re-run with --force."
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
if existing == content
|
|
295
|
+
{action: :unchanged, path: path}
|
|
296
|
+
else
|
|
297
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
298
|
+
tmp = "#{path}.tmp.#{Process.pid}"
|
|
299
|
+
begin
|
|
300
|
+
File.write(tmp, content)
|
|
301
|
+
File.rename(tmp, path)
|
|
302
|
+
ensure
|
|
303
|
+
File.delete(tmp) if File.exist?(tmp)
|
|
304
|
+
end
|
|
305
|
+
{action: existing ? :updated : :installed, path: path}
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
private_class_method def self.remove_managed_file(path:, content:, force:, description:)
|
|
310
|
+
return {action: :missing, path: path} unless File.exist?(path)
|
|
311
|
+
|
|
312
|
+
existing = File.read(path)
|
|
313
|
+
if existing != content && !force && !managed_src?(existing)
|
|
314
|
+
raise "Refusing to remove existing #{description} at #{path}. Re-run with --force."
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
FileUtils.rm_f(path)
|
|
318
|
+
{action: :removed, path: path}
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|
|
@@ -5,9 +5,9 @@ require "fileutils"
|
|
|
5
5
|
require "time"
|
|
6
6
|
require "dry/monads"
|
|
7
7
|
|
|
8
|
-
module
|
|
8
|
+
module Space::Src
|
|
9
9
|
module State
|
|
10
|
-
# Machine-managed state at $XDG_STATE_HOME/
|
|
10
|
+
# Machine-managed state at $XDG_STATE_HOME/space-src/state.yaml.
|
|
11
11
|
# Never hand-edited (per PRD §3.2). Per-repo + per-org records with
|
|
12
12
|
# a fixed status enum; the store validates the enum and timestamp
|
|
13
13
|
# format on write.
|
|
@@ -6,16 +6,16 @@ require "async"
|
|
|
6
6
|
require "async/barrier"
|
|
7
7
|
require "async/semaphore"
|
|
8
8
|
require "dry/monads"
|
|
9
|
-
require "
|
|
10
|
-
require "
|
|
11
|
-
require "
|
|
12
|
-
require "
|
|
13
|
-
require "
|
|
14
|
-
require "
|
|
15
|
-
require "
|
|
16
|
-
require "
|
|
17
|
-
|
|
18
|
-
module
|
|
9
|
+
require "space_src/config/model"
|
|
10
|
+
require "space_src/scm/git"
|
|
11
|
+
require "space_src/forge/github"
|
|
12
|
+
require "space_src/state/store"
|
|
13
|
+
require "space_src/state/lock"
|
|
14
|
+
require "space_src/paths"
|
|
15
|
+
require "space_src/sync/repo_plan"
|
|
16
|
+
require "space_src/ui/reporter"
|
|
17
|
+
|
|
18
|
+
module Space::Src
|
|
19
19
|
module Sync
|
|
20
20
|
# The sync engine: one run that brings every tracked repo to the
|
|
21
21
|
# evergreen invariant (PRD §3.3). Splits observation (RepoPlan)
|
|
@@ -68,7 +68,7 @@ module SpaceArchitect::Pristine
|
|
|
68
68
|
|
|
69
69
|
def initialize(scm: SCM::Git.new, forge: Forge::GitHub.new,
|
|
70
70
|
clock: -> { Time.now }, url_builder: DEFAULT_URL_BUILDER,
|
|
71
|
-
reporter:
|
|
71
|
+
reporter: Space::Src::UI::NullReporter.new)
|
|
72
72
|
@scm = scm
|
|
73
73
|
@forge = forge
|
|
74
74
|
@clock = clock
|
|
@@ -160,7 +160,7 @@ module SpaceArchitect::Pristine
|
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
if lock_result == State::Lock::NOT_ACQUIRED
|
|
163
|
-
warn "
|
|
163
|
+
warn "src: skipped — another sync in progress"
|
|
164
164
|
Dry::Monads::Success(State::Store.load(paths.state_file).success)
|
|
165
165
|
else
|
|
166
166
|
lock_result
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
require "time"
|
|
4
4
|
require "dry/monads"
|
|
5
|
-
require "
|
|
6
|
-
require "
|
|
5
|
+
require "space_src/scm/client"
|
|
6
|
+
require "space_src/scm/status"
|
|
7
7
|
|
|
8
|
-
module
|
|
8
|
+
module Space::Src
|
|
9
9
|
module Sync
|
|
10
10
|
# Pure-ish evergreen evaluation. Given a RepoRef + on-disk path +
|
|
11
11
|
# SCM client + refresh_interval, observe the repo and decide an
|
data/lib/space_src.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "space_src/version"
|
|
4
|
+
|
|
5
|
+
# space-src — keep local git clones evergreen.
|
|
6
|
+
# (clean · on the remote's default branch · fetched within refresh_interval)
|
|
7
|
+
#
|
|
8
|
+
# Slice 1 surface: Paths, Shell, Config::{Model,Contract,Store},
|
|
9
|
+
# State::Store, SCM::{Client,Git,Status}, Forge::{Client,GitHub}.
|
|
10
|
+
# Later slices build sync orchestration, CLI, and launchd on top.
|
|
11
|
+
|
|
12
|
+
module Space::Src
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
require "space_src/paths"
|
|
16
|
+
require "space_src/shell"
|
|
17
|
+
require "space_src/config/model"
|
|
18
|
+
require "space_src/config/contract"
|
|
19
|
+
require "space_src/config/store"
|
|
20
|
+
require "space_src/state/store"
|
|
21
|
+
require "space_src/state/lock"
|
|
22
|
+
require "space_src/scm/client"
|
|
23
|
+
require "space_src/scm/status"
|
|
24
|
+
require "space_src/scm/git"
|
|
25
|
+
require "space_src/forge/client"
|
|
26
|
+
require "space_src/forge/github"
|
|
27
|
+
require "space_src/sync/repo_plan"
|
|
28
|
+
require "space_src/sync/engine"
|
|
29
|
+
require "space_src/config/duration"
|
|
30
|
+
require "space_src/log_rotator"
|
|
31
|
+
require "space_src/launchd/plist"
|
|
32
|
+
require "space_src/launchd/agent"
|
|
33
|
+
require "space_src/ui/reporter"
|
|
34
|
+
require "space_src/ui/mode"
|
|
35
|
+
require "space_src/ui/plain_reporter"
|
|
36
|
+
require "space_src/ui/json_reporter"
|
|
37
|
+
require "space_src/cli"
|
data/skill/architect/SKILL.md
CHANGED
|
@@ -126,8 +126,8 @@ loop.
|
|
|
126
126
|
an iteration index pointing at each iteration file; per-iteration detail lives
|
|
127
127
|
in the iteration file, never duplicated into the handoff. `architect status`
|
|
128
128
|
prints mission state (iterations, freeze_shas, lanes, verdicts) at any point.
|
|
129
|
-
- **Space setup (first time):** `architect space new "Mission Name" org/repo …`
|
|
130
|
-
(
|
|
129
|
+
- **Space setup (first time):** `architect space new "Mission Name" -r org/repo -r …`
|
|
130
|
+
(each repo is a repeatable `-r` flag after the title), then `architect init` inside
|
|
131
131
|
the space to scaffold `architecture/ARCHITECT.md`.
|
|
132
132
|
- Scale to the task: trivial fixes don't need the loop — say so and let the
|
|
133
133
|
human do it inline or in a normal session. The loop is for iteration-sized
|
data/skill/architect/research.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# Research fan-out reference
|
|
2
2
|
|
|
3
|
-
Read this only when a research trigger fires (see SKILL.md step 3). The
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
the iteration's **Grounds** section itself.
|
|
3
|
+
Read this only when a research trigger fires (see SKILL.md step 3). The fan-out
|
|
4
|
+
uses `architect research dispatch` to launch parallel read-only `claude -p`
|
|
5
|
+
researchers (Sonnet 4.6, no Edit/Write/Bash) and `architect research wait` to
|
|
6
|
+
collect their results. The architect keeps all judgment: it verifies
|
|
7
|
+
load-bearing claims and writes the iteration's **Grounds** section itself.
|
|
8
|
+
|
|
9
|
+
**Note:** the `~/.claude/skills/architect-research/` copy of this skill is
|
|
10
|
+
synced separately and is NOT updated by this repo.
|
|
8
11
|
|
|
9
12
|
## Fan out
|
|
10
13
|
|
|
@@ -13,41 +16,42 @@ Cover different angles, not the same angle five times — typical split:
|
|
|
13
16
|
official docs/reference, changelog/breaking changes, community failure reports,
|
|
14
17
|
alternatives/comparisons, security/operational constraints.
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
tool call** (`run_in_background`) — one call per researcher, not a shell `&`
|
|
18
|
-
loop (a `&` launcher orphans the researchers and the harness reaps them all at
|
|
19
|
-
once; same trap as builder dispatch). The researcher toolset is read-only
|
|
20
|
-
(`Read,Grep,Glob`) plus the web tools (`WebSearch,WebFetch`) — no
|
|
21
|
-
`Edit`/`Write`/`Bash`, so it cannot touch the repo. Capture the final report
|
|
22
|
-
by redirecting stdout (the report *is* the text result in the default `text`
|
|
23
|
-
output format):
|
|
19
|
+
Write each research prompt to its own file, then dispatch and wait:
|
|
24
20
|
|
|
25
21
|
```bash
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
# 1. Write one prompt file per research question (use Write tool — do NOT shell-redirect)
|
|
23
|
+
# Filenames: <NN>-<topic>.prompt.md e.g. 01-official-api.prompt.md
|
|
24
|
+
|
|
25
|
+
# 2. Dispatch all lanes at once (non-blocking — returns PIDs immediately)
|
|
26
|
+
architect research dispatch \
|
|
27
|
+
01-official-api.prompt.md \
|
|
28
|
+
02-changelog.prompt.md
|
|
29
|
+
|
|
30
|
+
# 3. Wait for all lanes to complete (tails run.jsonl streams; exits non-zero if any lane fails)
|
|
31
|
+
architect research wait
|
|
32
|
+
|
|
33
|
+
# 4. Read each report
|
|
34
|
+
cat build/research/01-official-api/report.md
|
|
35
|
+
cat build/research/02-changelog/report.md
|
|
31
36
|
```
|
|
32
37
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
its report. Bisect and re-dispatch dead lanes; don't re-run as-is.
|
|
38
|
+
The id for each lane is derived from the prompt filename:
|
|
39
|
+
`01-official-api.prompt.md` → id `01-official-api` →
|
|
40
|
+
directory `build/research/01-official-api/`.
|
|
41
|
+
|
|
42
|
+
Verbosity flags for `wait`:
|
|
43
|
+
- default (L1): per-lane lifecycle + terminal outcome line
|
|
44
|
+
- `--level 2`: + assistant text
|
|
45
|
+
- `--level 3`: + tool call names
|
|
46
|
+
- `--level 4`: + tool call inputs and results
|
|
47
|
+
- `--quiet`: suppress all output; exit status alone signals outcome
|
|
48
|
+
- `--thinking`: reveal assistant thinking blocks
|
|
49
|
+
- `--jsonl`: emit raw lane-tagged JSONL instead of human text
|
|
50
|
+
|
|
51
|
+
The researchers are READ-ONLY by toolset (`Read,Grep,Glob,WebSearch,WebFetch`
|
|
52
|
+
with no Edit/Write/Bash) so they cannot touch the repo. Their final report
|
|
53
|
+
is extracted from the terminal `result` event in the stream-json log and
|
|
54
|
+
written to `build/research/<id>/report.md` automatically by `wait`.
|
|
51
55
|
|
|
52
56
|
## Research-prompt template
|
|
53
57
|
|
|
@@ -70,9 +74,14 @@ OUTPUT FORMAT — a markdown report:
|
|
|
70
74
|
- End with: the 2-3 findings most likely to change an implementation decision.
|
|
71
75
|
```
|
|
72
76
|
|
|
77
|
+
Keep each researcher scoped to ≤5 subjects and put hard context rules in the
|
|
78
|
+
prompt (snippet over page; quote ≤2 sentences; stop the moment you can answer)
|
|
79
|
+
— a researcher that fills its context window dies without emitting its report.
|
|
80
|
+
Bisect and re-dispatch dead lanes; don't re-run as-is.
|
|
81
|
+
|
|
73
82
|
## Gather (architect — this is your work, not another agent's)
|
|
74
83
|
|
|
75
|
-
1. Read every
|
|
84
|
+
1. Read every `build/research/<id>/report.md`.
|
|
76
85
|
2. Identify the **load-bearing claims** — facts the spec will depend on
|
|
77
86
|
(an API shape, a version constraint, a limit, a deprecation). Adversarially
|
|
78
87
|
verify each: cross-check against a second independent source or the live
|