gitignore: .archon (junction spre COMUN\.archon, versionat in COMUN)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018YqLHZCrqmvKr5snjKyGkd
This commit is contained in:
2026-09-25 12:36:07 +03:00
parent d2a2451e3b
commit f92e62e959
9 changed files with 1 additions and 1225 deletions

View File

@@ -1,90 +0,0 @@
#!/usr/bin/perl
use strict; use warnings;
use JSON::PP;
my $file = shift @ARGV or die "usage: analyze_claude.pl <file.jsonl>\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";

View File

@@ -1,81 +0,0 @@
#!/usr/bin/perl
use strict; use warnings;
use JSON::PP;
my $file = shift @ARGV or die "usage: analyze_pi.pl <file.jsonl> [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";

View File

@@ -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)

View File

@@ -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";
}
}

View File

@@ -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

View File

@@ -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};
}

View File

@@ -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

View File

@@ -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' <expresie>`) 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 '<expresie>' -CodeOnly
powershell -ExecutionPolicy Bypass -File $s @c -Find '<nume>'
```
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_<slug>.md` (`<slug>` = 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' <expresie>`.
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 '<expresie>' -CodeOnly # hits etichetate clasa.metoda
powershell -ExecutionPolicy Bypass -File $s @c -Where '<fisier>.vc2:<linie>' # cine detine linia
powershell -ExecutionPolicy Bypass -File $s @c -Find '<nume>' # unde e DEFINIT
powershell -ExecutionPolicy Bypass -File $s @c -Class '<nume clasa>' # 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\<run-id>\` (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\<run-id>\`, 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' <expresie>`.
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 '<expresie>' -CodeOnly # hits etichetate clasa.metoda
powershell -ExecutionPolicy Bypass -File $s @c -Where '<fisier>.vc2:<linie>' # cine detine linia
powershell -ExecutionPolicy Bypass -File $s @c -Find '<nume>' # unde e DEFINIT
powershell -ExecutionPolicy Bypass -File $s @c -Class '<nume clasa>' # 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\<run-id>\`, 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\<run-id>\`, 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\<run-id>\`, 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_<slug>.md` (acelasi
`<slug>` 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_<slug>.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.

1
.gitignore vendored
View File

@@ -108,3 +108,4 @@ docs/diff_*.patch
.gstack/ .gstack/
docs/local/ docs/local/
docs/ docs/
.archon/