ariadna 1.2.0 → 1.2.2
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/data/agents/ariadna-backend-executor.md +9 -6
- data/data/agents/ariadna-codebase-mapper.md +5 -5
- data/data/agents/ariadna-debugger.md +13 -13
- data/data/agents/ariadna-executor.md +9 -6
- data/data/agents/ariadna-frontend-executor.md +9 -6
- data/data/agents/ariadna-integration-checker.md +1 -1
- data/data/agents/ariadna-phase-researcher.md +1 -1
- data/data/agents/ariadna-planner.md +17 -17
- data/data/agents/ariadna-project-researcher.md +10 -10
- data/data/agents/ariadna-research-synthesizer.md +11 -11
- data/data/agents/ariadna-roadmapper.md +8 -8
- data/data/agents/ariadna-test-executor.md +9 -6
- data/data/agents/ariadna-verifier.md +4 -4
- data/data/ariadna/references/decimal-phase-calculation.md +2 -2
- data/data/ariadna/references/git-integration.md +4 -4
- data/data/ariadna/references/git-planning-commit.md +7 -7
- data/data/ariadna/references/model-profile-resolution.md +1 -1
- data/data/ariadna/references/model-profiles.md +2 -2
- data/data/ariadna/references/planning-config.md +13 -13
- data/data/ariadna/references/rails-conventions.md +9 -2
- data/data/ariadna/references/tdd.md +2 -2
- data/data/ariadna/templates/DEBUG.md +2 -2
- data/data/ariadna/templates/UAT.md +3 -3
- data/data/ariadna/templates/codebase/architecture.md +1 -1
- data/data/ariadna/templates/codebase/concerns.md +1 -1
- data/data/ariadna/templates/codebase/conventions.md +1 -1
- data/data/ariadna/templates/codebase/integrations.md +1 -1
- data/data/ariadna/templates/codebase/stack.md +1 -1
- data/data/ariadna/templates/codebase/structure.md +1 -1
- data/data/ariadna/templates/codebase/testing.md +1 -1
- data/data/ariadna/templates/context.md +2 -2
- data/data/ariadna/templates/continue-here.md +1 -1
- data/data/ariadna/templates/debug-subagent-prompt.md +2 -2
- data/data/ariadna/templates/discovery.md +2 -2
- data/data/ariadna/templates/milestone-archive.md +4 -4
- data/data/ariadna/templates/milestone.md +1 -1
- data/data/ariadna/templates/phase-prompt.md +19 -19
- data/data/ariadna/templates/planner-subagent-prompt.md +9 -9
- data/data/ariadna/templates/project.md +2 -2
- data/data/ariadna/templates/requirements.md +1 -1
- data/data/ariadna/templates/research-project/ARCHITECTURE.md +1 -1
- data/data/ariadna/templates/research-project/FEATURES.md +1 -1
- data/data/ariadna/templates/research-project/PITFALLS.md +1 -1
- data/data/ariadna/templates/research-project/STACK.md +1 -1
- data/data/ariadna/templates/research-project/SUMMARY.md +1 -1
- data/data/ariadna/templates/research.md +2 -2
- data/data/ariadna/templates/roadmap.md +1 -1
- data/data/ariadna/templates/state.md +4 -4
- data/data/ariadna/templates/summary.md +12 -1
- data/data/ariadna/templates/user-setup.md +2 -2
- data/data/ariadna/templates/verification-report.md +1 -1
- data/data/ariadna/workflows/add-phase.md +5 -5
- data/data/ariadna/workflows/add-todo.md +7 -7
- data/data/ariadna/workflows/audit-milestone.md +7 -7
- data/data/ariadna/workflows/check-todos.md +4 -4
- data/data/ariadna/workflows/complete-milestone.md +18 -18
- data/data/ariadna/workflows/diagnose-issues.md +4 -4
- data/data/ariadna/workflows/discovery-phase.md +4 -4
- data/data/ariadna/workflows/discuss-phase.md +2 -2
- data/data/ariadna/workflows/execute-phase.md +97 -9
- data/data/ariadna/workflows/execute-plan.md +30 -19
- data/data/ariadna/workflows/help.md +18 -18
- data/data/ariadna/workflows/insert-phase.md +6 -6
- data/data/ariadna/workflows/list-phase-assumptions.md +1 -1
- data/data/ariadna/workflows/map-codebase.md +22 -22
- data/data/ariadna/workflows/new-milestone.md +16 -16
- data/data/ariadna/workflows/new-project.md +39 -39
- data/data/ariadna/workflows/pause-work.md +4 -4
- data/data/ariadna/workflows/plan-milestone-gaps.md +4 -4
- data/data/ariadna/workflows/plan-phase.md +43 -19
- data/data/ariadna/workflows/progress.md +6 -6
- data/data/ariadna/workflows/quick.md +6 -6
- data/data/ariadna/workflows/remove-phase.md +3 -3
- data/data/ariadna/workflows/research-phase.md +4 -4
- data/data/ariadna/workflows/resume-project.md +9 -9
- data/data/ariadna/workflows/set-profile.md +2 -2
- data/data/ariadna/workflows/settings.md +4 -4
- data/data/ariadna/workflows/transition.md +11 -11
- data/data/ariadna/workflows/verify-phase.md +2 -2
- data/data/ariadna/workflows/verify-work.md +8 -8
- data/data/commands/ariadna/add-phase.md +2 -2
- data/data/commands/ariadna/add-todo.md +1 -1
- data/data/commands/ariadna/audit-milestone.md +6 -6
- data/data/commands/ariadna/check-todos.md +2 -2
- data/data/commands/ariadna/complete-milestone.md +11 -11
- data/data/commands/ariadna/debug.md +3 -3
- data/data/commands/ariadna/discuss-phase.md +2 -2
- data/data/commands/ariadna/execute-phase.md +6 -5
- data/data/commands/ariadna/insert-phase.md +2 -2
- data/data/commands/ariadna/list-phase-assumptions.md +2 -2
- data/data/commands/ariadna/map-codebase.md +7 -7
- data/data/commands/ariadna/new-milestone.md +10 -10
- data/data/commands/ariadna/new-project.md +6 -6
- data/data/commands/ariadna/pause-work.md +1 -1
- data/data/commands/ariadna/plan-milestone-gaps.md +5 -5
- data/data/commands/ariadna/quick.md +2 -2
- data/data/commands/ariadna/remove-phase.md +2 -2
- data/data/commands/ariadna/research-phase.md +6 -6
- data/data/commands/ariadna/verify-work.md +2 -2
- data/data/guides/frontend.md +1044 -9
- data/data/statusline/ariadna-statusline.sh +47 -0
- data/data/templates.md +1 -1
- data/exe/ariadna +2 -1
- data/lib/ariadna/installer.rb +30 -1
- data/lib/ariadna/tools/config_manager.rb +12 -6
- data/lib/ariadna/tools/git_integration.rb +2 -2
- data/lib/ariadna/tools/init.rb +66 -61
- data/lib/ariadna/tools/phase_manager.rb +31 -13
- data/lib/ariadna/tools/roadmap_analyzer.rb +5 -5
- data/lib/ariadna/tools/state_manager.rb +14 -14
- data/lib/ariadna/tools/template_filler.rb +5 -5
- data/lib/ariadna/tools/utilities.rb +4 -4
- data/lib/ariadna/tools/verification.rb +4 -4
- data/lib/ariadna/uninstaller.rb +17 -0
- data/lib/ariadna/version.rb +1 -1
- metadata +2 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Ariadna statusline for Claude Code
|
|
3
|
+
|
|
4
|
+
input=$(cat)
|
|
5
|
+
|
|
6
|
+
# Require jq
|
|
7
|
+
if ! command -v jq &>/dev/null; then
|
|
8
|
+
echo "ariadna: jq required for statusline"
|
|
9
|
+
exit 0
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
MODEL=$(echo "$input" | jq -r '.model.display_name // "unknown"')
|
|
13
|
+
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
|
|
14
|
+
CWD=$(echo "$input" | jq -r '.cwd // ""')
|
|
15
|
+
|
|
16
|
+
# Scale to 80% effective limit (Claude Code compresses at ~80%)
|
|
17
|
+
SCALED=$(( PCT * 100 / 80 ))
|
|
18
|
+
[ "$SCALED" -gt 100 ] && SCALED=100
|
|
19
|
+
|
|
20
|
+
# Color based on scaled percentage
|
|
21
|
+
if [ "$SCALED" -ge 80 ]; then
|
|
22
|
+
COLOR='\033[31m' # Red
|
|
23
|
+
elif [ "$SCALED" -ge 60 ]; then
|
|
24
|
+
COLOR='\033[33m' # Yellow
|
|
25
|
+
else
|
|
26
|
+
COLOR='\033[32m' # Green
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Progress bar (10 chars)
|
|
30
|
+
FILLED=$(( SCALED / 10 ))
|
|
31
|
+
EMPTY=$(( 10 - FILLED ))
|
|
32
|
+
BAR=$(printf "%${FILLED}s" | tr ' ' '█')$(printf "%${EMPTY}s" | tr ' ' '░')
|
|
33
|
+
|
|
34
|
+
# Phase info from STATE.md
|
|
35
|
+
PHASE=""
|
|
36
|
+
if [ -n "$CWD" ] && [ -f "$CWD/.ariadna_planning/STATE.md" ]; then
|
|
37
|
+
PHASE=$(grep -m1 '^Phase:' "$CWD/.ariadna_planning/STATE.md" | sed 's/^Phase:[[:space:]]*//')
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Build output
|
|
41
|
+
DIM='\033[2m'
|
|
42
|
+
RESET='\033[0m'
|
|
43
|
+
if [ -n "$PHASE" ]; then
|
|
44
|
+
echo -e "${DIM}${MODEL}${RESET} │ ${PHASE} ${COLOR}${BAR}${RESET} ${PCT}%"
|
|
45
|
+
else
|
|
46
|
+
echo -e "${DIM}${MODEL}${RESET} ${COLOR}${BAR}${RESET} ${PCT}%"
|
|
47
|
+
fi
|
data/data/templates.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Context
|
|
4
4
|
|
|
5
|
-
The templates in `data/ariadna/templates/codebase/` are used by Ariadna's codebase mapping agents to generate `.
|
|
5
|
+
The templates in `data/ariadna/templates/codebase/` are used by Ariadna's codebase mapping agents to generate `.ariadna_planning/codebase/` documents when analyzing a Rails project. Currently, all templates except `architecture.md` are generic/framework-agnostic with JavaScript/TypeScript examples (Next.js, Vitest, npm, etc.). Since Ariadna is targeting Ruby on Rails applications, these templates should use Rails-specific terminology, examples, tools, and patterns.
|
|
6
6
|
|
|
7
7
|
`architecture.md` has already been updated and serves as the reference for style and approach.
|
|
8
8
|
|
data/exe/ariadna
CHANGED
|
@@ -9,6 +9,7 @@ case command
|
|
|
9
9
|
when "install"
|
|
10
10
|
global = ARGV.include?("--global") || ARGV.include?("-g")
|
|
11
11
|
local = ARGV.include?("--local") || ARGV.include?("-l")
|
|
12
|
+
force_statusline = ARGV.include?("--force-statusline")
|
|
12
13
|
|
|
13
14
|
unless global || local
|
|
14
15
|
warn "Usage: ariadna install --global (install to ~/.claude/)"
|
|
@@ -16,7 +17,7 @@ when "install"
|
|
|
16
17
|
exit 1
|
|
17
18
|
end
|
|
18
19
|
|
|
19
|
-
Ariadna::Installer.new(local: local).install
|
|
20
|
+
Ariadna::Installer.new(local: local, force_statusline: force_statusline).install
|
|
20
21
|
when "uninstall"
|
|
21
22
|
require "ariadna/uninstaller"
|
|
22
23
|
global = ARGV.include?("--global") || ARGV.include?("-g")
|
data/lib/ariadna/installer.rb
CHANGED
|
@@ -7,9 +7,10 @@ module Ariadna
|
|
|
7
7
|
MANIFEST_NAME = "ariadna-manifest.json"
|
|
8
8
|
PATCHES_DIR = "ariadna-local-patches"
|
|
9
9
|
|
|
10
|
-
def initialize(target_dir: nil, local: false)
|
|
10
|
+
def initialize(target_dir: nil, local: false, force_statusline: false)
|
|
11
11
|
@local = local
|
|
12
12
|
@target_dir = target_dir || default_target_dir
|
|
13
|
+
@force_statusline = force_statusline
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def install
|
|
@@ -23,6 +24,7 @@ module Ariadna
|
|
|
23
24
|
copy_guides
|
|
24
25
|
copy_content
|
|
25
26
|
write_version
|
|
27
|
+
install_statusline
|
|
26
28
|
write_manifest
|
|
27
29
|
|
|
28
30
|
report_local_patches
|
|
@@ -135,6 +137,7 @@ module Ariadna
|
|
|
135
137
|
keys << rel
|
|
136
138
|
end
|
|
137
139
|
end
|
|
140
|
+
keys << "ariadna-statusline.sh"
|
|
138
141
|
keys
|
|
139
142
|
end
|
|
140
143
|
|
|
@@ -154,6 +157,28 @@ module Ariadna
|
|
|
154
157
|
end
|
|
155
158
|
end
|
|
156
159
|
|
|
160
|
+
# --- Statusline ---
|
|
161
|
+
|
|
162
|
+
def install_statusline
|
|
163
|
+
src = File.join(source_dir, "statusline", "ariadna-statusline.sh")
|
|
164
|
+
dest = File.join(@target_dir, "ariadna-statusline.sh")
|
|
165
|
+
|
|
166
|
+
FileUtils.cp(src, dest)
|
|
167
|
+
FileUtils.chmod(0o755, dest)
|
|
168
|
+
|
|
169
|
+
settings_path = File.join(@target_dir, "settings.json")
|
|
170
|
+
settings = File.exist?(settings_path) ? JSON.parse(File.read(settings_path)) : {}
|
|
171
|
+
|
|
172
|
+
if settings.key?("statusLine") && !@force_statusline
|
|
173
|
+
puts " i Existing statusLine config found \u2014 skipping (use --force-statusline to replace)"
|
|
174
|
+
return
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
settings["statusLine"] = { "type" => "command", "command" => dest }
|
|
178
|
+
File.write(settings_path, JSON.pretty_generate(settings))
|
|
179
|
+
puts " \u2713 Installed statusline"
|
|
180
|
+
end
|
|
181
|
+
|
|
157
182
|
# --- Copy operations ---
|
|
158
183
|
|
|
159
184
|
def copy_commands
|
|
@@ -226,6 +251,10 @@ module Ariadna
|
|
|
226
251
|
entries[rel] = Digest::SHA256.file(file).hexdigest
|
|
227
252
|
end
|
|
228
253
|
end
|
|
254
|
+
|
|
255
|
+
statusline_path = File.join(@target_dir, "ariadna-statusline.sh")
|
|
256
|
+
entries["ariadna-statusline.sh"] = Digest::SHA256.file(statusline_path).hexdigest if File.exist?(statusline_path)
|
|
257
|
+
|
|
229
258
|
entries
|
|
230
259
|
end
|
|
231
260
|
|
|
@@ -21,7 +21,7 @@ module Ariadna
|
|
|
21
21
|
}.freeze
|
|
22
22
|
|
|
23
23
|
def self.load_config(cwd = Dir.pwd)
|
|
24
|
-
config_path = File.join(cwd, ".
|
|
24
|
+
config_path = File.join(cwd, ".ariadna_planning", "config.json")
|
|
25
25
|
return DEFAULTS.dup unless File.exist?(config_path)
|
|
26
26
|
|
|
27
27
|
raw = File.read(config_path)
|
|
@@ -63,7 +63,13 @@ module Ariadna
|
|
|
63
63
|
"verifier" => nil_or.call(get.call("verifier", { section: "workflow", field: "verifier" }), DEFAULTS["verifier"]),
|
|
64
64
|
"parallelization" => parallelization,
|
|
65
65
|
"execution_mode" => get.call("execution_mode", { section: "execution", field: "mode" }) || DEFAULTS["execution_mode"],
|
|
66
|
-
"team_execution" =>
|
|
66
|
+
"team_execution" => begin
|
|
67
|
+
val = get.call("team_execution", { section: "execution", field: "team" })
|
|
68
|
+
case val
|
|
69
|
+
when "auto", true, false then val
|
|
70
|
+
else DEFAULTS["team_execution"]
|
|
71
|
+
end
|
|
72
|
+
end
|
|
67
73
|
}
|
|
68
74
|
rescue JSON::ParserError
|
|
69
75
|
DEFAULTS.dup
|
|
@@ -71,8 +77,8 @@ module Ariadna
|
|
|
71
77
|
|
|
72
78
|
def self.ensure_section(argv, raw: false)
|
|
73
79
|
cwd = Dir.pwd
|
|
74
|
-
config_path = File.join(cwd, ".
|
|
75
|
-
planning_dir = File.join(cwd, ".
|
|
80
|
+
config_path = File.join(cwd, ".ariadna_planning", "config.json")
|
|
81
|
+
planning_dir = File.join(cwd, ".ariadna_planning")
|
|
76
82
|
|
|
77
83
|
FileUtils.mkdir_p(planning_dir) unless File.directory?(planning_dir)
|
|
78
84
|
|
|
@@ -99,7 +105,7 @@ module Ariadna
|
|
|
99
105
|
}
|
|
100
106
|
|
|
101
107
|
File.write(config_path, JSON.pretty_generate(defaults))
|
|
102
|
-
Output.json({ created: true, path: ".
|
|
108
|
+
Output.json({ created: true, path: ".ariadna_planning/config.json" }, raw: raw, raw_value: "created")
|
|
103
109
|
end
|
|
104
110
|
|
|
105
111
|
def self.set(argv, raw: false)
|
|
@@ -108,7 +114,7 @@ module Ariadna
|
|
|
108
114
|
Output.error("Usage: config-set <key.path> <value>") unless key_path
|
|
109
115
|
|
|
110
116
|
cwd = Dir.pwd
|
|
111
|
-
config_path = File.join(cwd, ".
|
|
117
|
+
config_path = File.join(cwd, ".ariadna_planning", "config.json")
|
|
112
118
|
|
|
113
119
|
config = {}
|
|
114
120
|
if File.exist?(config_path)
|
|
@@ -22,14 +22,14 @@ module Ariadna
|
|
|
22
22
|
return
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
if git_ignored?(cwd, ".
|
|
25
|
+
if git_ignored?(cwd, ".ariadna_planning")
|
|
26
26
|
Output.json({ committed: false, hash: nil, reason: "skipped_gitignored" }, raw: raw, raw_value: "skipped")
|
|
27
27
|
return
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Stage files
|
|
31
31
|
if files.empty?
|
|
32
|
-
exec_git(cwd, ["add", ".
|
|
32
|
+
exec_git(cwd, ["add", ".ariadna_planning/"])
|
|
33
33
|
else
|
|
34
34
|
files.each { |f| exec_git(cwd, ["add", f]) }
|
|
35
35
|
end
|
data/lib/ariadna/tools/init.rb
CHANGED
|
@@ -83,14 +83,19 @@ module Ariadna
|
|
|
83
83
|
milestone_version: milestone[:version],
|
|
84
84
|
milestone_name: milestone[:name],
|
|
85
85
|
milestone_slug: generate_slug(milestone[:name]),
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
team_execution: config["team_execution"],
|
|
87
|
+
execution_mode: config["execution_mode"],
|
|
88
|
+
backend_executor_model: resolve_model(cwd, "ariadna-backend-executor"),
|
|
89
|
+
frontend_executor_model: resolve_model(cwd, "ariadna-frontend-executor"),
|
|
90
|
+
test_executor_model: resolve_model(cwd, "ariadna-test-executor"),
|
|
91
|
+
state_exists: path_exists?(cwd, ".ariadna_planning/STATE.md"),
|
|
92
|
+
roadmap_exists: path_exists?(cwd, ".ariadna_planning/ROADMAP.md"),
|
|
93
|
+
config_exists: path_exists?(cwd, ".ariadna_planning/config.json")
|
|
89
94
|
}
|
|
90
95
|
|
|
91
|
-
result[:state_content] = safe_read_file(File.join(cwd, ".
|
|
92
|
-
result[:config_content] = safe_read_file(File.join(cwd, ".
|
|
93
|
-
result[:roadmap_content] = safe_read_file(File.join(cwd, ".
|
|
96
|
+
result[:state_content] = safe_read_file(File.join(cwd, ".ariadna_planning", "STATE.md")) if includes.include?("state")
|
|
97
|
+
result[:config_content] = safe_read_file(File.join(cwd, ".ariadna_planning", "config.json")) if includes.include?("config")
|
|
98
|
+
result[:roadmap_content] = safe_read_file(File.join(cwd, ".ariadna_planning", "ROADMAP.md")) if includes.include?("roadmap")
|
|
94
99
|
|
|
95
100
|
Output.json(result, raw: raw)
|
|
96
101
|
end
|
|
@@ -119,13 +124,13 @@ module Ariadna
|
|
|
119
124
|
has_context: phase_info&.dig(:has_context) || false,
|
|
120
125
|
has_plans: (phase_info&.dig(:plans)&.length || 0) > 0,
|
|
121
126
|
plan_count: phase_info&.dig(:plans)&.length || 0,
|
|
122
|
-
planning_exists: path_exists?(cwd, ".
|
|
123
|
-
roadmap_exists: path_exists?(cwd, ".
|
|
127
|
+
planning_exists: path_exists?(cwd, ".ariadna_planning"),
|
|
128
|
+
roadmap_exists: path_exists?(cwd, ".ariadna_planning/ROADMAP.md")
|
|
124
129
|
}
|
|
125
130
|
|
|
126
|
-
result[:state_content] = safe_read_file(File.join(cwd, ".
|
|
127
|
-
result[:roadmap_content] = safe_read_file(File.join(cwd, ".
|
|
128
|
-
result[:requirements_content] = safe_read_file(File.join(cwd, ".
|
|
131
|
+
result[:state_content] = safe_read_file(File.join(cwd, ".ariadna_planning", "STATE.md")) if includes.include?("state")
|
|
132
|
+
result[:roadmap_content] = safe_read_file(File.join(cwd, ".ariadna_planning", "ROADMAP.md")) if includes.include?("roadmap")
|
|
133
|
+
result[:requirements_content] = safe_read_file(File.join(cwd, ".ariadna_planning", "REQUIREMENTS.md")) if includes.include?("requirements")
|
|
129
134
|
|
|
130
135
|
if includes.include?("context") && phase_info&.dig(:directory)
|
|
131
136
|
phase_dir_full = File.join(cwd, phase_info[:directory])
|
|
@@ -176,13 +181,13 @@ module Ariadna
|
|
|
176
181
|
synthesizer_model: resolve_model(cwd, "ariadna-research-synthesizer"),
|
|
177
182
|
roadmapper_model: resolve_model(cwd, "ariadna-roadmapper"),
|
|
178
183
|
commit_docs: config["commit_docs"],
|
|
179
|
-
project_exists: path_exists?(cwd, ".
|
|
180
|
-
has_codebase_map: path_exists?(cwd, ".
|
|
181
|
-
planning_exists: path_exists?(cwd, ".
|
|
184
|
+
project_exists: path_exists?(cwd, ".ariadna_planning/PROJECT.md"),
|
|
185
|
+
has_codebase_map: path_exists?(cwd, ".ariadna_planning/codebase"),
|
|
186
|
+
planning_exists: path_exists?(cwd, ".ariadna_planning"),
|
|
182
187
|
has_existing_code: has_code,
|
|
183
188
|
has_package_file: has_package_file,
|
|
184
189
|
is_brownfield: has_code || has_package_file,
|
|
185
|
-
needs_codebase_map: (has_code || has_package_file) && !path_exists?(cwd, ".
|
|
190
|
+
needs_codebase_map: (has_code || has_package_file) && !path_exists?(cwd, ".ariadna_planning/codebase"),
|
|
186
191
|
has_git: path_exists?(cwd, ".git")
|
|
187
192
|
}
|
|
188
193
|
|
|
@@ -202,9 +207,9 @@ module Ariadna
|
|
|
202
207
|
research_enabled: config["research"],
|
|
203
208
|
current_milestone: milestone[:version],
|
|
204
209
|
current_milestone_name: milestone[:name],
|
|
205
|
-
project_exists: path_exists?(cwd, ".
|
|
206
|
-
roadmap_exists: path_exists?(cwd, ".
|
|
207
|
-
state_exists: path_exists?(cwd, ".
|
|
210
|
+
project_exists: path_exists?(cwd, ".ariadna_planning/PROJECT.md"),
|
|
211
|
+
roadmap_exists: path_exists?(cwd, ".ariadna_planning/ROADMAP.md"),
|
|
212
|
+
state_exists: path_exists?(cwd, ".ariadna_planning/STATE.md")
|
|
208
213
|
}
|
|
209
214
|
|
|
210
215
|
Output.json(result, raw: raw)
|
|
@@ -216,7 +221,7 @@ module Ariadna
|
|
|
216
221
|
now = Time.now.utc
|
|
217
222
|
slug = description && !description.empty? ? generate_slug(description)&.slice(0, 40) : nil
|
|
218
223
|
|
|
219
|
-
quick_dir = File.join(cwd, ".
|
|
224
|
+
quick_dir = File.join(cwd, ".ariadna_planning", "quick")
|
|
220
225
|
next_num = 1
|
|
221
226
|
if File.directory?(quick_dir)
|
|
222
227
|
existing = Dir.children(quick_dir)
|
|
@@ -233,10 +238,10 @@ module Ariadna
|
|
|
233
238
|
description: description && !description.empty? ? description : nil,
|
|
234
239
|
date: now.strftime("%Y-%m-%d"),
|
|
235
240
|
timestamp: now.iso8601,
|
|
236
|
-
quick_dir: ".
|
|
237
|
-
task_dir: slug ? ".
|
|
238
|
-
roadmap_exists: path_exists?(cwd, ".
|
|
239
|
-
planning_exists: path_exists?(cwd, ".
|
|
241
|
+
quick_dir: ".ariadna_planning/quick",
|
|
242
|
+
task_dir: slug ? ".ariadna_planning/quick/#{next_num}-#{slug}" : nil,
|
|
243
|
+
roadmap_exists: path_exists?(cwd, ".ariadna_planning/ROADMAP.md"),
|
|
244
|
+
planning_exists: path_exists?(cwd, ".ariadna_planning")
|
|
240
245
|
}
|
|
241
246
|
|
|
242
247
|
Output.json(result, raw: raw)
|
|
@@ -247,14 +252,14 @@ module Ariadna
|
|
|
247
252
|
config = ConfigManager.load_config(cwd)
|
|
248
253
|
|
|
249
254
|
interrupted_agent_id = nil
|
|
250
|
-
agent_file = File.join(cwd, ".
|
|
255
|
+
agent_file = File.join(cwd, ".ariadna_planning", "current-agent-id.txt")
|
|
251
256
|
interrupted_agent_id = File.read(agent_file).strip if File.exist?(agent_file)
|
|
252
257
|
|
|
253
258
|
result = {
|
|
254
|
-
state_exists: path_exists?(cwd, ".
|
|
255
|
-
roadmap_exists: path_exists?(cwd, ".
|
|
256
|
-
project_exists: path_exists?(cwd, ".
|
|
257
|
-
planning_exists: path_exists?(cwd, ".
|
|
259
|
+
state_exists: path_exists?(cwd, ".ariadna_planning/STATE.md"),
|
|
260
|
+
roadmap_exists: path_exists?(cwd, ".ariadna_planning/ROADMAP.md"),
|
|
261
|
+
project_exists: path_exists?(cwd, ".ariadna_planning/PROJECT.md"),
|
|
262
|
+
planning_exists: path_exists?(cwd, ".ariadna_planning"),
|
|
258
263
|
has_interrupted_agent: !interrupted_agent_id.nil?,
|
|
259
264
|
interrupted_agent_id: interrupted_agent_id,
|
|
260
265
|
commit_docs: config["commit_docs"]
|
|
@@ -302,8 +307,8 @@ module Ariadna
|
|
|
302
307
|
has_plans: (phase_info&.dig(:plans)&.length || 0) > 0,
|
|
303
308
|
has_verification: phase_info&.dig(:has_verification) || false,
|
|
304
309
|
plan_count: phase_info&.dig(:plans)&.length || 0,
|
|
305
|
-
roadmap_exists: path_exists?(cwd, ".
|
|
306
|
-
planning_exists: path_exists?(cwd, ".
|
|
310
|
+
roadmap_exists: path_exists?(cwd, ".ariadna_planning/ROADMAP.md"),
|
|
311
|
+
planning_exists: path_exists?(cwd, ".ariadna_planning")
|
|
307
312
|
}
|
|
308
313
|
|
|
309
314
|
Output.json(result, raw: raw)
|
|
@@ -314,7 +319,7 @@ module Ariadna
|
|
|
314
319
|
config = ConfigManager.load_config(cwd)
|
|
315
320
|
now = Time.now.utc
|
|
316
321
|
|
|
317
|
-
pending_dir = File.join(cwd, ".
|
|
322
|
+
pending_dir = File.join(cwd, ".ariadna_planning", "todos", "pending")
|
|
318
323
|
count = 0
|
|
319
324
|
todo_list = []
|
|
320
325
|
|
|
@@ -330,7 +335,7 @@ module Ariadna
|
|
|
330
335
|
count += 1
|
|
331
336
|
todo_list << {
|
|
332
337
|
file: File.basename(file), created: created, title: title, area: todo_area,
|
|
333
|
-
path: File.join(".
|
|
338
|
+
path: File.join(".ariadna_planning", "todos", "pending", File.basename(file))
|
|
334
339
|
}
|
|
335
340
|
end
|
|
336
341
|
end
|
|
@@ -342,11 +347,11 @@ module Ariadna
|
|
|
342
347
|
todo_count: count,
|
|
343
348
|
todos: todo_list,
|
|
344
349
|
area_filter: area,
|
|
345
|
-
pending_dir: ".
|
|
346
|
-
completed_dir: ".
|
|
347
|
-
planning_exists: path_exists?(cwd, ".
|
|
348
|
-
todos_dir_exists: path_exists?(cwd, ".
|
|
349
|
-
pending_dir_exists: path_exists?(cwd, ".
|
|
350
|
+
pending_dir: ".ariadna_planning/todos/pending",
|
|
351
|
+
completed_dir: ".ariadna_planning/todos/completed",
|
|
352
|
+
planning_exists: path_exists?(cwd, ".ariadna_planning"),
|
|
353
|
+
todos_dir_exists: path_exists?(cwd, ".ariadna_planning/todos"),
|
|
354
|
+
pending_dir_exists: path_exists?(cwd, ".ariadna_planning/todos/pending")
|
|
350
355
|
}
|
|
351
356
|
|
|
352
357
|
Output.json(result, raw: raw)
|
|
@@ -357,7 +362,7 @@ module Ariadna
|
|
|
357
362
|
config = ConfigManager.load_config(cwd)
|
|
358
363
|
milestone = get_milestone_info(cwd)
|
|
359
364
|
|
|
360
|
-
phases_dir = File.join(cwd, ".
|
|
365
|
+
phases_dir = File.join(cwd, ".ariadna_planning", "phases")
|
|
361
366
|
phase_count = 0
|
|
362
367
|
completed_phases = 0
|
|
363
368
|
|
|
@@ -370,7 +375,7 @@ module Ariadna
|
|
|
370
375
|
end
|
|
371
376
|
end
|
|
372
377
|
|
|
373
|
-
archive_dir = File.join(cwd, ".
|
|
378
|
+
archive_dir = File.join(cwd, ".ariadna_planning", "archive")
|
|
374
379
|
archived_milestones = []
|
|
375
380
|
if File.directory?(archive_dir)
|
|
376
381
|
archived_milestones = Dir.children(archive_dir).select { |e| File.directory?(File.join(archive_dir, e)) }
|
|
@@ -386,11 +391,11 @@ module Ariadna
|
|
|
386
391
|
all_phases_complete: phase_count > 0 && phase_count == completed_phases,
|
|
387
392
|
archived_milestones: archived_milestones,
|
|
388
393
|
archive_count: archived_milestones.length,
|
|
389
|
-
project_exists: path_exists?(cwd, ".
|
|
390
|
-
roadmap_exists: path_exists?(cwd, ".
|
|
391
|
-
state_exists: path_exists?(cwd, ".
|
|
392
|
-
archive_exists: path_exists?(cwd, ".
|
|
393
|
-
phases_dir_exists: path_exists?(cwd, ".
|
|
394
|
+
project_exists: path_exists?(cwd, ".ariadna_planning/PROJECT.md"),
|
|
395
|
+
roadmap_exists: path_exists?(cwd, ".ariadna_planning/ROADMAP.md"),
|
|
396
|
+
state_exists: path_exists?(cwd, ".ariadna_planning/STATE.md"),
|
|
397
|
+
archive_exists: path_exists?(cwd, ".ariadna_planning/archive"),
|
|
398
|
+
phases_dir_exists: path_exists?(cwd, ".ariadna_planning/phases")
|
|
394
399
|
}
|
|
395
400
|
|
|
396
401
|
Output.json(result, raw: raw)
|
|
@@ -400,7 +405,7 @@ module Ariadna
|
|
|
400
405
|
cwd = Dir.pwd
|
|
401
406
|
config = ConfigManager.load_config(cwd)
|
|
402
407
|
|
|
403
|
-
codebase_dir = File.join(cwd, ".
|
|
408
|
+
codebase_dir = File.join(cwd, ".ariadna_planning", "codebase")
|
|
404
409
|
existing_maps = []
|
|
405
410
|
existing_maps = Dir.children(codebase_dir).select { |f| f.end_with?(".md") } if File.directory?(codebase_dir)
|
|
406
411
|
|
|
@@ -409,11 +414,11 @@ module Ariadna
|
|
|
409
414
|
commit_docs: config["commit_docs"],
|
|
410
415
|
search_gitignored: config["search_gitignored"],
|
|
411
416
|
parallelization: config["parallelization"],
|
|
412
|
-
codebase_dir: ".
|
|
417
|
+
codebase_dir: ".ariadna_planning/codebase",
|
|
413
418
|
existing_maps: existing_maps,
|
|
414
419
|
has_maps: existing_maps.any?,
|
|
415
|
-
planning_exists: path_exists?(cwd, ".
|
|
416
|
-
codebase_dir_exists: path_exists?(cwd, ".
|
|
420
|
+
planning_exists: path_exists?(cwd, ".ariadna_planning"),
|
|
421
|
+
codebase_dir_exists: path_exists?(cwd, ".ariadna_planning/codebase")
|
|
417
422
|
}
|
|
418
423
|
|
|
419
424
|
Output.json(result, raw: raw)
|
|
@@ -424,7 +429,7 @@ module Ariadna
|
|
|
424
429
|
config = ConfigManager.load_config(cwd)
|
|
425
430
|
milestone = get_milestone_info(cwd)
|
|
426
431
|
|
|
427
|
-
phases_dir = File.join(cwd, ".
|
|
432
|
+
phases_dir = File.join(cwd, ".ariadna_planning", "phases")
|
|
428
433
|
phases = []
|
|
429
434
|
current_phase = nil
|
|
430
435
|
next_phase = nil
|
|
@@ -458,7 +463,7 @@ module Ariadna
|
|
|
458
463
|
|
|
459
464
|
phase_entry = {
|
|
460
465
|
number: phase_number, name: phase_name,
|
|
461
|
-
directory: File.join(".
|
|
466
|
+
directory: File.join(".ariadna_planning", "phases", dir),
|
|
462
467
|
status: status, plan_count: plans.length,
|
|
463
468
|
summary_count: summaries.length, has_research: has_research
|
|
464
469
|
}
|
|
@@ -470,7 +475,7 @@ module Ariadna
|
|
|
470
475
|
end
|
|
471
476
|
|
|
472
477
|
paused_at = nil
|
|
473
|
-
state_path = File.join(cwd, ".
|
|
478
|
+
state_path = File.join(cwd, ".ariadna_planning", "STATE.md")
|
|
474
479
|
if File.exist?(state_path)
|
|
475
480
|
state_content = File.read(state_path)
|
|
476
481
|
pause_match = state_content.match(/\*\*Paused At:\*\*\s*(.+)/)
|
|
@@ -491,15 +496,15 @@ module Ariadna
|
|
|
491
496
|
next_phase: next_phase,
|
|
492
497
|
paused_at: paused_at,
|
|
493
498
|
has_work_in_progress: !current_phase.nil?,
|
|
494
|
-
project_exists: path_exists?(cwd, ".
|
|
495
|
-
roadmap_exists: path_exists?(cwd, ".
|
|
496
|
-
state_exists: path_exists?(cwd, ".
|
|
499
|
+
project_exists: path_exists?(cwd, ".ariadna_planning/PROJECT.md"),
|
|
500
|
+
roadmap_exists: path_exists?(cwd, ".ariadna_planning/ROADMAP.md"),
|
|
501
|
+
state_exists: path_exists?(cwd, ".ariadna_planning/STATE.md")
|
|
497
502
|
}
|
|
498
503
|
|
|
499
|
-
result[:state_content] = safe_read_file(File.join(cwd, ".
|
|
500
|
-
result[:roadmap_content] = safe_read_file(File.join(cwd, ".
|
|
501
|
-
result[:project_content] = safe_read_file(File.join(cwd, ".
|
|
502
|
-
result[:config_content] = safe_read_file(File.join(cwd, ".
|
|
504
|
+
result[:state_content] = safe_read_file(File.join(cwd, ".ariadna_planning", "STATE.md")) if includes.include?("state")
|
|
505
|
+
result[:roadmap_content] = safe_read_file(File.join(cwd, ".ariadna_planning", "ROADMAP.md")) if includes.include?("roadmap")
|
|
506
|
+
result[:project_content] = safe_read_file(File.join(cwd, ".ariadna_planning", "PROJECT.md")) if includes.include?("project")
|
|
507
|
+
result[:config_content] = safe_read_file(File.join(cwd, ".ariadna_planning", "config.json")) if includes.include?("config")
|
|
503
508
|
|
|
504
509
|
Output.json(result, raw: raw)
|
|
505
510
|
end
|
|
@@ -509,7 +514,7 @@ module Ariadna
|
|
|
509
514
|
def self.find_phase_internal(cwd, phase)
|
|
510
515
|
return nil unless phase
|
|
511
516
|
|
|
512
|
-
phases_dir = File.join(cwd, ".
|
|
517
|
+
phases_dir = File.join(cwd, ".ariadna_planning", "phases")
|
|
513
518
|
normalized = normalize_phase(phase)
|
|
514
519
|
|
|
515
520
|
return nil unless File.directory?(phases_dir)
|
|
@@ -539,7 +544,7 @@ module Ariadna
|
|
|
539
544
|
end
|
|
540
545
|
|
|
541
546
|
{
|
|
542
|
-
directory: File.join(".
|
|
547
|
+
directory: File.join(".ariadna_planning", "phases", match),
|
|
543
548
|
phase_number: phase_number,
|
|
544
549
|
phase_name: phase_name,
|
|
545
550
|
phase_slug: phase_slug,
|
|
@@ -555,7 +560,7 @@ module Ariadna
|
|
|
555
560
|
end
|
|
556
561
|
|
|
557
562
|
def self.get_milestone_info(cwd)
|
|
558
|
-
roadmap = File.read(File.join(cwd, ".
|
|
563
|
+
roadmap = File.read(File.join(cwd, ".ariadna_planning", "ROADMAP.md"))
|
|
559
564
|
version_match = roadmap.match(/v(\d+\.\d+)/)
|
|
560
565
|
name_match = roadmap.match(/## .*v\d+\.\d+[:\s]+([^\n(]+)/)
|
|
561
566
|
{
|
|
@@ -60,7 +60,7 @@ module Ariadna
|
|
|
60
60
|
Output.error("phase identifier required") unless phase
|
|
61
61
|
|
|
62
62
|
cwd = Dir.pwd
|
|
63
|
-
phases_dir = File.join(cwd, ".
|
|
63
|
+
phases_dir = File.join(cwd, ".ariadna_planning", "phases")
|
|
64
64
|
normalized = normalize_phase_name(phase)
|
|
65
65
|
not_found = { found: false, directory: nil, phase_number: nil, phase_name: nil, plans: [], summaries: [] }
|
|
66
66
|
|
|
@@ -88,7 +88,7 @@ module Ariadna
|
|
|
88
88
|
|
|
89
89
|
result = {
|
|
90
90
|
found: true,
|
|
91
|
-
directory: File.join(".
|
|
91
|
+
directory: File.join(".ariadna_planning", "phases", match),
|
|
92
92
|
phase_number: phase_number,
|
|
93
93
|
phase_name: phase_name,
|
|
94
94
|
plans: plans,
|
|
@@ -104,7 +104,7 @@ module Ariadna
|
|
|
104
104
|
Output.error("phase required") unless phase
|
|
105
105
|
|
|
106
106
|
cwd = Dir.pwd
|
|
107
|
-
phases_dir = File.join(cwd, ".
|
|
107
|
+
phases_dir = File.join(cwd, ".ariadna_planning", "phases")
|
|
108
108
|
normalized = normalize_phase_name(phase)
|
|
109
109
|
|
|
110
110
|
unless File.directory?(phases_dir)
|
|
@@ -128,15 +128,33 @@ module Ariadna
|
|
|
128
128
|
fm = Frontmatter.extract(content)
|
|
129
129
|
summary_name = f.sub(/-PLAN\.md$/i, "-SUMMARY.md")
|
|
130
130
|
has_summary = File.exist?(File.join(dir_path, summary_name))
|
|
131
|
-
{
|
|
131
|
+
{
|
|
132
|
+
file: f, phase: fm["phase"], plan: fm["plan"], wave: fm["wave"],
|
|
133
|
+
type: fm["type"], completed: has_summary,
|
|
134
|
+
domain: fm["domain"] || "general",
|
|
135
|
+
depends_on: fm["depends_on"] || [],
|
|
136
|
+
files_modified: fm["files_modified"] || [],
|
|
137
|
+
autonomous: fm.key?("autonomous") ? fm["autonomous"] : true,
|
|
138
|
+
objective: fm["objective"],
|
|
139
|
+
task_count: content.scan(/<task\b/).count
|
|
140
|
+
}
|
|
132
141
|
end
|
|
133
142
|
|
|
134
|
-
|
|
143
|
+
domains = plans.map { |p| p[:domain] }.uniq
|
|
144
|
+
non_general = domains.reject { |d| d == "general" }
|
|
145
|
+
|
|
146
|
+
Output.json({
|
|
147
|
+
plans: plans, count: plans.size,
|
|
148
|
+
domains: domains,
|
|
149
|
+
domain_count: non_general.size,
|
|
150
|
+
multi_domain: non_general.size >= 2,
|
|
151
|
+
recommend_team: plans.size >= 3 && non_general.size >= 2
|
|
152
|
+
}, raw: raw)
|
|
135
153
|
end
|
|
136
154
|
|
|
137
155
|
def self.list(options, raw: false)
|
|
138
156
|
cwd = Dir.pwd
|
|
139
|
-
phases_dir = File.join(cwd, ".
|
|
157
|
+
phases_dir = File.join(cwd, ".ariadna_planning", "phases")
|
|
140
158
|
|
|
141
159
|
unless File.directory?(phases_dir)
|
|
142
160
|
key = options[:type] ? :files : :directories
|
|
@@ -174,7 +192,7 @@ module Ariadna
|
|
|
174
192
|
def self.next_decimal(base_phase, raw: false)
|
|
175
193
|
Output.error("base phase required") unless base_phase
|
|
176
194
|
cwd = Dir.pwd
|
|
177
|
-
phases_dir = File.join(cwd, ".
|
|
195
|
+
phases_dir = File.join(cwd, ".ariadna_planning", "phases")
|
|
178
196
|
normalized = normalize_phase_name(base_phase)
|
|
179
197
|
|
|
180
198
|
unless File.directory?(phases_dir)
|
|
@@ -204,8 +222,8 @@ module Ariadna
|
|
|
204
222
|
def self.add(description, raw: false)
|
|
205
223
|
Output.error("description required") unless description && !description.empty?
|
|
206
224
|
cwd = Dir.pwd
|
|
207
|
-
phases_dir = File.join(cwd, ".
|
|
208
|
-
roadmap_path = File.join(cwd, ".
|
|
225
|
+
phases_dir = File.join(cwd, ".ariadna_planning", "phases")
|
|
226
|
+
roadmap_path = File.join(cwd, ".ariadna_planning", "ROADMAP.md")
|
|
209
227
|
|
|
210
228
|
existing = if File.directory?(phases_dir)
|
|
211
229
|
Dir.children(phases_dir)
|
|
@@ -234,7 +252,7 @@ module Ariadna
|
|
|
234
252
|
def self.insert(after, description, raw: false)
|
|
235
253
|
Output.error("after phase and description required") unless after && description && !description.empty?
|
|
236
254
|
cwd = Dir.pwd
|
|
237
|
-
phases_dir = File.join(cwd, ".
|
|
255
|
+
phases_dir = File.join(cwd, ".ariadna_planning", "phases")
|
|
238
256
|
normalized = normalize_phase_name(after)
|
|
239
257
|
|
|
240
258
|
# Calculate next decimal
|
|
@@ -259,7 +277,7 @@ module Ariadna
|
|
|
259
277
|
def self.remove(phase, force: false, raw: false)
|
|
260
278
|
Output.error("phase required") unless phase
|
|
261
279
|
cwd = Dir.pwd
|
|
262
|
-
phases_dir = File.join(cwd, ".
|
|
280
|
+
phases_dir = File.join(cwd, ".ariadna_planning", "phases")
|
|
263
281
|
normalized = normalize_phase_name(phase)
|
|
264
282
|
|
|
265
283
|
unless File.directory?(phases_dir)
|
|
@@ -290,7 +308,7 @@ module Ariadna
|
|
|
290
308
|
def self.complete(phase, raw: false)
|
|
291
309
|
Output.error("phase required") unless phase
|
|
292
310
|
cwd = Dir.pwd
|
|
293
|
-
roadmap_path = File.join(cwd, ".
|
|
311
|
+
roadmap_path = File.join(cwd, ".ariadna_planning", "ROADMAP.md")
|
|
294
312
|
normalized = normalize_phase_name(phase)
|
|
295
313
|
|
|
296
314
|
# Mark in ROADMAP.md
|
|
@@ -309,7 +327,7 @@ module Ariadna
|
|
|
309
327
|
cwd = Dir.pwd
|
|
310
328
|
|
|
311
329
|
# Create milestone archive
|
|
312
|
-
archive_dir = File.join(cwd, ".
|
|
330
|
+
archive_dir = File.join(cwd, ".ariadna_planning", "milestones")
|
|
313
331
|
FileUtils.mkdir_p(archive_dir)
|
|
314
332
|
|
|
315
333
|
milestone_name = name || "v#{version}"
|