From f92e62e95962f3a6e382c3c742a7af6005237aa9 Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Fri, 25 Sep 2026 12:36:07 +0300 Subject: [PATCH] gitignore: .archon (junction spre COMUN\.archon, versionat in COMUN) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018YqLHZCrqmvKr5snjKyGkd --- .archon/scripts/analyze_claude.pl | 90 ---- .archon/scripts/analyze_pi.pl | 81 ---- .archon/scripts/claude_extract.pl | 94 ---- .archon/scripts/pi_extract.pl | 104 ----- .archon/scripts/porneste_server.ps1 | 6 - .archon/scripts/raport_context.pl | 163 ------- .archon/scripts/verifica_vfp_text.ps1 | 90 ---- .archon/workflows/roa-fix.yaml | 597 -------------------------- .gitignore | 1 + 9 files changed, 1 insertion(+), 1225 deletions(-) delete mode 100644 .archon/scripts/analyze_claude.pl delete mode 100644 .archon/scripts/analyze_pi.pl delete mode 100644 .archon/scripts/claude_extract.pl delete mode 100644 .archon/scripts/pi_extract.pl delete mode 100644 .archon/scripts/porneste_server.ps1 delete mode 100644 .archon/scripts/raport_context.pl delete mode 100644 .archon/scripts/verifica_vfp_text.ps1 delete mode 100644 .archon/workflows/roa-fix.yaml diff --git a/.archon/scripts/analyze_claude.pl b/.archon/scripts/analyze_claude.pl deleted file mode 100644 index 5618229..0000000 --- a/.archon/scripts/analyze_claude.pl +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/perl -use strict; use warnings; -use JSON::PP; -my $file = shift @ARGV or die "usage: analyze_claude.pl \n"; -my $json = JSON::PP->new; -my %calls; # id -> {name, args, reqts(epoch ms)} -my @results; -open my $fh, '<:encoding(UTF-8)', $file or die $!; -sub to_epoch { - my $iso = shift; - return undef unless $iso; - # 2026-09-24T22:48:53.885Z - if ($iso =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(?:\.(\d+))?Z$/) { - my ($Y,$Mo,$D,$H,$Mi,$S,$ms) = ($1,$2,$3,$4,$5,$6,$7//0); - require Time::Local; - my $epoch = Time::Local::timegm($S,$Mi,$H,$D,$Mo-1,$Y); - return $epoch*1000 + $ms; - } - return undef; -} -while (my $line = <$fh>) { - chomp $line; - next unless length $line; - my $obj = eval { $json->decode($line) }; - next unless $obj; - my $ts = to_epoch($obj->{timestamp}); - my $msg = $obj->{message} or next; - my $role = $msg->{role} // ''; - my $content = $msg->{content}; - next unless ref($content) eq 'ARRAY'; - if ($role eq 'assistant') { - for my $c (@$content) { - next unless ($c->{type}//'') eq 'tool_use'; - my $args = ''; - if (ref($c->{input}) eq 'HASH') { - $args = $c->{input}{command} // $c->{input}{file_path} // $c->{input}{pattern} // ''; - $args = substr((eval{$json->encode($c->{input})}//''),0,200) unless $args; - } - $calls{$c->{id}} = { name => $c->{name}, args => $args, reqts => $ts }; - } - } elsif ($role eq 'user') { - for my $c (@$content) { - next unless ($c->{type}//'') eq 'tool_result'; - my $iserror = $c->{is_error} ? 1 : 0; - my $snippet = ''; - if ($iserror) { - my $ct = $c->{content}; - if (ref($ct) eq 'ARRAY') { $snippet = substr($ct->[0]{text}//'',0,300); } - elsif (!ref($ct)) { $snippet = substr($ct//'',0,300); } - } - push @results, { id => $c->{tool_use_id}, rests => $ts, iserror => $iserror, snippet => $snippet }; - } - } -} -close $fh; - -my @rows; -for my $r (@results) { - my $c = $calls{$r->{id}} or next; - my $dur = ($r->{rests} && $c->{reqts}) ? ($r->{rests} - $c->{reqts}) : undef; - push @rows, { name => $c->{name}, args => $c->{args}, dur => $dur, iserror => $r->{iserror}, snippet => $r->{snippet} }; -} - -my %cnt; $cnt{$_->{name}}++ for @rows; -print "=== tool counts ===\n"; -for my $k (sort { $cnt{$b} <=> $cnt{$a} } keys %cnt) { print "$k: $cnt{$k}\n"; } - -print "\n=== top 10 longest ===\n"; -my @sorted = sort { ($b->{dur}//0) <=> ($a->{dur}//0) } @rows; -for my $i (0..9) { - last unless $sorted[$i]; - my $row = $sorted[$i]; - my $a = $row->{args}; $a =~ s/\s+/ /g; $a = substr($a,0,100); - printf "%8dms %-10s %s\n", ($row->{dur}//-1), $row->{name}, $a; -} - -print "\n=== errors ===\n"; -my $ec = 0; -for my $row (@rows) { - next unless $row->{iserror}; - $ec++; - my $a = $row->{args}; $a =~ s/\s+/ /g; $a = substr($a,0,150); - my $s = $row->{snippet}; $s =~ s/\s+/ /g; $s = substr($s,0,200); - print "dur=".($row->{dur}//'?')."ms CMD: $a\n ERR: $s\n"; -} -print "total errors: $ec\n"; - -my $totaldur = 0; $totaldur += ($_->{dur}//0) for @rows; -print "\n=== total tool time (sum durations, ms) === $totaldur\n"; -print "=== total tool calls with duration === " . scalar(@rows) . "\n"; diff --git a/.archon/scripts/analyze_pi.pl b/.archon/scripts/analyze_pi.pl deleted file mode 100644 index e5580e8..0000000 --- a/.archon/scripts/analyze_pi.pl +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/perl -use strict; use warnings; -use JSON::PP; -my $file = shift @ARGV or die "usage: analyze_pi.pl [startline] [endline]\n"; -my $startline = shift @ARGV || 1; -my $endline = shift @ARGV || 1e9; -my $json = JSON::PP->new; -my %calls; # id -> {name, args, reqts} -my @results; # {id, name, rests, iserror, errsnippet} -open my $fh, '<:encoding(UTF-8)', $file or die $!; -my $ln = 0; -while (my $line = <$fh>) { - $ln++; - next if $ln < $startline || $ln > $endline; - chomp $line; - next unless length $line; - my $obj = eval { $json->decode($line) }; - next unless $obj; - my $msg = $obj->{message} or next; - if (($msg->{role} // '') eq 'assistant') { - my $ts = $msg->{timestamp}; - for my $c (@{$msg->{content} || []}) { - next unless ($c->{type} // '') eq 'toolCall'; - my $argstr = ''; - if ($c->{arguments}) { - $argstr = $c->{arguments}{command} // $c->{arguments}{path} // $c->{arguments}{pattern} // encode_json_short($c->{arguments}); - } - $calls{$c->{id}} = { name => $c->{name}, args => $argstr, reqts => $ts }; - } - } elsif (($msg->{role} // '') eq 'toolResult') { - my $ts = $msg->{timestamp}; - my $iserror = $msg->{isError} ? 1 : 0; - my $snippet = ''; - if ($iserror) { - for my $c (@{$msg->{content} || []}) { - if (($c->{type}//'') eq 'text') { $snippet = substr($c->{text}//'',0,300); last; } - } - } - push @results, { id => $msg->{toolCallId}, name => $msg->{toolName}, rests => $ts, iserror => $iserror, snippet => $snippet }; - } -} -close $fh; - -sub encode_json_short { my $h = shift; my $s = eval { $json->encode($h) } // ''; return substr($s,0,200); } - -# join -my @rows; -for my $r (@results) { - my $c = $calls{$r->{id}}; - next unless $c; - my $dur = ($r->{rests} && $c->{reqts}) ? ($r->{rests} - $c->{reqts}) : undef; - push @rows, { name => $c->{name}, args => $c->{args}, dur => $dur, iserror => $r->{iserror}, snippet => $r->{snippet}, reqts=>$c->{reqts}, rests=>$r->{rests} }; -} - -# counts by tool name -my %cnt; -$cnt{$_->{name}}++ for @rows; -print "=== tool counts ===\n"; -for my $k (sort { $cnt{$b} <=> $cnt{$a} } keys %cnt) { print "$k: $cnt{$k}\n"; } - -print "\n=== top 10 longest ===\n"; -my @sorted = sort { ($b->{dur}//0) <=> ($a->{dur}//0) } @rows; -for my $i (0..9) { - last unless $sorted[$i]; - my $row = $sorted[$i]; - my $a = $row->{args}; $a =~ s/\s+/ /g; $a = substr($a,0,100); - printf "%8dms %-6s %s\n", ($row->{dur}//-1), $row->{name}, $a; -} - -print "\n=== errors ===\n"; -for my $row (@rows) { - next unless $row->{iserror}; - my $a = $row->{args}; $a =~ s/\s+/ /g; $a = substr($a,0,150); - my $s = $row->{snippet}; $s =~ s/\s+/ /g; $s = substr($s,0,200); - print "reqts=$row->{reqts} rests=$row->{rests} dur=".($row->{dur}//'?')."ms\n CMD: $a\n ERR: $s\n"; -} - -my $totaldur = 0; -$totaldur += ($_->{dur}//0) for @rows; -print "\n=== total tool time (sum durations, ms) === $totaldur\n"; -print "=== total tool calls with duration === " . scalar(@rows) . "\n"; diff --git a/.archon/scripts/claude_extract.pl b/.archon/scripts/claude_extract.pl deleted file mode 100644 index b2908e3..0000000 --- a/.archon/scripts/claude_extract.pl +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/perl -use strict; use warnings; -use JSON::PP; -use Time::Local; - -my ($file, $cutoff_start_iso, $cutoff_end_iso) = @ARGV; # optional: only count entries in [start,end] - -sub iso_to_epoch { - my ($s) = @_; - return 0 unless defined $s; - if ($s =~ /(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)\.(\d+)Z/) { - return timegm($6,$5,$4,$3,$2-1,$1) * 1000 + $7; - } - return 0; -} -my $cutoff_start = $cutoff_start_iso ? iso_to_epoch($cutoff_start_iso) : 0; -my $cutoff_end = $cutoff_end_iso ? iso_to_epoch($cutoff_end_iso) : 0; - -open(my $fh, "<:encoding(UTF-8)", $file) or die $!; -my $nAssistant=0; my %toolCounts; -my %callById; # toolu_id -> {name,input,issued_ts} -my @durs; my @errs; -my $maxCtx=0; my $sumIn=0; my $sumOut=0; -my $firstTs; my $lastTs; - -while (my $line = <$fh>) { - chomp $line; - next unless $line; - my $obj = eval { decode_json($line) }; - next unless $obj; - my $ts = iso_to_epoch($obj->{timestamp}); - next unless $ts; - next if $cutoff_start && $ts < $cutoff_start; - next if $cutoff_end && $ts > $cutoff_end; - $firstTs = $ts if !defined($firstTs) || $ts < $firstTs; - $lastTs = $ts if !defined($lastTs) || $ts > $lastTs; - - if ($obj->{type} eq 'assistant') { - $nAssistant++; - my $msg = $obj->{message}; - my $usage = $msg->{usage}; - if ($usage) { - my $ctx = ($usage->{input_tokens}//0) + ($usage->{cache_read_input_tokens}//0) + ($usage->{cache_creation_input_tokens}//0); - $maxCtx = $ctx if $ctx > $maxCtx; - $sumIn += $ctx; $sumOut += ($usage->{output_tokens}//0); - } - for my $c (@{$msg->{content}}) { - if ($c->{type} eq 'tool_use') { - $toolCounts{$c->{name}}++; - $callById{$c->{id}} = { name=>$c->{name}, input=>encode_json($c->{input}), issued=>$ts }; - } - } - } elsif ($obj->{type} eq 'user') { - my $msg = $obj->{message}; - next unless ref($msg->{content}) eq 'ARRAY'; - for my $c (@{$msg->{content}}) { - next unless $c->{type} && $c->{type} eq 'tool_result'; - my $tcid = $c->{tool_use_id}; - my $call = $callById{$tcid}; - next unless $call; - my $dur = $ts - $call->{issued}; - my $isErr = $c->{is_error} ? 1 : 0; - my $text = ref($c->{content}) ? encode_json($c->{content}) : ($c->{content}//''); - push @durs, { name=>$call->{name}, input=>$call->{input}, dur=>$dur, isError=>$isErr, err=>substr($text,0,200) }; - push @errs, $durs[-1] if $isErr; - } - } -} - -@durs = sort { $b->{dur} <=> $a->{dur} } @durs; - -print "=== $file ===\n"; -print "cutoff: $cutoff_start_iso .. ", ($cutoff_end_iso//''), "\n" if $cutoff_start_iso; -print "assistant turns: $nAssistant\n"; -print "tool calls total: ", scalar(keys %callById), "\n"; -print "tool calls by type: "; for my $k (sort keys %toolCounts) { print "$k=$toolCounts{$k} "; } print "\n"; -print "max context (in+cache_read+cache_creation) single call: $maxCtx sum_in(approx): $sumIn sum_out: $sumOut\n"; -print "span: ", (($lastTs-$firstTs)//0)/1000, "s\n"; -my $toolTimeSum = 0; $toolTimeSum += $_->{dur} for @durs; -print "total tool time (sum all calls): ", $toolTimeSum/1000, "s\n"; -print "--- top 10 longest tool calls ---\n"; -for my $i (0..9) { - last unless $durs[$i]; - my $d = $durs[$i]; - my $a = $d->{input}; $a =~ s/\s+/ /g; $a = substr($a,0,100); - printf("%7.1fs %-10s %s %s\n", $d->{dur}/1000, $d->{name}, $a, ($d->{isError}?"ERROR":"")); -} -print "--- errors (", scalar(@errs), ") ---\n"; -for my $d (@errs) { - my $a = $d->{input}; $a =~ s/\s+/ /g; $a = substr($a,0,100); - my $e = $d->{err}; $e =~ s/\s+/ /g; - print "$d->{name} $a :: $e\n"; -} -# sum total tool time (appended quick calc, reuse @durs if still in scope - not, so separate script) diff --git a/.archon/scripts/pi_extract.pl b/.archon/scripts/pi_extract.pl deleted file mode 100644 index 1e0a3c8..0000000 --- a/.archon/scripts/pi_extract.pl +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/perl -use strict; use warnings; -use JSON::PP; -use Time::Local; - -my ($file, $cutoff_iso) = @ARGV; # cutoff_iso optional: only count entries with timestamp >= this -my $cutoff = 0; -if ($cutoff_iso) { - $cutoff = iso_to_epoch($cutoff_iso); -} - -sub iso_to_epoch { - my ($s) = @_; - return 0 unless defined $s; - if ($s =~ /^\d+$/) { return $s + 0; } # already epoch ms - if ($s =~ /(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)\.(\d+)Z/) { - return timegm($6,$5,$4,$3,$2-1,$1) * 1000 + $7; - } - return 0; -} - -open(my $fh, "<:encoding(UTF-8)", $file) or die $!; -my @msgs; -while (my $line = <$fh>) { - chomp $line; - next unless $line; - my $obj = eval { decode_json($line) }; - next unless $obj; - next unless $obj->{type} eq "message"; - my $ts = iso_to_epoch($obj->{message}{timestamp} // $obj->{timestamp} // ''); - next if $cutoff && $ts < $cutoff; - push @msgs, { obj=>$obj, ts=>$ts }; -} - -my $nAssistant=0; my %toolCounts; my @calls; # each: name,args,issued_ts,id -my %callById; -my @results; # {id, ts, isError, textlen} -my $totalInTok=0; my $totalOutTok=0; my $maxInTok=0; -my $firstTs; my $lastTs; - -for my $m (@msgs) { - my $obj = $m->{obj}; - my $role = $obj->{message}{role} // '?'; - $firstTs = $m->{ts} if !defined($firstTs) || $m->{ts} < $firstTs; - $lastTs = $m->{ts} if !defined($lastTs) || $m->{ts} > $lastTs; - if ($role eq 'assistant') { - $nAssistant++; - my $usage = $obj->{message}{usage}; - if ($usage) { - my $in = $usage->{input} // $usage->{inputTokens} // $usage->{prompt_tokens} // 0; - my $out = $usage->{output} // $usage->{outputTokens} // $usage->{completion_tokens} // 0; - $totalInTok += $in; $totalOutTok += $out; - $maxInTok = $in if $in > $maxInTok; - } - for my $c (@{$obj->{message}{content}}) { - if ($c->{type} eq 'toolCall') { - $toolCounts{$c->{name}}++; - my $argstr = encode_json($c->{arguments}); - $callById{$c->{id}} = { name=>$c->{name}, args=>$argstr, issued=>$m->{ts} }; - } - } - } elsif ($role eq 'toolResult') { - my $tcid = $obj->{message}{toolCallId}; - my $isErr = $obj->{message}{isError} ? 1 : 0; - my $text = ''; - for my $c (@{$obj->{message}{content}}) { $text .= ($c->{text}//'') if $c->{type} eq 'text'; } - push @results, { id=>$tcid, ts=>$m->{ts}, isError=>$isErr, text=>substr($text,0,200) }; - } -} - -# compute durations: result.ts - issued.ts (per call) -my @durs; -for my $r (@results) { - my $c = $callById{$r->{id}}; - next unless $c; - my $dur = $r->{ts} - $c->{issued}; - push @durs, { name=>$c->{name}, args=>$c->{args}, dur=>$dur, isError=>$r->{isError}, err=>$r->{text} }; -} -@durs = sort { $b->{dur} <=> $a->{dur} } @durs; - -print "=== $file ===\n"; -print "cutoff: $cutoff_iso ($cutoff)\n" if $cutoff_iso; -print "assistant turns: $nAssistant\n"; -print "tool calls total: ", scalar(keys %callById), "\n"; -print "tool calls by type: "; for my $k (sort keys %toolCounts) { print "$k=$toolCounts{$k} "; } print "\n"; -print "total input tokens (sum): $totalInTok max single-call input: $maxInTok total output tokens: $totalOutTok\n"; -print "span: ", ($lastTs-$firstTs)/1000, "s first=$firstTs last=$lastTs\n"; -my $toolTimeSum = 0; $toolTimeSum += $_->{dur} for @durs; -print "total tool time (sum all calls): ", $toolTimeSum/1000, "s\n"; -print "--- top 10 longest tool calls ---\n"; -for my $i (0..9) { - last unless $durs[$i]; - my $d = $durs[$i]; - my $a = $d->{args}; $a =~ s/\s+/ /g; $a = substr($a,0,100); - printf("%7.1fs %-8s %s %s\n", $d->{dur}/1000, $d->{name}, $a, ($d->{isError}?"ERROR":"")); -} -print "--- errors ---\n"; -for my $d (@durs) { - if ($d->{isError}) { - my $a = $d->{args}; $a =~ s/\s+/ /g; $a = substr($a,0,100); - my $e = $d->{err}; $e =~ s/\s+/ /g; - print "$d->{name} $a :: $e\n"; - } -} diff --git a/.archon/scripts/porneste_server.ps1 b/.archon/scripts/porneste_server.ps1 deleted file mode 100644 index 7dfe2eb..0000000 --- a/.archon/scripts/porneste_server.ps1 +++ /dev/null @@ -1,6 +0,0 @@ -# Porneste serverul web Archon (port 3090, publicat pe tailnet prin tailscale serve) -foreach ($n in 'CLAUDE_USE_GLOBAL_AUTH','CLAUDE_BIN_PATH','ARCHON_TELEMETRY_DISABLED','OPENCODE_GO_API_KEY') { - Set-Item "env:$n" ([Environment]::GetEnvironmentVariable($n, 'User')) -} -Set-Location D:\roa\roacont -& "C:\Users\mmari\.archon\bin\archon.exe" serve diff --git a/.archon/scripts/raport_context.pl b/.archon/scripts/raport_context.pl deleted file mode 100644 index e0e4084..0000000 --- a/.archon/scripts/raport_context.pl +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/perl -# Genereaza tabelul de varf-context + timp per nod pentru o rulare roa-fix. -# Sursa: archon.db (evenimente node_started/node_completed, exacte) pentru -# fereastra de timp a fiecarui nod, apoi sesiunile brute de pe disc (Claude -# .jsonl / Pi .jsonl) pentru varful REAL de context (max per apel, nu suma). -# Vezi docs/pilot_archon_diagnoza_47.md, sectiunea "Finalizare workflow". -use strict; use warnings; -use JSON::PP; -use Time::Local; - -my ($run_id) = @ARGV; # opțional; gol/lipsă -> auto-detectat (ultimul run roa-fix din archon.db) -my $SCRIPT_DIR = $0; $SCRIPT_DIR =~ s{[\\/][^\\/]+$}{}; -my $SQLITE = "D:/roa/roacont/sqlite3.exe"; -my $DB = "C:/Users/mmari/.archon/archon.db"; -my $CLAUDE_DIR = "C:/Users/mmari/.claude/projects/D--ROA-ROACONT"; -my $PI_DIR = "C:/Users/mmari/.pi/agent/sessions/--D--ROA-ROACONT--"; -my $THRESHOLD = 200000; - -# nod -> provider, doar nodurile AI din roa-fix.yaml (bash/approval sar peste) -my %PROVIDER = ( - plan => 'claude', - plan_review => 'claude', - implement => 'pi', - implement_retry => 'pi', - escaladare => 'claude', - review => 'pi', - escaladare_review => 'claude', - review2 => 'pi', - invatare => 'claude', - aplica_doc => 'pi', -); -my @ORDER = qw(plan plan_review implement implement_retry escaladare review escaladare_review review2 invatare aplica_doc); - -sub sqlite_rows { - # -ascii: coloane separate cu 0x1F, RANDURI separate cu 0x1E (nu \n) - unele - # campuri (ex. eroarea PowerShell capturata de nodul `verifica`) contin \r\n - # BRUT, necodat, in JSON-ul din coloana `data`; citirea linie-cu-linie (\n) - # desincroniza toate randurile de dupa primul astfel de camp si raporta - # gresit "toate nodurile skipped" (confirmat 25.09 pe run-ul real 3c029727, - # vezi docs/pilot_archon_diagnoza_47.md). 0x1E nu apare in text normal. - my ($sql) = @_; - open(my $fh, "-|", $SQLITE, "-ascii", $DB, $sql) or die "sqlite3: $!"; - local $/; - my $out = <$fh> // ''; - close $fh; - my @rows; - for my $rec (split /\x1e/, $out) { - next if $rec eq '' || $rec eq "\n"; - push @rows, [split /\x1f/, $rec, -1]; - } - return @rows; -} - -sub iso_to_epoch_ms { - my ($s) = @_; # "YYYY-MM-DD HH:MM:SS" (UTC, din sqlite datetime('now')) - return 0 unless $s && $s =~ /^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/; - return timegm($6,$5,$4,$3,$2-1,$1) * 1000; -} -sub epoch_ms_to_iso { # -> "YYYY-MM-DDTHH:MM:SS.000Z" (pt claude_extract.pl/pi_extract.pl) - my ($ms) = @_; - my @t = gmtime(int($ms/1000)); - return sprintf("%04d-%02d-%02dT%02d:%02d:%02d.000Z", $t[5]+1900,$t[4]+1,$t[3],$t[2],$t[1],$t[0]); -} - -unless ($run_id) { - my @rows = sqlite_rows("SELECT id FROM remote_agent_workflow_runs WHERE workflow_name='roa-fix' AND working_path LIKE '%ROACONT%' ORDER BY started_at DESC LIMIT 1;"); - $run_id = $rows[0] ? $rows[0][0] : ''; -} -unless ($run_id) { - print "Nu am gasit niciun run roa-fix in archon.db (working_path ROACONT). Tabel neconstruit.\n"; - exit 0; -} -print "run_id folosit: $run_id\n"; - -# ia ULTIMUL node_completed per step_name (in caz de resume/retry pe acelasi run_id) -my @evrows = sqlite_rows("SELECT step_name, created_at, data FROM remote_agent_workflow_events WHERE workflow_run_id='$run_id' AND event_type='node_completed' ORDER BY event_order;"); -my %node; # step_name -> {end_ms, duration_ms} -for my $r (@evrows) { - my ($step, $created_at, $data) = @$r; - next unless exists $PROVIDER{$step}; - my $obj = eval { decode_json($data) }; - next unless $obj && defined $obj->{duration_ms}; - my $end_ms = iso_to_epoch_ms($created_at); - $node{$step} = { end_ms => $end_ms, duration_ms => $obj->{duration_ms} }; -} - -sub find_claude_file { - my ($end_ms) = @_; - return undef unless -d $CLAUDE_DIR; - opendir(my $dh, $CLAUDE_DIR) or return undef; - my ($best, $bestdiff); - for my $f (readdir $dh) { - next unless $f =~ /\.jsonl$/; - my $path = "$CLAUDE_DIR/$f"; - my @st = stat($path); next unless @st; - my $mtime_ms = $st[9] * 1000; - my $diff = $mtime_ms - $end_ms; # asteptat >=0, fisierul se scrie la/dupa finalul nodului - next if $diff < -5000 || $diff > 120000; # toleranta -5s..+120s - if (!defined($bestdiff) || abs($diff) < abs($bestdiff)) { $best = $path; $bestdiff = $diff; } - } - closedir $dh; - return $best; -} - -sub find_pi_file { - my ($start_ms) = @_; - return undef unless -d $PI_DIR; - opendir(my $dh, $PI_DIR) or return undef; - my ($best, $bestdiff); - for my $f (readdir $dh) { - next unless $f =~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z_/; - my $fts_ms = timegm($6,$5,$4,$3,$2-1,$1) * 1000 + $7; - my $diff = $fts_ms - $start_ms; - next if abs($diff) > 5000; # numele fisierului Pi contine timestamp-ul de start exact - if (!defined($bestdiff) || abs($diff) < abs($bestdiff)) { $best = "$PI_DIR/$f"; $bestdiff = $diff; } - } - closedir $dh; - return $best; -} - -my @table; # {node, provider, duration_s, peak, note} -for my $nid (@ORDER) { - my $n = $node{$nid}; - unless ($n) { - push @table, { node=>$nid, provider=>$PROVIDER{$nid}, duration_s=>'-', peak=>'-', note=>'nu a rulat (skipped)' }; - next; - } - my $provider = $PROVIDER{$nid}; - my $start_ms = $n->{end_ms} - $n->{duration_ms}; - my $duration_s = sprintf("%.1f", $n->{duration_ms}/1000); - my ($peak, $note) = ('?', ''); - if ($provider eq 'claude') { - my $file = find_claude_file($n->{end_ms}); - if ($file) { - my $start_iso = epoch_ms_to_iso($start_ms - 2000); - my $end_iso = epoch_ms_to_iso($n->{end_ms} + 2000); - my $out = `perl "$SCRIPT_DIR/claude_extract.pl" "$file" "$start_iso" "$end_iso" 2>&1`; - if ($out =~ /max context[^:]*:\s*(\d+)/) { $peak = $1; } - $note = "fisier: $file"; - } else { - $note = 'sesiune Claude negasita (fereastra de timp fara potrivire)'; - } - } else { - my $file = find_pi_file($start_ms); - if ($file) { - my $start_iso = epoch_ms_to_iso($start_ms); - my $out = `perl "$SCRIPT_DIR/pi_extract.pl" "$file" "$start_iso" 2>&1`; - if ($out =~ /max single-call input:\s*(\d+)/) { $peak = $1; } - $note = "fisier: $file"; - } else { - $note = 'sesiune Pi negasita (fereastra de timp fara potrivire)'; - } - } - if ($peak ne '?' && $peak >= $THRESHOLD) { $note = "ATENTIE: varf $peak >= $THRESHOLD. $note"; } - push @table, { node=>$nid, provider=>$provider, duration_s=>$duration_s, peak=>$peak, note=>$note }; -} - -print "\n| nod | provider | durata (s) | varf context | nota |\n"; -print "|---|---|---|---|---|\n"; -for my $row (@table) { - my $flag = ($row->{peak} ne '?' && $row->{peak} ne '-' && $row->{peak} >= $THRESHOLD) ? 'ATENTIE' : ''; - printf "| %s | %s | %s | %s | %s %s |\n", $row->{node}, $row->{provider}, $row->{duration_s}, $row->{peak}, $flag, $row->{note}; -} diff --git a/.archon/scripts/verifica_vfp_text.ps1 b/.archon/scripts/verifica_vfp_text.ps1 deleted file mode 100644 index 698ca79..0000000 --- a/.archon/scripts/verifica_vfp_text.ps1 +++ /dev/null @@ -1,90 +0,0 @@ -<# -Verificare mecanica dupa implement, pentru workflow-ul roa-fix (pilot Archon). -Pentru fiecare fisier dat (implicit: git diff --name-only HEAD + fisiere noi netracked, -in ProjectRoot): - 1. EF BF BD absent din tot fisierul (semnul coruperii cp1250/cp1252 -> UTF-8 replacement char). - 2. Zero LF izolat (CRLF pe tot fisierul) - conteaza octeti pe disc, nu string decodat. - 3. Pentru .vc2/.sc2: txt2vcx.ps1 -DryRun trebuie sa reuseasca (fidelity-check). -Iesire: 0 daca toate fisierele trec toate verificarile; 1 la orice esec (cu motivul pe fisier). -#> -param( - [string]$ProjectRoot = "D:\roa\roacont", - [string[]]$Files -) - -$ErrorActionPreference = "Stop" -Set-Location $ProjectRoot - -if (-not $Files -or $Files.Count -eq 0) { - $tracked = git diff --name-only HEAD 2>$null - $untracked = git ls-files --others --exclude-standard 2>$null - # COMUN e repo git separat, exclus din repo-ul proiectului - $comun = @(git -C COMUN diff --name-only HEAD 2>$null) + @(git -C COMUN ls-files --others --exclude-standard 2>$null) | Where-Object { $_ } | Where-Object { $_ -match ".(prg|vc2|sc2|fr2|mn2|h)$" } | ForEach-Object { "COMUN/$_" } - $Files = @($tracked) + @($untracked) + @($comun) | Where-Object { $_ -match ".(prg|vc2|sc2|fr2|mn2|h)$" } | Sort-Object -Unique -} - -if (-not $Files -or $Files.Count -eq 0) { - Write-Output "Niciun fisier modificat - nimic de verificat." - exit 0 -} - -$failures = @() - -foreach ($f in $Files) { - $full = Join-Path $ProjectRoot $f - if (-not (Test-Path $full)) { - Write-Output "SKIP $f (sters sau inexistent)" - continue - } - - $bytes = [IO.File]::ReadAllBytes($full) - - # 1. EF BF BD absent - $badSeq = 0 - for ($i = 0; $i -lt $bytes.Length - 2; $i++) { - if ($bytes[$i] -eq 0xEF -and $bytes[$i+1] -eq 0xBF -and $bytes[$i+2] -eq 0xBD) { $badSeq++ } - } - if ($badSeq -gt 0) { - $failures += "$f : $badSeq octet(i) EF BF BD (corupere cp1250/cp1252 -> UTF-8 replacement char)" - continue - } - - # 2. CRLF pe tot fisierul (zero LF izolat) - $lf = 0; $crlf = 0 - for ($i = 0; $i -lt $bytes.Length; $i++) { - if ($bytes[$i] -eq 0x0A) { - $lf++ - if ($i -gt 0 -and $bytes[$i-1] -eq 0x0D) { $crlf++ } - } - } - $isolated = $lf - $crlf - if ($isolated -ne 0) { - $failures += "$f : $isolated LF izolat (fisierul nu mai e CRLF pe tot)" - continue - } - - # 3. txt2vcx.ps1 -DryRun pentru .vc2/.sc2 - $ext = [IO.Path]::GetExtension($f).ToLowerInvariant() - if ($ext -eq ".vc2" -or $ext -eq ".sc2") { - # tintele de sub COMUN\ cer -AllowComun (DryRun nu scrie nimic) - $argv = @('-ExecutionPolicy', 'Bypass', '-File', 'D:\ROA\UTIL\foxbin2prg\txt2vcx.ps1', - '-TextFile', $full, '-ProjectRoot', $ProjectRoot, '-CacheRoot', $ProjectRoot, '-DryRun') - if ($f -match '^COMUN[\\/]') { $argv += '-AllowComun' } - & powershell $argv 2>&1 | Out-Null - if ($LASTEXITCODE -ne 0) { - $failures += "$f : txt2vcx.ps1 -DryRun a esuat (exit $LASTEXITCODE)" - continue - } - } - - Write-Output "OK $f" -} - -if ($failures.Count -gt 0) { - Write-Output "--- ESECURI ---" - $failures | ForEach-Object { Write-Output $_ } - exit 1 -} - -Write-Output "Toate fisierele au trecut verificarile." -exit 0 diff --git a/.archon/workflows/roa-fix.yaml b/.archon/workflows/roa-fix.yaml deleted file mode 100644 index a1973e5..0000000 --- a/.archon/workflows/roa-fix.yaml +++ /dev/null @@ -1,597 +0,0 @@ -name: roa-fix -description: | - Pilot ROA: plan (Opus, cu auto-review eng inglobat) -> aprobare plan -> implementare - (Pi/DeepSeek, write-back+test permise dupa -DryRun) -> verificare mecanica - (cp1252/CRLF/txt2vcx -DryRun) cu 1 reincercare si escaladare la Opus -> review - (Pi/DeepSeek, cu acces la cod) cu escaladare la Opus pe verdict BLOCANT -> re-review - dupa escaladare (verdict vizibil, fara bucla infinita) -> control fisiere suspecte -> - propunere de documentare (nvatare, neaplicata) -> diff in docs/ -> aprobare finala - (arata si propunerea de doc) -> aplicare doc aprobat. - Commit-ul (git/svn) ramane manual, in afara workflow-ului. - -worktree: - enabled: false -provider: claude -interactive: true - -nodes: - # ============================================================ - # a. PLAN (Opus) - citeste regulile, localizeaza codul, confirma headless - # presupunerile critice, scrie planul, se auto-revizuieste (eng review inglobat) - # ============================================================ - - id: plan - model: opus - idle_timeout: 900000 - skills: [roa-vfp-text-edit, roa-vfp-headless-test, roa-vfp-null-guards, roa-vfp-go-recno, roa-oracle-sqlexec-no-data] - prompt: | - Sarcina ROA de planificat: $ARGUMENTS - - Esti agentul de PLANIFICARE (nu implementezi, doar citesti, probezi headless si scrii - planul). - - ## Pasi obligatorii - 1. Citeste `CLAUDE.md` (radacina proiectului) - context, layout, reguli de versionare. - 2. Citeste `COMUN\docs\reguli_lucru.md` integral, in special punctul 7 (rutare pe zona - atinsa) - identifica ce skill-uri/docs sunt obligatorii pentru sarcina de mai sus. - Citeste INTEGRAL (nu doar titlul) fiecare doc de conventie din zona atinsa pe care - punctul 7 il indica (ex. conventii `oExecute`/`goExecutor`, ALTER TABLE, NULL, GO/Recno). - In plan, la fiecare decizie relevanta, citeaza regula aplicabila `fisier:linie`. Daca - solutia aleasa CONTRAZICE un doc de conventie, scrie explicit de ce (nu il ignora tacut). - 3. Localizeaza codul relevant. **Niciodata `grep -r`/`grep -rn` pe tot arborele - `D:\ROA\ROACONT` fara scop** (masurat: un singur `grep -rn` nescopat in aceasta faza a - costat 120s intr-o rulare anterioara, cel mai lung apel din nodul `plan`). Foloseste - `rg` cu excluderi (`rg --glob '!.svn' --glob '!*.exe' --glob '!*.fxp' --glob '!*.vct' - --glob '!*.sct' `) sau scopeaza pe director/extensie. Pentru cod in - `.vc2`/`.sc2`, foloseste `vfp_symbols.ps1` (nu Grep simplu - nu poate spune carei - clase/metode apartine un hit): - ``` - $s = 'D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1' - $c = @('-CacheRoot', 'D:\ROA\ROACONT', '-ProjectRoot', 'D:\ROA\ROACONT', '-IndexFile', 'D:\ROA\_vfp_textcache\roacont\_symbols.tsv') - powershell -ExecutionPolicy Bypass -File $s @c -Grep '' -CodeOnly - powershell -ExecutionPolicy Bypass -File $s @c -Find '' - ``` - Ruleaza intai `git_sync.ps1` daca textul `.??2` pare vechi fata de binar. - 4. **Proba headless obligatorie pentru orice presupunere critica de runtime.** Daca planul - se bazeaza pe un comportament neverificat (ex. "ALTER TABLE e permis pe acest cursor", - "acest camp Oracle nu poate fi NULL", "GO pe acest Recno e stabil intre requery-uri"), - scrie si ruleaza O PROBA MICA SI RAPIDA headless (`.prg` de test, in scratchpad, sters - dupa) care demonstreaza comportamentul PE CALEA REALA (nu pe un cursor izolat de test) - inainte de a scrie planul pe baza acelei presupuneri. Motiv: intr-o rulare anterioara - (f50d54a2), presupunerea "ALTER TABLE permis pe cursor rematerializat" nu a fost - verificata pe lantul real `oExecute` -> a picat cu eroarea 1115, iar reparatia a costat - 42 min de escaladare Opus. Include in plan, la sectiunea "Verificari", dovada probei - (comanda + rezultat pe scurt). - 5. Scrie planul in `docs/plan_.md` (`` = un nume scurt kebab-case derivat din - sarcina). Planul e fisier-cu-fisier, cu `fisier:linie` exact pentru fiecare schimbare, - modificari MINIME (doar ce s-a cerut, nimic in plus). Include sectiune "Verificari" cu - ce trebuie sa treaca (cens octeti, CRLF, txt2vcx -DryRun, teste, proba headless de la - pasul 4) si sectiune "Conventii citate" cu regulile de la pasul 2. - 6. Clasifica sarcina pentru nodul urmator de review (`plan_review`), campul `tip_sarcina`: - `"ui"` daca sarcina atinge un formular/grid/UI (colorari, layout, interactiune), - `"mare"` daca schimba scope sau atinge mai multe module/zone, `"ui_mare"` daca ambele, - altfel `"simplu"`. NU faci tu auto-review-ul (asta e in nodul separat `plan_review`, - care ruleaza skill-urile gstack reale, nu un checklist inglobat aici). - 7. NU edita niciun fisier de cod in acest pas (doar proba headless de la pasul 4, care se - sterge dupa). - - La final raspunde STRICT cu campurile cerute de output_format (plan_file = calea relativa - a fisierului de plan, ex. `docs/plan_exemplu.md`). - output_format: - type: object - properties: - plan_file: { type: string } - summary: { type: string } - tip_sarcina: { type: string, enum: [simplu, ui, mare, ui_mare] } - required: [plan_file, tip_sarcina] - - # ============================================================ - # a2. PLAN_REVIEW (Opus) - ruleaza REAL skill-urile gstack de review pe plan, - # headless (auto-decide pe AskUserQuestion, nu exista utilizator). - # Verificat empiric 25.09 (scratchpad final_wf/smoke_repo): nod cu - # skills: [plan-eng-review], context: fresh, ruleaza complet in ~78s, - # varf context 76k, 0 blocaje pe cele 7 AskUserQuestion intalnite - - # modelul a auto-decis pe fiecare, conform instructiunii din prompt. - # ============================================================ - - id: plan_review - depends_on: [plan] - model: opus - context: fresh - idle_timeout: 900000 - skills: [plan-eng-review, plan-design-review, plan-ceo-review] - prompt: | - Ruleaza skill-ul `plan-eng-review` REAL (tool-ul Skill, nu un checklist inglobat) pe - fisierul de plan $plan.output.plan_file. - - tip_sarcina din nodul anterior: $plan.output.tip_sarcina - - Daca tip_sarcina e "ui" sau "ui_mare", ruleaza SI skill-ul `plan-design-review` pe - acelasi fisier. - - Daca tip_sarcina e "mare" sau "ui_mare", ruleaza SI skill-ul `plan-ceo-review`. - - Daca tip_sarcina e "simplu", ruleaza doar `plan-eng-review`. - - Nu exista utilizator uman disponibil in acest nod. Daca un skill invoca - `AskUserQuestion`, alege TU insuti, imediat, optiunea recomandata (nu astepta raspuns - uman, nu te opri BLOCKED) si continua. - - Scrie constatarile si deciziile fiecarui skill rulat intr-o sectiune noua in - $plan.output.plan_file: `## Review eng` (obligatoriu), `## Review design` (doar daca ai - rulat plan-design-review), `## Review CEO` (doar daca ai rulat plan-ceo-review). - - Raspunde STRICT conform output_format (summary = 2-3 randuri cu cele mai importante - decizii, din toate sectiunile de review scrise). - output_format: - type: object - properties: - summary: { type: string } - required: [summary] - - # ============================================================ - # b. APROBARE PLAN (Marius) - # ============================================================ - - id: aprobare_plan - depends_on: [plan_review] - approval: - message: | - Plan scris in $plan.output.plan_file (tip_sarcina: $plan.output.tip_sarcina) - $plan.output.summary - - Review (skill-uri gstack reale, deciziile sunt deja scrise in plan la sectiunile - "Review eng"/"Review design"/"Review CEO"): - $plan_review.output.summary - - Aprobi implementarea conform acestui plan? - - # ============================================================ - # c. IMPLEMENT (Pi / DeepSeek V4.1 Flash, prin abonamentul opencode go) - # ============================================================ - - id: implement - depends_on: [aprobare_plan] - provider: pi - model: opencode-go/deepseek-v4.1-flash - idle_timeout: 900000 - allowed_tools: [read, bash, edit, write, grep, find, ls] - skills: [roa-vfp-text-edit, roa-vfp-headless-test, roa-vfp-null-guards, roa-vfp-go-recno, roa-oracle-sqlexec-no-data] - prompt: | - Esti un agent EXECUTANT pe o singura sarcina, intr-un proiect ROA (Visual FoxPro 9 + Oracle). - - ## Cautare rapida (obligatorie) - Niciodata `grep -r` pe tot arborele `D:\ROA\ROACONT` (10+ minute). In ordine: - 1. Unealta `grep`/`find` (rapide, bazate pe ripgrep) sau `rg` direct din bash - exclude - `.svn` si binarele: `rg --glob '!.svn' --glob '!*.exe' --glob '!*.fxp' --glob '!*.vct' --glob '!*.sct' `. - 2. Pentru cod VFP text (`.vc2`/`.sc2`), `vfp_symbols.ps1` - Grep simplu nu spune carei - clase/metode apartine un hit: - ``` - $s = 'D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1' - $c = @('-CacheRoot', 'D:\ROA\ROACONT', '-ProjectRoot', 'D:\ROA\ROACONT', '-IndexFile', 'D:\ROA\_vfp_textcache\roacont\_symbols.tsv') - powershell -ExecutionPolicy Bypass -File $s @c -Grep '' -CodeOnly # hits etichetate clasa.metoda - powershell -ExecutionPolicy Bypass -File $s @c -Where '.vc2:' # cine detine linia - powershell -ExecutionPolicy Bypass -File $s @c -Find '' # unde e DEFINIT - powershell -ExecutionPolicy Bypass -File $s @c -Class '' # lant de mostenire + metode - ``` - 3. ORICE comanda bash (nu doar VFP headless) primeste un timeout explicit (`timeout 120 - ...` sau echivalent) si nu se ruleaza interactiv - un dialog modal sau un proces - agatat blocheaza nodul pana la idle_timeout, nu doar comanda. Niciodata doua sau mai - multe comenzi bash paralele care se astepta una pe alta (blocant) - un nod din acest - workflow (`review2`) a atins idle_timeout de 15 min exact asa (25.09, run 3c029727). - - ## Rol - - Aplici STRICT planul din $plan.output.plan_file, nimic mai mult. - - Inainte de orice editare, respecta `COMUN\docs\reguli_lucru.md` si punctul 7 de acolo - pentru zona atinsa (byte-safe pe `.vc2`/`.sc2`, CRLF, comentarii de maxim o linie). - - ## Write-back si teste (permise in acest nod) - - Dupa editarea `.vc2`/`.sc2`, ruleaza intai `txt2vcx.ps1 -DryRun` (fidelity-check). - Daca trece, poti rula write-back-ul REAL (`txt2vcx.ps1` FARA `-DryRun`) si testul - headless din plan, imediat, in acest nod - conform `CLAUDE.md` - ("Write-back-ul cu txt2vcx.ps1 si testele se fac imediat dupa editare; doar commit-ul - asteapta aprobarea"). Nu sari peste `-DryRun`. - - Probele, backup-urile si scripturile ajutatoare temporare (`_probe*`, `*.bak`, - `_patch*`, loguri de proba) se scriu STRICT intr-un director temporar, NU in repo: - `%TEMP%\archon_roa\\` (foloseste variabila de mediu/`$ARTIFACTS_DIR` daca e - disponibila, altfel `%TEMP%\archon_roa\manual\`). Le stergi la final daca nu mai sunt - necesare pentru dovada in plan. - - ## Interzis - - commit git sau svn; `svn update`/`revert`; `git checkout`/`reset` pe fisiere neatinse. - - editarea binarelor VFP (`.vcx .vct .scx .sct .frx .mnx .dbf .pjx`) sau a fisierelor compilate. - - `sed -i`, scrieri cu `python` (stub Windows, nu scrie nimic), refactorizari din oficiu. - - modificari pe Oracle de productie; pe productie doar SELECT. - - fisiere de proba/backup/scratch lasate in `D:\ROA\ROACONT` sau `COMUN\` (vezi mai sus). - - ## Editare - - Modificari minime, doar ce e in plan. Refolosesti ce exista. - - `.vc2/.sc2/.prg`: strict ASCII (fara diacritice) in codul scris de tine. - - Pastrezi CRLF pe tot fisierul editat. - - Comentarii: maxim o linie, doar unde codul nu se citeste singur. - - Daca planul e neclar sau cere o decizie, opreste-te si scrie problema in raspunsul tau - (acest workflow nu are un pas separat de intrebari - descrie exact ce e blocat). - - Plan: $plan.output.plan_file (citeste-l de pe disc pentru detalii complete). - - # ============================================================ - # d. VERIFICA (bash, 0 tokeni) - primul rand - # ============================================================ - - id: verifica - depends_on: [implement] - bash: | - mkdir -p "$ARTIFACTS_DIR" - powershell -ExecutionPolicy Bypass -File D:/roa/roacont/.archon/scripts/verifica_vfp_text.ps1 -ProjectRoot D:\roa\roacont > "$ARTIFACTS_DIR/verifica_log.txt" 2>&1 - RC=$? - cat "$ARTIFACTS_DIR/verifica_log.txt" - if [ $RC -eq 0 ]; then echo OK; else echo FAIL; fi - - # ============================================================ - # e. RETRY: implement inca o data cu eroarea, apoi re-verifica - # ============================================================ - - id: implement_retry - depends_on: [verifica] - when: "$verifica.output == 'FAIL'" - provider: pi - model: opencode-go/deepseek-v4.1-flash - idle_timeout: 900000 - prompt: | - Prima ta incercare de implementare a picat verificarea automata. Corecteaza STRICT - problemele de mai jos, fara sa te abati de la planul din $plan.output.plan_file si fara - sa introduci alte schimbari. Write-back real + test headless permise (vezi nodul - `implement` pentru reguli complete de write-back/probe temporare). - - ORICE comanda bash primeste timeout explicit; nu lansa apeluri bash paralele blocante - (vezi nodul `implement` pentru reguli complete de cautare/write-back). - - Iesirea verificarii (citeste si $ARTIFACTS_DIR/verifica_log.txt pentru detalii complete): - $verifica.output - - - id: verifica2 - depends_on: [implement_retry] - bash: | - powershell -ExecutionPolicy Bypass -File D:/roa/roacont/.archon/scripts/verifica_vfp_text.ps1 -ProjectRoot D:\roa\roacont > "$ARTIFACTS_DIR/verifica_log2.txt" 2>&1 - RC=$? - cat "$ARTIFACTS_DIR/verifica_log2.txt" - if [ $RC -eq 0 ]; then echo OK; else echo FAIL; fi - - # ============================================================ - # al doilea esec -> escaladare la Opus - # ============================================================ - - id: escaladare - depends_on: [verifica2] - when: "$verifica2.output == 'FAIL'" - model: opus - idle_timeout: 900000 - skills: [roa-vfp-text-edit, roa-vfp-headless-test, roa-vfp-null-guards, roa-vfp-go-recno, roa-oracle-sqlexec-no-data] - prompt: | - Doua incercari de implementare (Pi/DeepSeek) au picat verificarea automata pentru - planul din $plan.output.plan_file. Repara TU direct, minim, respectand planul si - `COMUN\docs\reguli_lucru.md`. Write-back real (`txt2vcx.ps1` FARA `-DryRun`, dupa - `-DryRun` OK) si testul headless din plan sunt permise in acest nod, imediat dupa - editare. Probele/scripturile temporare merg in `%TEMP%\archon_roa\\`, NU in repo - (vezi nodul `implement` pentru regula completa). - - ORICE comanda bash primeste timeout explicit; nu lansa apeluri bash paralele blocante. - - Iesirea ultimei verificari (si $ARTIFACTS_DIR/verifica_log2.txt pentru detalii complete): - $verifica2.output - - Dupa ce repari, ruleaza din nou verificarea mecanica manual: - powershell -ExecutionPolicy Bypass -File D:/roa/roacont/.archon/scripts/verifica_vfp_text.ps1 -ProjectRoot D:\roa\roacont - si confirma in raspuns ca trece (exit 0). - - # ============================================================ - # f. REVIEW (Pi / DeepSeek, cu acces la cod) - # ============================================================ - - id: review - depends_on: [verifica, verifica2, escaladare] - trigger_rule: none_failed_min_one_success - provider: pi - model: opencode-go/deepseek-v4.1-flash - context: fresh - idle_timeout: 900000 - allowed_tools: [read, bash, edit, write, grep, find, ls] - skills: [roa-vfp-text-edit, roa-vfp-headless-test, roa-vfp-null-guards, roa-vfp-go-recno, roa-oracle-sqlexec-no-data] - prompt: | - Esti reviewer de cod Visual FoxPro 9 cu backend Oracle. Gaseste bug-urile reale din - diff (corectitudine, nu stil). Verifica fiecare afirmatie pe codul real inainte de - verdict - citeste fisierele schimbate, nu doar diful. - - ## Cautare rapida (obligatorie) - Niciodata `grep -r` pe tot arborele `D:\ROA\ROACONT`. In ordine: - 1. Unealta `grep`/`find` (rapide, bazate pe ripgrep) sau `rg` direct din bash - exclude - `.svn` si binarele: `rg --glob '!.svn' --glob '!*.exe' --glob '!*.fxp' --glob '!*.vct' --glob '!*.sct' `. - 2. Pentru cod VFP text (`.vc2`/`.sc2`), `vfp_symbols.ps1`: - ``` - $s = 'D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1' - $c = @('-CacheRoot', 'D:\ROA\ROACONT', '-ProjectRoot', 'D:\ROA\ROACONT', '-IndexFile', 'D:\ROA\_vfp_textcache\roacont\_symbols.tsv') - powershell -ExecutionPolicy Bypass -File $s @c -Grep '' -CodeOnly # hits etichetate clasa.metoda - powershell -ExecutionPolicy Bypass -File $s @c -Where '.vc2:' # cine detine linia - powershell -ExecutionPolicy Bypass -File $s @c -Find '' # unde e DEFINIT - powershell -ExecutionPolicy Bypass -File $s @c -Class '' # lant de mostenire + metode - ``` - 3. ORICE comanda bash (nu doar VFP headless) primeste timeout explicit - nu rula - interactiv si nu lansa apeluri bash paralele blocante (au dus la idle_timeout de 15 - min pe `review2`, 25.09, run 3c029727). - - Probele tale de reproducere merg in `%TEMP%\archon_roa\\`, NU in repo. - - Ruleaza: - git diff --stat HEAD - git diff HEAD - git -C COMUN diff --stat HEAD - git -C COMUN diff HEAD - (COMUN e repo git separat; modificarile de acolo apar doar cu `git -C COMUN`.) - - Planul original e in $plan.output.plan_file. - - Verdict final: OK sau BLOCANT (raspunde strict conform output_format). - output_format: - type: object - properties: - verdict: { type: string, enum: [OK, BLOCANT] } - findings: { type: string } - required: [verdict, findings] - - # ============================================================ - # review BLOCANT -> escaladare la Opus - # ============================================================ - - id: escaladare_review - depends_on: [review] - when: "$review.output.verdict == 'BLOCANT'" - model: opus - idle_timeout: 900000 - skills: [roa-vfp-text-edit, roa-vfp-headless-test, roa-vfp-null-guards, roa-vfp-go-recno, roa-oracle-sqlexec-no-data] - prompt: | - Review-ul (Pi/DeepSeek) a dat verdict BLOCANT pe implementarea planului - $plan.output.plan_file. Constatari: - - $review.output.findings - - Repara TU direct, minim, respectand planul si `COMUN\docs\reguli_lucru.md`. Write-back - real si testul headless sunt permise in acest nod, imediat dupa editare (dupa - `-DryRun` OK). Probele temporare merg in `%TEMP%\archon_roa\\`, NU in repo. - ORICE comanda bash primeste timeout explicit; nu lansa apeluri bash paralele blocante. - Dupa ce repari, ruleaza din nou verificarea mecanica: - powershell -ExecutionPolicy Bypass -File D:/roa/roacont/.archon/scripts/verifica_vfp_text.ps1 -ProjectRoot D:\roa\roacont - si confirma in raspuns ca trece (exit 0). - - # ============================================================ - # g. RE-REVIEW dupa escaladare_review - RULEAZA MEREU (scurt-circuit daca - # review 1 a fost deja OK), ca sa poata fi referentiat in siguranta mai - # jos ($review2.output... nu e niciodata pe un nod SKIPPED - un nod - # skipped nu poate fi referentiat in template, testat empiric 25.09). - # Nu se opreste bucla la infinit: daca verdictul e tot BLOCANT, nu mai - # exista alt nod de escaladare dupa - se merge direct spre aprobare, cu - # verdictul vizibil acolo. - # ============================================================ - - id: review2 - depends_on: [review, escaladare_review] - trigger_rule: none_failed_min_one_success - provider: pi - model: opencode-go/deepseek-v4.1-flash - idle_timeout: 900000 - allowed_tools: [read, bash, edit, write, grep, find, ls] - skills: [roa-vfp-text-edit, roa-vfp-headless-test, roa-vfp-null-guards, roa-vfp-go-recno, roa-oracle-sqlexec-no-data] - prompt: | - Verdictul review-ului initial: $review.output.verdict - - Daca verdictul de mai sus e OK, escaladarea la Opus NU a rulat (nimic de reparat) - - raspunde IMEDIAT cu verdict OK, findings: "review initial deja OK, escaladarea nu a - rulat", FARA sa mai citesti cod (raspuns scurt, ieftin, fara tool-uri). - - Daca verdictul de mai sus e BLOCANT, Opus tocmai a incercat o reparare pe baza - constatarilor de mai jos - verifica pe codul REAL (nu doar presupunand ca fixul e - corect) daca problema e rezolvata si daca nu s-a introdus alta: - - $review.output.findings - - Aceleasi reguli de cautare rapida si probe temporare ca la nodul `review` (probele in - `%TEMP%\archon_roa\\`, NU in repo). ORICE comanda bash primeste timeout explicit - (`timeout 120 ...` sau echivalent) si nu se ruleaza interactiv. Niciodata doua sau mai - multe comenzi bash paralele care se astepta una pe alta (blocant) - acest nod a atins - idle_timeout de 15 min exact asa (25.09, run 3c029727). - - git diff --stat HEAD - git diff HEAD - git -C COMUN diff --stat HEAD - git -C COMUN diff HEAD - - Verdict final: OK sau BLOCANT. Daca e tot BLOCANT, NU se mai escaladeaza automat - - workflow-ul se opreste la aprobarea finala cu verdictul tau vizibil, ca Marius sa - decida manual. - - Inainte sa raspunzi, scrie verdictul si in fisier (nodul `review2_status` de dupa il - citeste de acolo, nu din raspunsul tau, ca sa nu se piarda daca acest nod - esueaza/timeout): prima linie `VERDICT: OK` sau `VERDICT: BLOCANT`, apoi findings, in - `$ARTIFACTS_DIR/review2_verdict.txt`. - - Raspunde strict conform output_format. - output_format: - type: object - properties: - verdict: { type: string, enum: [OK, BLOCANT] } - findings: { type: string } - required: [verdict, findings] - - # ============================================================ - # g2. STATUS REVIEW2 (bash, 0 tokeni) - citeste verdictul din fisier, NU din - # $review2.output.verdict: referirea directa la un nod ESUAT/idle_timeout - # pica randarea mesajului care o foloseste (confirmat 25.09, run 3c029727 - # - aprobare_final a picat exact asa, vezi docs/pilot_archon_diagnoza_47.md, - # "Rulare 2 sarcina 47"). trigger_rule: all_done -> ruleaza chiar daca - # review2 a esuat/timeout, ca probe_check/invatare/diff/aprobare_final din - # aval sa nu mai depinda de succesul lui review2. - # ============================================================ - - id: review2_status - depends_on: [review2] - trigger_rule: all_done - bash: | - F="$ARTIFACTS_DIR/review2_verdict.txt" - if [ -s "$F" ]; then - cat "$F" - else - echo "VERDICT: NECUNOSCUT" - echo "review2 esuat - verifica manual" - fi - - # ============================================================ - # h. CONTROL fisiere suspecte (bash, 0 tokeni) - inainte de diff - # ============================================================ - - id: probe_check - depends_on: [review2_status] - bash: | - mkdir -p "$ARTIFACTS_DIR" - cd D:/roa/roacont - { - echo "=== ROACONT netracked suspecte ===" - git ls-files --others --exclude-standard | grep -Ei '_probe|\.bak$|_patch|\.FXP$|_log\.txt$' || echo "(niciunul)" - echo "=== COMUN netracked suspecte ===" - git -C COMUN ls-files --others --exclude-standard | grep -Ei '_probe|\.bak$|_patch|\.FXP$|_log\.txt$' || echo "(niciunul)" - } > "$ARTIFACTS_DIR/probe_check.txt" - cat "$ARTIFACTS_DIR/probe_check.txt" - if grep -q "(niciunul)" "$ARTIFACTS_DIR/probe_check.txt" && [ "$(grep -c '(niciunul)' "$ARTIFACTS_DIR/probe_check.txt")" -eq 2 ]; then - echo CURAT - else - echo ATENTIE_FISIERE_SUSPECTE - fi - - # ============================================================ - # i. INVATARE - propunere de documentare (neaplicata), roa-actualizare-doc headless - # ============================================================ - - id: invatare - depends_on: [probe_check] - model: sonnet - idle_timeout: 900000 - skills: [roa-actualizare-doc] - prompt: | - Rulezi skill-ul `roa-actualizare-doc` HEADLESS (fara sa astepti aprobare interactiva - - doar pana la pasul "Propune", NU aplici nimic). Scop: capcanele/regulile descoperite in - aceasta rulare sa nu se piarda si sa nu se repete la urmatoarea sarcina similara. - - Surse (citeste iesirile nodurilor din acest run, nu presupune): - - Plan: $plan.output.plan_file (si sectiunea "Review eng") - - Verdict review 1: $review.output.verdict / $review.output.findings - - Verdict review 2 (daca a rulat): vezi `git log`/artefacte pentru contextul escaladarii - - Verifica/verifica2: $ARTIFACTS_DIR/verifica_log.txt, $ARTIFACTS_DIR/verifica_log2.txt - (daca exista) - - Concentreaza-te pe BLOCANT-uri si esecuri (nu pe ce a mers bine din prima) - acolo e - capcana care merita documentata. Exemplu real (f50d54a2, 25.09): documentul - `conventie_goexecutor_alter_table.md` deja lista simptomul (eroarea 1115 la ALTER TABLE - pe cursor din oExecute), dar planul l-a citit gresit ("rematerializare -> ALTER permis") - - propunerea corecta ar fi clarificat regula in doc, nu ar fi adaugat un doc nou. - - Verifica INTAI daca subiectul exista deja in `COMUN\docs\README.md` / `docs\cercetare\` - (nu duplica). Scrie propunerea (NU o aplica) in `docs/propunere_doc_.md` (acelasi - `` ca planul): lista de modificari, fiecare cu fisierul tinta exact si textul - propus (2-5 randuri, ASCII, fara diacritice, ton ca notele din MEMORY.md - regula + - strictul de context, fara istoric/motivatie). Daca nu exista nimic reutilizabil de - documentat (sarcina a mers fara capcane noi), scrie in fisier "Nimic de propus." si atat. - - Raspunde STRICT conform output_format. - output_format: - type: object - properties: - propunere_file: { type: string } - are_propuneri: { type: boolean } - required: [propunere_file, are_propuneri] - - # ============================================================ - # j. DIFF (bash, 0 tokeni) - include si fisierele noi netracked - # ============================================================ - - id: diff - depends_on: [invatare] - bash: | - mkdir -p docs - cd D:/roa/roacont - PLANFILE=$plan.output.plan_file - SLUG=$(basename "$PLANFILE" .md | sed 's/^plan_//') - OUT="docs/diff_${SLUG}.patch" - : > "$OUT" - - git diff HEAD >> "$OUT" - git -C COMUN diff --src-prefix=a/COMUN/ --dst-prefix=b/COMUN/ HEAD -- "*.prg" "*.vc2" "*.sc2" >> "$OUT" - - # fisiere noi netracked (ROACONT), exclus .archon/ si docs/plan_* - git ls-files --others --exclude-standard | grep -v '^\.archon/' | grep -v '^docs/plan_' | while IFS= read -r f; do - git diff --no-index -- /dev/null "$f" >> "$OUT" || true - done - - # fisiere noi netracked (COMUN), cu prefix COMUN/ - git -C COMUN ls-files --others --exclude-standard | while IFS= read -r f; do - git -C COMUN diff --no-index --src-prefix=a/COMUN/ --dst-prefix=b/COMUN/ -- /dev/null "$f" >> "$OUT" || true - done - - echo "Diff scris in $OUT" - wc -l "$OUT" - - # ============================================================ - # k0. RAPORT CONTEXT (bash, 0 tokeni) - varf de context + timp per nod, din - # archon.db (evenimente node_started/node_completed, exacte) + sesiunile - # brute Pi/Claude de pe disc (varf real, .archon/scripts/*_extract.pl). - # trigger_rule: all_done - ruleaza chiar daca ceva a picat mai devreme in - # lant (Marius vrea sa vada tabelul si dupa un esec, nu doar pe happy path). - # ============================================================ - - id: raport_context - depends_on: [diff] - trigger_rule: all_done - bash: | - mkdir -p docs - cd D:/roa/roacont - PLANFILE=$plan.output.plan_file - SLUG=$(basename "$PLANFILE" .md | sed 's/^plan_//') - OUT="docs/context_${SLUG}.md" - { - echo "# Context si timp per nod - $SLUG" - echo - perl .archon/scripts/raport_context.pl - } > "$OUT" 2>&1 - cat "$OUT" - - # ============================================================ - # k. APROBARE FINALA (Marius vede diff-ul, verdictul si propunerea de doc) - # Verdictul review2 e citit din nodul `review2_status` (bash, all_done), NU - # direct din $review2.output.verdict: referirea directa la un nod ESUAT - # (idle_timeout) pica randarea acestui mesaj - confirmat 25.09, run 3c029727 - # (vezi docs/pilot_archon_diagnoza_47.md, "Rulare 2 sarcina 47"). Un nod - # SKIPPED tot nu poate fi referentiat in template (confirmat empiric 25.09); - # review2_status ruleaza mereu (all_done), deci nu se sare niciodata. - # ============================================================ - - id: aprobare_final - depends_on: [raport_context, review2_status] - approval: - message: | - Diff scris in docs/ (vezi nodul 'diff' pentru numele exact al fisierului). - Control fisiere suspecte (probe/backup uitate): vezi artefactul `probe_check.txt`. - Context si timp per nod (varf peste 200k e marcat ATENTIE): vezi docs/context_.md - (vezi nodul 'raport_context' pentru numele exact al fisierului). - - Verdict review 1: $review.output.verdict - Verdict final (review2 - re-review dupa escaladare, sau scurt-circuit daca review 1 - a fost deja OK; daca review2 a esuat/timeout, verdictul de mai jos e "NECUNOSCUT - - verifica manual"): - $review2_status.output - (daca verdictul final e tot BLOCANT sau NECUNOSCUT, workflow-ul NU escaladeaza din - nou - decizi tu: aprobi cu rezerve, respingi, sau ceri o interventie manuala) - Propunere documentatie (NEAPLICATA): $invatare.output.propunere_file - (are_propuneri: $invatare.output.are_propuneri) - - Testeaza in VFP. Commit-ul (git/svn) ramane manual, in afara acestui workflow. - Write-back-ul (txt2vcx, dupa -DryRun) a fost facut deja in nodurile de implementare/ - escaladare. Aprobi (inclusiv aplicarea propunerii de documentatie de mai sus)? - - # ============================================================ - # l. APLICA DOC (dupa aprobare) - aplica propunerea de documentare aprobata - # ============================================================ - - id: aplica_doc - depends_on: [aprobare_final] - when: "$invatare.output.are_propuneri == 'true'" - provider: pi - model: opencode-go/deepseek-v4.1-flash - allowed_tools: [read, bash, edit, write, grep, find, ls] - prompt: | - Marius a aprobat propunerea de documentare din $invatare.output.propunere_file. Aplic-o - STRICT (nu adauga altceva): pentru fiecare modificare din propunere, editeaza fisierul - tinta exact (creeaza-l doar daca propunerea cere explicit un fisier nou). `COMUN\docs` - e un repo git SEPARAT de ROACONT - editarile de acolo se fac normal pe disc (commit-ul - ramane manual, la fel ca pentru cod). Fisierele `.md` sunt text obisnuit: pastreaza - terminatia de linie existenta a fiecarui fisier (nu forta CRLF ca la `.vc2`/`.sc2` - aia - e o regula doar pentru codul VFP). Daca propunerea cere randul nou in - `COMUN\docs\README.md` si declansatorul in `reguli_lucru.md` pct. 7, adauga-le. - Nu rula `roa_sync`, nu da commit. diff --git a/.gitignore b/.gitignore index 0b7a74f..c4c8b59 100644 --- a/.gitignore +++ b/.gitignore @@ -108,3 +108,4 @@ docs/diff_*.patch .gstack/ docs/local/ docs/ +.archon/