5fe8f228c1
Add a read-only /ecosystem page that consumes the sibling services' JSON APIs (Nexus entities, Praxis attention, Hexis capabilities), fetched concurrently with honest per-panel error states. Siblings stay headless — mavweb is their human surface (arch §16). Wired via mavweb -nexus/-praxis/-hexis flags; mavweb joins the ecosystem compose network. Fix mobile horizontal overflow across all pages: .content is a flex child with default min-width:auto, so it refused to shrink below the tables' intrinsic width. min-width:0 lets wide tables pan inside .scroll instead of dragging the page sideways. Verified via CDP geometry check (scrollWidth === clientWidth at 430px). Also includes in-progress Ethos UI redesign, ecosystem deploy compose, and planning docs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
46 lines
1.6 KiB
HTML
46 lines
1.6 KiB
HTML
{{template "shellTop" "history"}}
|
||
<h1>Command History</h1>
|
||
{{if .Facts}}
|
||
<p class=hint>{{len .Facts}} facts shown (newest first)</p>
|
||
<div id=msg class=msg hidden></div>
|
||
<div class=scroll><table class=mono>
|
||
<tr><th>when<th>kind<th>key<th>value<th>source<th>conf<th></tr>
|
||
{{range .Facts}}<tr class="{{if .VoidsID}}voided{{end}}">
|
||
<td>{{if .VoidsID}}<span class=void-badge>⨯ voided</span>{{end}}{{.Ts.Format "2006-01-02 15:04"}}</td>
|
||
<td>{{.Kind}}</td>
|
||
<td class=key>{{.Key}}</td>
|
||
<td class=val>{{.Value}}</td>
|
||
<td class=hint>{{.Source}}</td>
|
||
<td>{{printf "%.2f" .Confidence}}</td>
|
||
<td>{{if not .VoidsID}}<button class="btn btn-sm" onclick="revert('{{.Key}}',this)">revert</button>{{end}}</td>
|
||
</tr>{{end}}
|
||
</table></div>
|
||
{{else}}
|
||
<div class=empty>
|
||
<svg class=icon width="24" height="24"><use href="/ethos-icons.svg#i-clock"/></svg>
|
||
<div>no facts recorded yet</div>
|
||
<div class=hint>facts appear here when maven observes or records events</div>
|
||
</div>
|
||
{{end}}
|
||
{{template "shellBottom"}}
|
||
<script>
|
||
const msg=document.getElementById('msg');
|
||
function revert(key,btn){
|
||
btn.disabled=true;
|
||
fetch('/api/revert',{method:'POST',headers:{'content-type':'application/x-www-form-urlencoded'},body:'key='+encodeURIComponent(key)})
|
||
.then(r=>r.json().then(d=>({ok:r.ok,data:d})))
|
||
.then(({ok,data})=>{
|
||
msg.className=ok?'msg msg-ok':'msg msg-err';
|
||
msg.hidden=false;
|
||
msg.textContent=ok?'reverted ✓':(data.error||'revert failed');
|
||
if(ok){btn.closest('tr').className='voided';btn.disabled=true;}
|
||
}).catch(e=>{
|
||
msg.className='msg msg-err';
|
||
msg.hidden=false;
|
||
msg.textContent='error: '+e;
|
||
btn.disabled=false;
|
||
});
|
||
}
|
||
</script>
|
||
</html>
|