humanish 0.20.3 → 0.20.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/observer-assets.js
CHANGED
|
@@ -417,6 +417,20 @@ a { color: inherit; text-decoration: none; }
|
|
|
417
417
|
/* ============================================================ STREAM SURFACES */
|
|
418
418
|
.surface-fill { position: absolute; inset: 0; width: 100%; height: 100%; }
|
|
419
419
|
.surface-screenshot { object-fit: contain; object-position: top center; }
|
|
420
|
+
/* Replay scrubber (#292 first slice): a per-turn keyframe timeline built from persisted frames + trace. */
|
|
421
|
+
.replay { position: absolute; inset: 0; display: flex; flex-direction: column; background: #0b0d10; }
|
|
422
|
+
.replay-stage { position: relative; flex: 1 1 auto; min-height: 0; }
|
|
423
|
+
.replay-badge { position: absolute; top: 6px; right: 8px; z-index: 2; font-size: 9px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-2); background: rgba(0,0,0,.55); border: 1px solid var(--line-2); border-radius: 999px; padding: 2px 7px; }
|
|
424
|
+
.replay-bar { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-top: 1px solid var(--line-2); background: var(--surface-2); }
|
|
425
|
+
.replay-btn { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 7px; border: 1px solid var(--line-2); background: transparent; color: var(--text-1); cursor: pointer; }
|
|
426
|
+
.replay-btn:hover { background: var(--surface-3); }
|
|
427
|
+
.replay-range { flex: 1 1 auto; accent-color: var(--accent-color); cursor: pointer; height: 4px; min-width: 40px; }
|
|
428
|
+
.replay-count { flex: 0 0 auto; font-size: 11px; color: var(--text-2); min-width: 44px; text-align: right; }
|
|
429
|
+
.replay-info { flex: 0 0 auto; max-height: 32%; overflow-y: auto; padding: 8px 10px; border-top: 1px solid var(--line-2); background: var(--surface-1); font-size: 12px; line-height: 1.5; color: var(--text-1); }
|
|
430
|
+
.replay-acts { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; }
|
|
431
|
+
.replay-act { font-family: var(--mono); font-size: 10px; color: var(--text-2); background: var(--surface-3); border: 1px solid var(--line-2); border-radius: 5px; padding: 2px 6px; }
|
|
432
|
+
.replay-narr { white-space: pre-wrap; color: var(--text-1); }
|
|
433
|
+
.replay-dim { color: var(--text-2); font-style: italic; }
|
|
420
434
|
.live-stream-mount { position: absolute; inset: 0; overflow: hidden; background: #000; }
|
|
421
435
|
.live-stream-overlay { position: absolute; overflow: hidden; pointer-events: none; z-index: 2; }
|
|
422
436
|
.live-stream-overlay[data-focus="true"] .bw-lab-dock { max-height: 86px; }
|
|
@@ -1143,6 +1157,12 @@ export function observerClientJs() {
|
|
|
1143
1157
|
motion: readPref("motion", "full")
|
|
1144
1158
|
};
|
|
1145
1159
|
var artifactCache = {};
|
|
1160
|
+
// Replay-scrubber state: per-stream current frame index + auto-advance timer. Kept OUTSIDE the S
|
|
1161
|
+
// render-state so a data-poll re-render preserves the scrub position; indices survive because
|
|
1162
|
+
// render() reads scrubIndexFor() (which defaults to the last frame — also fixing the "finished lane
|
|
1163
|
+
// cuts to black" symptom). Timers are cleared on every render() so playback never orphans.
|
|
1164
|
+
var scrubState = {};
|
|
1165
|
+
var scrubTimers = {};
|
|
1146
1166
|
var liveStreamFrames = {};
|
|
1147
1167
|
var liveStreamHost = null;
|
|
1148
1168
|
var liveStreamLayoutRaf = null;
|
|
@@ -1198,7 +1218,9 @@ export function observerClientJs() {
|
|
|
1198
1218
|
lock: '<rect x="4.5" y="10" width="15" height="10" rx="2"' + P + '/><path d="M8 10V7a4 4 0 0 1 8 0v3"' + P + '/>',
|
|
1199
1219
|
caret: '<path d="m6 9 6 6 6-6"' + P + '/>',
|
|
1200
1220
|
filter: '<path d="M3 5h18l-7 8.2V20l-4-2.2v-4.6L3 5Z"' + P + '/>',
|
|
1201
|
-
panelRight: '<rect x="3" y="4" width="18" height="16" rx="2"' + P + '/><path d="M15 4v16"' + P + '/>'
|
|
1221
|
+
panelRight: '<rect x="3" y="4" width="18" height="16" rx="2"' + P + '/><path d="M15 4v16"' + P + '/>',
|
|
1222
|
+
play: '<path d="M7 5l12 7-12 7z"' + P + '/>',
|
|
1223
|
+
pause: '<path d="M9 5v14M15 5v14"' + P + '/>'
|
|
1202
1224
|
};
|
|
1203
1225
|
function icon(name, size) {
|
|
1204
1226
|
var s = size || 18;
|
|
@@ -1605,14 +1627,147 @@ export function observerClientJs() {
|
|
|
1605
1627
|
}
|
|
1606
1628
|
return '<div class="wait"><div class="wait-inner">' + inner + '</div></div>';
|
|
1607
1629
|
}
|
|
1630
|
+
// ---------------------------------------------------------------- replay scrubber
|
|
1631
|
+
// A durable per-turn keyframe replay built PURELY from the artifacts already in the bundle: the
|
|
1632
|
+
// ordered actor.items (reasoning/message/ui_action) sequenced against each persisted screenshot.
|
|
1633
|
+
// No new capture, no schema change, no new privacy surface — it reuses the frames' existing
|
|
1634
|
+
// gitignored / publishable:false posture. (#292 first slice.)
|
|
1635
|
+
function replayFrames(s) {
|
|
1636
|
+
var actor = s && s.actor;
|
|
1637
|
+
var items = actor && actor.items;
|
|
1638
|
+
if (!items || !items.length) return [];
|
|
1639
|
+
var frames = [];
|
|
1640
|
+
var narration = [];
|
|
1641
|
+
var actions = [];
|
|
1642
|
+
for (var i = 0; i < items.length; i += 1) {
|
|
1643
|
+
var it = items[i];
|
|
1644
|
+
if (!it) continue;
|
|
1645
|
+
if (it.kind === "reasoning" || it.kind === "message") { if (it.text) narration.push(String(it.text)); }
|
|
1646
|
+
else if (it.kind === "ui_action") { if (it.title) actions.push(String(it.title)); }
|
|
1647
|
+
else if (it.kind === "screenshot" && it.screenshotRef && it.screenshotRef.path) {
|
|
1648
|
+
frames.push({
|
|
1649
|
+
src: it.screenshotRef.path,
|
|
1650
|
+
label: it.title || ("frame " + (frames.length + 1)),
|
|
1651
|
+
redaction: (it.screenshotRef.redaction && it.screenshotRef.redaction !== "none") ? it.screenshotRef.redaction : "raw",
|
|
1652
|
+
narration: narration,
|
|
1653
|
+
actions: actions
|
|
1654
|
+
});
|
|
1655
|
+
narration = [];
|
|
1656
|
+
actions = [];
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
return frames;
|
|
1660
|
+
}
|
|
1661
|
+
function streamById(id) {
|
|
1662
|
+
var ss = currentData.streams || [];
|
|
1663
|
+
for (var i = 0; i < ss.length; i += 1) { if (ss[i].id === id) return ss[i]; }
|
|
1664
|
+
return null;
|
|
1665
|
+
}
|
|
1666
|
+
function scrubIndexOf(id, frames) {
|
|
1667
|
+
var v = scrubState[id];
|
|
1668
|
+
if (v == null) return frames.length ? frames.length - 1 : 0; // default: the last real frame
|
|
1669
|
+
v = Number(v);
|
|
1670
|
+
if (!(v >= 0)) v = 0;
|
|
1671
|
+
if (v > frames.length - 1) v = frames.length - 1;
|
|
1672
|
+
return v;
|
|
1673
|
+
}
|
|
1674
|
+
function frameInfoHtml(f) {
|
|
1675
|
+
if (!f) return "";
|
|
1676
|
+
var out = "";
|
|
1677
|
+
var acts = (f.actions || []).filter(Boolean);
|
|
1678
|
+
var narr = (f.narration || []).filter(Boolean);
|
|
1679
|
+
if (acts.length) out += '<div class="replay-acts">' + acts.map(function (a) { return '<span class="replay-act">' + esc(a) + '</span>'; }).join("") + '</div>';
|
|
1680
|
+
if (narr.length) out += '<div class="replay-narr">' + esc(narr.join(NL + NL)) + '</div>';
|
|
1681
|
+
if (!out) out = '<div class="replay-narr replay-dim">No narration recorded before this frame.</div>';
|
|
1682
|
+
return out;
|
|
1683
|
+
}
|
|
1684
|
+
function replayScrubber(s) {
|
|
1685
|
+
var frames = replayFrames(s);
|
|
1686
|
+
var id = s.id;
|
|
1687
|
+
var idx = scrubIndexOf(id, frames);
|
|
1688
|
+
var f = frames[idx];
|
|
1689
|
+
var playing = !!scrubTimers[id];
|
|
1690
|
+
return '<div class="replay" data-stream="' + esc(id) + '">'
|
|
1691
|
+
+ '<div class="replay-stage"><img class="surface-fill surface-screenshot" id="replay-img-' + esc(id) + '" src="' + esc(runArtifactHref(f && f.src)) + '" alt="replay frame ' + (idx + 1) + '"/>'
|
|
1692
|
+
+ '<span class="replay-badge" id="replay-badge-' + esc(id) + '" title="frame capture fidelity">' + esc(f ? f.redaction : "raw") + '</span></div>'
|
|
1693
|
+
+ '<div class="replay-bar">'
|
|
1694
|
+
+ '<button class="replay-btn" id="replay-play-' + esc(id) + '" data-action="scrub:' + esc(id) + ':play" aria-label="Play replay">' + icon(playing ? "pause" : "play", 13) + '</button>'
|
|
1695
|
+
+ '<button class="replay-btn" data-action="scrub:' + esc(id) + ':-1" aria-label="Previous frame">' + icon("chevL", 13) + '</button>'
|
|
1696
|
+
+ '<input class="replay-range" type="range" data-role="scrub" data-stream="' + esc(id) + '" min="0" max="' + (frames.length - 1) + '" step="1" value="' + idx + '" aria-label="Scrub frames"/>'
|
|
1697
|
+
+ '<button class="replay-btn" data-action="scrub:' + esc(id) + ':1" aria-label="Next frame">' + icon("chevR", 13) + '</button>'
|
|
1698
|
+
+ '<span class="replay-count mono" id="replay-count-' + esc(id) + '">' + (idx + 1) + '/' + frames.length + '</span>'
|
|
1699
|
+
+ '</div>'
|
|
1700
|
+
+ '<div class="replay-info" id="replay-info-' + esc(id) + '">' + frameInfoHtml(f) + '</div>'
|
|
1701
|
+
+ '</div>';
|
|
1702
|
+
}
|
|
1703
|
+
function updateScrubDom(id) {
|
|
1704
|
+
var s = streamById(id);
|
|
1705
|
+
if (!s) return;
|
|
1706
|
+
var frames = replayFrames(s);
|
|
1707
|
+
if (!frames.length) return;
|
|
1708
|
+
var idx = scrubIndexOf(id, frames);
|
|
1709
|
+
var f = frames[idx];
|
|
1710
|
+
var img = document.getElementById("replay-img-" + id);
|
|
1711
|
+
if (img) img.setAttribute("src", runArtifactHref(f && f.src));
|
|
1712
|
+
var badge = document.getElementById("replay-badge-" + id);
|
|
1713
|
+
if (badge) badge.textContent = f ? f.redaction : "raw";
|
|
1714
|
+
var cnt = document.getElementById("replay-count-" + id);
|
|
1715
|
+
if (cnt) cnt.textContent = (idx + 1) + "/" + frames.length;
|
|
1716
|
+
var info = document.getElementById("replay-info-" + id);
|
|
1717
|
+
if (info) info.innerHTML = frameInfoHtml(f);
|
|
1718
|
+
var range = app.querySelector('.replay-range[data-stream="' + id + '"]');
|
|
1719
|
+
if (range && String(range.value) !== String(idx)) range.value = idx;
|
|
1720
|
+
}
|
|
1721
|
+
function syncPlayBtn(id) {
|
|
1722
|
+
var btn = document.getElementById("replay-play-" + id);
|
|
1723
|
+
if (btn) btn.innerHTML = icon(scrubTimers[id] ? "pause" : "play", 13);
|
|
1724
|
+
}
|
|
1725
|
+
function stopScrubPlay(id) {
|
|
1726
|
+
if (scrubTimers[id]) { clearInterval(scrubTimers[id]); delete scrubTimers[id]; syncPlayBtn(id); }
|
|
1727
|
+
}
|
|
1728
|
+
function stopAllScrubTimers() {
|
|
1729
|
+
for (var k in scrubTimers) { if (scrubTimers.hasOwnProperty(k)) clearInterval(scrubTimers[k]); }
|
|
1730
|
+
scrubTimers = {};
|
|
1731
|
+
}
|
|
1732
|
+
function toggleScrubPlay(id) {
|
|
1733
|
+
if (scrubTimers[id]) { stopScrubPlay(id); return; }
|
|
1734
|
+
var s = streamById(id);
|
|
1735
|
+
var frames = s ? replayFrames(s) : [];
|
|
1736
|
+
if (frames.length < 2) return;
|
|
1737
|
+
if (scrubIndexOf(id, frames) >= frames.length - 1) { scrubState[id] = 0; updateScrubDom(id); } // restart from the top
|
|
1738
|
+
scrubTimers[id] = setInterval(function () {
|
|
1739
|
+
var st = streamById(id);
|
|
1740
|
+
var fr = st ? replayFrames(st) : [];
|
|
1741
|
+
if (fr.length < 2) { stopScrubPlay(id); return; }
|
|
1742
|
+
var cur = scrubIndexOf(id, fr);
|
|
1743
|
+
if (cur >= fr.length - 1) { stopScrubPlay(id); return; }
|
|
1744
|
+
scrubState[id] = cur + 1;
|
|
1745
|
+
updateScrubDom(id);
|
|
1746
|
+
}, 850);
|
|
1747
|
+
syncPlayBtn(id);
|
|
1748
|
+
}
|
|
1749
|
+
function handleScrub(id, op) {
|
|
1750
|
+
var s = streamById(id);
|
|
1751
|
+
var frames = s ? replayFrames(s) : [];
|
|
1752
|
+
if (!frames.length) return;
|
|
1753
|
+
if (op === "play") { toggleScrubPlay(id); return; }
|
|
1754
|
+
stopScrubPlay(id);
|
|
1755
|
+
var idx = scrubIndexOf(id, frames) + Number(op);
|
|
1756
|
+
if (idx < 0) idx = 0;
|
|
1757
|
+
if (idx > frames.length - 1) idx = frames.length - 1;
|
|
1758
|
+
scrubState[id] = idx;
|
|
1759
|
+
updateScrubDom(id);
|
|
1760
|
+
}
|
|
1608
1761
|
function browserSurface(s, focus) {
|
|
1609
1762
|
var live = tone(s.status) === "running";
|
|
1610
1763
|
var route = laneRoute(s) || "(local)";
|
|
1611
1764
|
var liveUrl = browserLiveUrl(s);
|
|
1612
1765
|
var shot = browserShot(s);
|
|
1613
1766
|
var dock = focus ? browserLabDock(s, shot) : "";
|
|
1767
|
+
var showReplay = focus && !(liveUrl && S.media === "live") && replayFrames(s).length >= 2;
|
|
1614
1768
|
var body;
|
|
1615
1769
|
if (liveUrl && S.media === "live") body = liveStreamMount(s, liveUrl);
|
|
1770
|
+
else if (showReplay) body = replayScrubber(s);
|
|
1616
1771
|
else if (shot) body = '<img class="surface-fill surface-screenshot" src="' + esc(shot) + '" alt="' + (s.desktopGeometry ? "desktop screenshot" : "browser screenshot") + '"/>';
|
|
1617
1772
|
else body = '<div class="bw-app-wait"><div class="wait-spinner" style="width:24px;height:24px"></div>'
|
|
1618
1773
|
+ '<div class="mono" style="font-size:9px">' + esc(route) + '</div>'
|
|
@@ -2495,6 +2650,7 @@ export function observerClientJs() {
|
|
|
2495
2650
|
}
|
|
2496
2651
|
|
|
2497
2652
|
function render() {
|
|
2653
|
+
stopAllScrubTimers(); // a full rebuild replaces the scrubber DOM; never leave a timer ticking on stale nodes
|
|
2498
2654
|
var docEl = document.documentElement;
|
|
2499
2655
|
docEl.setAttribute("data-theme", S.theme);
|
|
2500
2656
|
docEl.setAttribute("data-motion", S.motion);
|
|
@@ -2561,6 +2717,7 @@ export function observerClientJs() {
|
|
|
2561
2717
|
var arg = parts[1];
|
|
2562
2718
|
var arg2 = parts[2];
|
|
2563
2719
|
switch (cmd) {
|
|
2720
|
+
case "scrub": handleScrub(arg, arg2); break;
|
|
2564
2721
|
case "open": openFocus(arg); break;
|
|
2565
2722
|
case "select": S.focusedId = arg; writeHash(arg); render(); break;
|
|
2566
2723
|
case "exit-focus": exitFocus(); break;
|
|
@@ -2615,7 +2772,16 @@ export function observerClientJs() {
|
|
|
2615
2772
|
});
|
|
2616
2773
|
app.addEventListener("input", function (e) {
|
|
2617
2774
|
var t = e.target;
|
|
2618
|
-
if (t
|
|
2775
|
+
if (!t || !t.getAttribute) return;
|
|
2776
|
+
if (t.getAttribute("data-role") === "search") { S.query = t.value; render(); return; }
|
|
2777
|
+
if (t.getAttribute("data-role") === "scrub") {
|
|
2778
|
+
// Direct DOM update (NOT a full render) so dragging the slider stays smooth and the slider
|
|
2779
|
+
// element is not rebuilt mid-drag. Position is stashed in scrubState so a later render restores it.
|
|
2780
|
+
var sid = t.getAttribute("data-stream");
|
|
2781
|
+
stopScrubPlay(sid);
|
|
2782
|
+
scrubState[sid] = Number(t.value);
|
|
2783
|
+
updateScrubDom(sid);
|
|
2784
|
+
}
|
|
2619
2785
|
});
|
|
2620
2786
|
document.addEventListener("mousedown", function (e) {
|
|
2621
2787
|
if (openDd) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observer-assets.js","sourceRoot":"","sources":["../src/observer-assets.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,gFAAgF;AAChF,+EAA+E;AAC/E,iEAAiE;AACjE,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,+CAA+C;AAE/C,MAAM,UAAU,WAAW;IACzB,OAAO
|
|
1
|
+
{"version":3,"file":"observer-assets.js","sourceRoot":"","sources":["../src/observer-assets.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,gFAAgF;AAChF,+EAA+E;AAC/E,iEAAiE;AACjE,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,+CAA+C;AAE/C,MAAM,UAAU,WAAW;IACzB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsjCR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmxDR,CAAC;AACF,CAAC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Date: 2026-06-02 (current-state note updated 2026-07-14)
|
|
4
4
|
|
|
5
5
|
Status: reference map for the major contracts shipped through source version
|
|
6
|
-
`0.20.
|
|
6
|
+
`0.20.4`; it is not an exhaustive inventory of command/result envelopes. Exported types,
|
|
7
7
|
schema constants, parsers, and validators in `src/` are authoritative. Rows
|
|
8
8
|
marked "reserved" name layering intent only — no code emits or validates them
|
|
9
9
|
yet. Do not emit a reserved schema.
|
package/docs/goals/current.md
CHANGED
|
@@ -16,7 +16,7 @@ Humanish should be the open-source CLI that lets a maintainer ask:
|
|
|
16
16
|
The answer should be observable, verifiable, public-safe, and easy to turn into
|
|
17
17
|
actionable feedback.
|
|
18
18
|
|
|
19
|
-
## Current Program Truth (source `0.20.
|
|
19
|
+
## Current Program Truth (source `0.20.4`)
|
|
20
20
|
|
|
21
21
|
The package source and repository implementation in this tree agree on these
|
|
22
22
|
points:
|
package/docs/ramp/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Status: public-safe contributor and agent ramp.
|
|
4
4
|
|
|
5
|
-
Package/source version in this tree: `0.20.
|
|
5
|
+
Package/source version in this tree: `0.20.4` (2026-08-03). The containment boundary introduced in
|
|
6
6
|
`0.15.1` remains in force: managed run and output paths bind to validated
|
|
7
7
|
physical filesystem identities, and stored provider IDs are evidence, not
|
|
8
8
|
cleanup authority. The bundled OSS meta-lab is dry-run only until
|
package/package.json
CHANGED