List each AI enhancement against the script it enhances
Declared in PHP rather than in each bash header, against scriptinfo's usual rule that the header next to the code is authoritative: it is authoritative about what the script does, and an enhancement is something else reading its output, gated by a flag the script has never heard of. A description of PHP inside a file that cannot enforce it would drift the first time either changed. Shown with its switch, so "there is an enhancement" and "it is running" are never the same claim. Discovery is listed even though nothing acts on its output — it takes the first accessible root folder with no regard for content, and the classification scan is what notices that night. That relationship explains where misfiled series come from and was written down nowhere.
This commit is contained in:
@@ -113,9 +113,20 @@ foreach ($searchFiles as [$label, $file]) {
|
||||
if ($body) $sections[] = ['source' => $label, 'body' => $body];
|
||||
}
|
||||
|
||||
// Any AI enhancement that reads this script's output, and whether it is switched on. Kept out of
|
||||
// $sections because it is not documentation: the sections above describe what the script does, and
|
||||
// this describes something else that watches it. Merging them would put a claim in the doc panel
|
||||
// that the script's own header cannot support.
|
||||
//
|
||||
// require_once here rather than at the top: ai_repair.php pulls in the findings layer, and a
|
||||
// scheduler info request on a host with AI off has no reason to load it.
|
||||
require_once dirname(__DIR__) . '/include/ai_repair.php';
|
||||
$enhancement = function_exists('vv_ai_script_enhancements') ? vv_ai_script_enhancements($id) : [];
|
||||
|
||||
echo json_encode([
|
||||
'ok' => true,
|
||||
'name' => $name,
|
||||
'header' => $header,
|
||||
'sections' => $sections,
|
||||
'enhancement' => $enhancement ?: null,
|
||||
]);
|
||||
|
||||
@@ -974,6 +974,64 @@ function vv_ai_watchdog_findings(?array $payload = null): array {
|
||||
return $found;
|
||||
}
|
||||
|
||||
// ── What the AI adds to which script ──────────────────────────────────────────────────────────
|
||||
// Declared here rather than in each script's header, and that is a deliberate departure from
|
||||
// api/scriptinfo.php's usual rule that the header next to the code is authoritative. It is
|
||||
// authoritative about what the script does. An enhancement is not the script's behaviour — it is
|
||||
// something else reading the script's output afterwards, implemented in PHP, gated by a flag the
|
||||
// script has never heard of. Writing it into the bash header would put a description of PHP inside
|
||||
// a file that cannot enforce it, and the two would drift the first time either changed.
|
||||
//
|
||||
// A script may appear here without the enhancement being about its output. sonarr discovery is
|
||||
// listed because the triage is its safety net: discovery takes the first accessible root folder
|
||||
// (playback_aware_sonarr_discovery.sh:750) with no regard for whether the show is anime, kids or
|
||||
// general, and the classification scan is what notices the next night. That relationship is real,
|
||||
// it explains where misfiled series come from, and until now it was written down nowhere.
|
||||
const VV_AI_SCRIPT_ENHANCEMENTS = [
|
||||
'Arrs_Stack/sonarr_classification_scan.sh' => [
|
||||
'name' => 'Classification triage',
|
||||
'flag' => 'AI_ASSIST_DISCOVERY',
|
||||
'what' => 'This scan reports reverse-anime leaks and deliberately does not act on them — '
|
||||
. 'its own header calls them genuine judgement calls, because no metadata field '
|
||||
. 'separates a misfile from a deliberate choice. The triage sorts that bucket into '
|
||||
. 'misfiled, donghua, anime-adjacent or uncertain.',
|
||||
'acts' => 'Files a finding for misfiled and uncertain only. A misfiled series carries a '
|
||||
. 'Move action, which relocates the files — pressed by a person, never automatic.',
|
||||
],
|
||||
'Arrs_Stack/playback_aware_sonarr_discovery.sh' => [
|
||||
'name' => 'Classification triage (safety net)',
|
||||
'flag' => 'AI_ASSIST_DISCOVERY',
|
||||
'what' => 'Discovery adds every show it finds to the first accessible root folder, without '
|
||||
. 'classifying it. Anything it places wrongly is caught by the classification scan '
|
||||
. 'that night, and the triage is what turns that scan\'s count into named titles.',
|
||||
'acts' => 'Nothing here. The enhancement runs against the classification scan\'s output, '
|
||||
. 'not against this script.',
|
||||
],
|
||||
'Orchestrators/watchdog_orchestrator.sh' => [
|
||||
'name' => 'Watchdog findings',
|
||||
'flag' => 'AI_ASSIST_WATCHDOG',
|
||||
'what' => 'Turns the counters the watchdogs keep — skip lists, strikes past their limit, '
|
||||
. 'repeated restarts, unattended reboots, sustained pressure — into named findings '
|
||||
. 'instead of numbers on a card.',
|
||||
'acts' => 'Files findings only. The kind is not conf-bound, so it cannot autofix by '
|
||||
. 'construction rather than by a setting.',
|
||||
],
|
||||
];
|
||||
|
||||
function vv_ai_script_enhancements(string $id = ''): array {
|
||||
if ($id === '') return VV_AI_SCRIPT_ENHANCEMENTS;
|
||||
$id = ltrim(trim($id), '/');
|
||||
if (!str_ends_with($id, '.sh')) $id .= '.sh';
|
||||
$e = VV_AI_SCRIPT_ENHANCEMENTS[$id] ?? null;
|
||||
if (!$e) return [];
|
||||
// The flag state travels with it. An enhancement listed against a script without saying
|
||||
// whether it is switched on is the same trap AI_ASSIST_WATCHDOG was for months: a name that
|
||||
// looks like a feature and does nothing.
|
||||
$e['enabled'] = strtolower(trim((string)(vv_conf_vars()[$e['flag']] ?? 'false'))) === 'true'
|
||||
&& vv_ai_repair_enabled();
|
||||
return $e;
|
||||
}
|
||||
|
||||
// ── Classification triage ─────────────────────────────────────────────────────────────────────
|
||||
// The one place in the media stack where a model beats the rule it is helping.
|
||||
//
|
||||
|
||||
@@ -4450,6 +4450,29 @@ function vvShowScriptInfoMode(name, hdr, id) {
|
||||
+ '</div>';
|
||||
}
|
||||
|
||||
// Above the documentation, because it changes how the sections below should be read: a
|
||||
// script whose output is being triaged behaves the same but is no longer the last word on
|
||||
// what happens to what it reports. Stated with its switch, so "there is an enhancement" and
|
||||
// "it is running" are never the same claim — AI_ASSIST_WATCHDOG spent months looking like a
|
||||
// feature while reading nothing.
|
||||
if (info.ok && info.enhancement) {
|
||||
const e = info.enhancement;
|
||||
const col = e.enabled ? '#4caf50' : '#555';
|
||||
html += '<div class="vv-sinfo-block">'
|
||||
+ '<div class="vv-sinfo-lbl">AI enhancement</div>'
|
||||
+ '<div style="padding:6px 2px;">'
|
||||
+ '<div style="display:flex;align-items:baseline;gap:8px;margin-bottom:4px;">'
|
||||
+ '<span style="font-size:12px;color:#bbb;">' + vvEscHtml(e.name) + '</span>'
|
||||
+ '<span style="font-size:9px;color:' + col + ';border:1px solid ' + col + '44;'
|
||||
+ 'background:' + col + '14;border-radius:3px;padding:1px 6px;">'
|
||||
+ (e.enabled ? 'on' : 'off') + ' · ' + vvEscHtml(e.flag) + '</span>'
|
||||
+ '</div>'
|
||||
+ '<div style="font-size:11px;color:#666;line-height:1.5;">' + vvEscHtml(e.what) + '</div>'
|
||||
+ '<div style="font-size:10px;color:#3f3f3f;line-height:1.5;margin-top:4px;">'
|
||||
+ vvEscHtml(e.acts) + '</div>'
|
||||
+ '</div></div>';
|
||||
}
|
||||
|
||||
if (info.ok && info.sections?.length) {
|
||||
for (const sec of info.sections) {
|
||||
html += '<div class="vv-sinfo-block">'
|
||||
|
||||
Reference in New Issue
Block a user