Procházet zdrojové kódy

feat: add decision hold control and signal decision inspector

master
Jan Svabenik před 2 hodinami
rodič
revize
379698fe30
3 změnil soubory, kde provedl 29 přidání a 0 odebrání
  1. +1
    -0
      README.md
  2. +26
    -0
      web/app.js
  3. +2
    -0
      web/index.html

+ 1
- 0
README.md Zobrazit soubor

@@ -80,6 +80,7 @@ Edit `config.yaml` (autosave goes to `config.autosave.yaml`).
- `resources.max_refinement_jobs` — processing budget hint
- `resources.max_recording_streams` — recording/streaming budget hint
- `resources.max_decode_jobs` — decode budget hint
- `resources.decision_hold_ms` — hold time for queue slots before churn
- `profiles[]` — named operating profiles/intent metadata

In phase 1, the engine stays backward compatible, but the config model now reflects the intended separation between:


+ 26
- 0
web/app.js Zobrazit soubor

@@ -71,6 +71,7 @@ const resMaxRecord = qs('resMaxRecord');
const resMaxDecode = qs('resMaxDecode');

const signalList = qs('signalList');
const signalDecisionSummary = qs('signalDecisionSummary');
const eventList = qs('eventList');
const recordingList = qs('recordingList');
const signalCountBadge = qs('signalCountBadge');
@@ -760,6 +761,7 @@ async function loadRefinement() {
items.forEach(item => {
if (item && item.id != null) decisionIndex.set(String(item.id), item);
});
updateSignalDecisionSummary(window._selectedSignal?.id);
} catch {}
}

@@ -1349,6 +1351,22 @@ function renderDetailSpectrogram() {

let _lastEventListKey = '';

function updateSignalDecisionSummary(id) {
if (!signalDecisionSummary) return;
if (!id) {
signalDecisionSummary.textContent = 'Decision: -';
return;
}
const dec = decisionIndex.get(String(id));
if (!dec) {
signalDecisionSummary.textContent = 'Decision: -';
return;
}
const flags = `${dec.record ? 'REC' : ''}${dec.decode ? (dec.record ? '+DEC' : 'DEC') : ''}` || 'none';
const reason = dec.reason ? ` · ${dec.reason}` : '';
signalDecisionSummary.textContent = `Decision: ${flags}${reason}`;
}

function _createSignalItem(s) {
const btn = document.createElement('button');
btn.className = 'list-item signal-item';
@@ -1487,6 +1505,8 @@ function renderLists() {
`).join('');
}
}

updateSignalDecisionSummary(window._selectedSignal?.id);
}

function normalizeEvent(ev) {
@@ -2023,6 +2043,10 @@ if (resMaxDecode) resMaxDecode.addEventListener('change', () => {
const v = parseInt(resMaxDecode.value || '0', 10);
queueConfigUpdate({ resources: { max_decode_jobs: v } });
});
if (resDecisionHold) resDecisionHold.addEventListener('change', () => {
const v = parseInt(resDecisionHold.value || '0', 10);
queueConfigUpdate({ resources: { decision_hold_ms: v } });
});

avgSelect.addEventListener('change', () => {
avgAlpha = parseFloat(avgSelect.value) || 0;
@@ -2141,10 +2165,12 @@ signalList.addEventListener('click', (ev) => {
target.classList.add('active');
// Store selected signal data for Live Listen button
window._selectedSignal = {
id: target.dataset.id || null,
freq: parseFloat(target.dataset.center),
bw: parseFloat(target.dataset.bw || '12000'),
mode: target.dataset.class || ''
};
updateSignalDecisionSummary(window._selectedSignal.id);
});

if (liveListenBtn) {


+ 2
- 0
web/index.html Zobrazit soubor

@@ -246,6 +246,7 @@
<label class="field"><span>Max Refinement</span><input id="resMaxRefine" type="number" step="1" min="0" /></label>
<label class="field"><span>Max Record</span><input id="resMaxRecord" type="number" step="1" min="0" /></label>
<label class="field"><span>Max Decode</span><input id="resMaxDecode" type="number" step="1" min="0" /></label>
<label class="field"><span>Decision Hold (ms)</span><input id="resDecisionHold" type="number" step="250" min="0" /></label>
</div>
<div class="panel-sub">Budgets applied to refinement selection, recording, and decode decisions.</div>
</div>
@@ -270,6 +271,7 @@
<section class="tab-panel" data-panel="signals">
<div class="list-head"><span class="grp-title">Detected carriers</span><span class="count-pill" id="signalCountBadge">0 live</span></div>
<div class="signal-list" id="signalList"><div class="empty-state">No live signals yet.</div></div>
<div class="panel-sub" id="signalDecisionSummary">Decision: -</div>
<div class="field-pair">
<label class="field"><span>Listen sec</span><input id="listenSeconds" type="number" min="1" max="10" step="1" value="2" /></label>
<label class="field"><span>Listen mode</span>


Načítá se…
Zrušit
Uložit