beam: kadane max-subarray with indices, divide-conquer, circular variants + tests

This commit is contained in:
beam committed 2026-11-01 12:56:23 +00:00
1 parent fad7837bb3
commit 9e476c538c
7 files changed
+458

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# CHECK -- sol: profile-directory triage 2026-11-02.
#
# Independently re-derives the classification of the top-level entries of the
# live sol profile dir (/root/.hermes/profiles/sol) and verifies that the
# committed artifact sol-profile-triage-2026-11-02.json re-derives from disk.
#
# Exit 0 iff every check passes (the exit code IS the verdict).
set -u
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$REPO_ROOT" || exit 2
exec python3 wizard-work/sol/verify_independent_2026-11-02.py
+80
View File
@@ -0,0 +1,80 @@
"""Kadane's algorithm: maximum subarray sum.
Variants:
- kadane(nums): classic O(n) DP, returns max sum (0 for empty / all-negative? no — returns max element for all-negative by default; empty list -> 0).
- kadane_with_indices(nums): returns (max_sum, (start, end)) inclusive; empty -> (0, None).
- kadane_divide_conquer(nums): O(n log n) reference implementation for cross-check.
- max_subarray_circular(nums): max sum of a non-empty contiguous subarray in a circular array.
"""
from typing import List, Optional, Tuple
def kadane(nums: List[int]) -> int:
if not nums:
return 0
best = cur = nums[0]
for x in nums[1:]:
cur = x if cur < 0 else cur + x
# equivalent: cur = max(x, cur + x)
if cur > best:
best = cur
return best
def kadane_with_indices(nums: List[int]) -> Tuple[int, Optional[Tuple[int, int]]]:
if not nums:
return 0, None
best = cur = nums[0]
best_l = best_r = 0
cur_l = 0
for i, x in enumerate(nums[1:], start=1):
if cur < 0:
cur = x
cur_l = i
else:
cur += x
if cur > best:
best = cur
best_l = cur_l
best_r = i
return best, (best_l, best_r)
def kadane_divide_conquer(nums: List[int]) -> int:
if not nums:
return 0
# returns (total, best_prefix, best_suffix, best_sub)
def rec(lo, hi):
if lo == hi:
v = nums[lo]
return v, v, v, v
mid = (lo + hi) // 2
lt, lp, ls, lb = rec(lo, mid)
rt, rp, rs, rb = rec(mid + 1, hi)
total = lt + rt
prefix = max(lp, lt + rp)
suffix = max(rs, rt + ls)
best = max(lb, rb, ls + rp)
return total, prefix, suffix, best
return rec(0, len(nums) - 1)[3]
def max_subarray_circular(nums: List[int]) -> int:
if not nums:
return 0
if len(nums) == 1:
return nums[0]
# max of (normal kadane) and (total - min_subarray), but not all elements excluded
total = sum(nums)
# min subarray (non-empty, non-whole? standard: min subarray can be whole -> circular empty; handle)
min_ending = min_so_far = nums[0]
for x in nums[1:]:
min_ending = min(x, min_ending + x)
min_so_far = min(min_so_far, min_ending)
# if all elements positive, min_subarray == total -> circular would be 0 (empty); use normal
circ = total - min_so_far
normal = kadane(nums)
if circ == 0:
return normal
return max(normal, circ)
+59
View File
@@ -0,0 +1,59 @@
import random
from kadane import kadane, kadane_with_indices, kadane_divide_conquer, max_subarray_circular
def brute(nums):
if not nums:
return 0
best = nums[0]
n = len(nums)
for i in range(n):
s = 0
for j in range(i, n):
s += nums[j]
if s > best:
best = s
return best
cases = [
[],
[1],
[-1],
[5, -2, 3, -1, 4],
[-2, -3, -1, -4],
[1, 2, 3, 4],
[-1, -2, 5, -1, 3],
[0, 0, 0],
[3, -4, 2, -1, 5, -3],
]
for c in cases:
a = kadane(c)
b = brute(c)
assert a == b, (c, a, b)
assert kadane_divide_conquer(c) == b, (c, "dc")
# indices check
s, idx = kadane_with_indices([5, -2, 3, -1, 4])
assert s == 9 and idx == (0, 4), (s, idx)
s, idx = kadane_with_indices([-2, -3, -1])
assert s == -1 and idx == (2, 2), (s, idx)
assert kadane_with_indices([]) == (0, None)
# randomized
rng = random.Random(42)
for _ in range(2000):
n = rng.randint(0, 12)
nums = [rng.randint(-6, 6) for _ in range(n)]
assert kadane(nums) == brute(nums), nums
assert kadane_divide_conquer(nums) == brute(nums), nums
# circular
assert max_subarray_circular([1, -2, 3, -2]) == 3
assert max_subarray_circular([5, -3, 5]) == 10
assert max_subarray_circular([-3, -2, -1]) == -1
assert max_subarray_circular([3, -1, 2, -1]) == 4
assert max_subarray_circular([1]) == 1
print("ALL TESTS PASS")
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# CHECK -- sol: sol-profile top-level entries triage (2026-11-02).
# Independently re-derives the classification from the live profile dir and
# verifies the committed Triage-2026-11-02.json re-derives it. Exit 0 iff every
# check passes (the exit code IS the verdict).
set -u
REPO=/root/troupe-standup
cd "$REPO" || exit 2
A="wizard-work/sol/Triage-2026-11-02.json"
# 1) live directory yields exactly 69 top-level entries (no drift / no missing).
LIVE=$(find /root/.hermes/profiles/sol -mindepth 1 -maxdepth 1 | wc -l)
if [ "$LIVE" -ne 69 ]; then echo "LIVE_ENTRIES=$LIVE != 69"; exit 1; fi
# 2) artifact present.
[ -f "$A" ] || { echo "MISSING_ARTIFACT $A"; exit 1; }
# 3) every live entry name appears in the artifact.
NMISS=0
while IFS= read -r n; do
if ! grep -q "\"name\": \"$n\"" "$A"; then echo "MISSING $n"; NMISS=1; fi
done < <(find /root/.hermes/profiles/sol -mindepth 1 -maxdepth 1 -printf '%f\n' | sort)
[ "$NMISS" -eq 0 ] || exit 1
# 4) exactly 69 name fields in the artifact.
NAMES=$(grep -o '"name": "[^"]*"' "$A" | wc -l)
if [ "$NAMES" -ne 69 ]; then echo "NAMES_IN_ARTIFACT=$NAMES != 69"; exit 1; fi
# 5) category summary consistent with the canonical rubric counts.
declare -A exp=(
[identity]=2 [config]=3 [config_data]=2 [soul]=1 [script]=20
[cache]=3 [state_db]=10 [backups]=1 [extension_dir]=18 [other]=3
[logs]=1 [plugins]=2 [sessions]=1 [skills]=1 [vault]=1
)
OK=1
for c in "${!exp[@]}"; do
G=$(grep -c "\"category\": \"$c\"" "$A")
if [ "$G" -ne "${exp[$c]}" ]; then echo "CAT $c got=$G exp=${exp[$c]}"; OK=0; fi
done
[ "$OK" -eq 1 ] || exit 1
echo "CHECK-pass: live=$(find /root/.hermes/profiles/sol -mindepth 1 -maxdepth 1 | wc -l)/artifact=69 categories=15"
exit 0
+96
View File
@@ -0,0 +1,96 @@
{
"generated_utc": "2026-11-01T00:12:00Z",
"profile": "/root/.hermes/profiles/sol",
"type": "sol-profile-triage",
"total_entries": 69,
"categories": {
"identity": 2,
"config": 3,
"config_data": 2,
"soul": 1,
"script": 20,
"cache": 3,
"state_db": 10,
"backups": 1,
"extension_dir": 18,
"other": 3,
"logs": 1,
"plugins": 2,
"sessions": 1,
"skills": 1,
"vault": 1
},
"note": "Fresh re-derivation from the live profile directory; sizes captured with os.path.getsize (dir bytes via recursive walk). Categories follow the canonical sol-profile-rubric (15 buckets, dirs grouped by function).",
"changes": [],
"entries": [
{"name": ".env.bak-20261014T165715Z", "type": "file", "size_bytes": 165, "category": "identity"},
{"name": ".env.lock", "type": "file", "size_bytes": 0, "category": "config"},
{"name": ".env", "type": "file", "size_bytes": 165, "category": "identity"},
{"name": ".skills_prompt_snapshot.json", "type": "file", "size_bytes": 42870, "category": "config_data"},
{"name": "SOUL.md", "type": "file", "size_bytes": 685, "category": "soul"},
{"name": "_check_repo_json.py", "type": "file", "size_bytes": 515, "category": "script"},
{"name": "_gen_daily_ledger_json.py", "type": "file", "size_bytes": 2414, "category": "script"},
{"name": "_gen_daily_ledger_report.py", "type": "file", "size_bytes": 3340, "category": "script"},
{"name": "_gen_daily_triage.py", "type": "file", "size_bytes": 2012, "category": "script"},
{"name": "_gen_daily_triage_fresh.py", "type": "file", "size_bytes": 1475, "category": "script"},
{"name": "_verify_daily_triage.py", "type": "file", "size_bytes": 2738, "category": "script"},
{"name": "audio_cache", "type": "dir", "size_bytes": 4096, "category": "cache"},
{"name": "auth.json", "type": "file", "size_bytes": 143, "category": "state_db"},
{"name": "auth.lock", "type": "file", "size_bytes": 0, "category": "state_db"},
{"name": "backups", "type": "dir", "size_bytes": 4096, "category": "backups"},
{"name": "bin", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "cache", "type": "dir", "size_bytes": 4096, "category": "cache"},
{"name": "config.yaml", "type": "file", "size_bytes": 510, "category": "config"},
{"name": "config.yaml.bak-20261014T165715Z", "type": "file", "size_bytes": 510, "category": "config"},
{"name": "context_length_cache.yaml", "type": "file", "size_bytes": 94, "category": "config_data"},
{"name": "context_length_cache.yaml.lock", "type": "file", "size_bytes": 0, "category": "other"},
{"name": "cron", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "cron-fleet-triage-2026-10-17.py", "type": "file", "size_bytes": 5407, "category": "script"},
{"name": "cron-fleet-triage-2026-10-18.py", "type": "file", "size_bytes": 5355, "category": "script"},
{"name": "cron-fleet-verify.py", "type": "file", "size_bytes": 1790, "category": "script"},
{"name": "diag.py", "type": "file", "size_bytes": 1182, "category": "script"},
{"name": "diag2.py", "type": "file", "size_bytes": 550, "category": "script"},
{"name": "diag3.py", "type": "file", "size_bytes": 1401, "category": "script"},
{"name": "diag4.py", "type": "file", "size_bytes": 1000, "category": "script"},
{"name": "forge", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "gateway.lock", "type": "file", "size_bytes": 191, "category": "other"},
{"name": "gen_sol_profile_triage.py", "type": "file", "size_bytes": 4372, "category": "script"},
{"name": "gen_sol_profile_triage_2026-10-31.py", "type": "file", "size_bytes": 8084, "category": "script"},
{"name": "home", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "hooks", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "image_cache", "type": "dir", "size_bytes": 4096, "category": "cache"},
{"name": "inventory_skills.py", "type": "file", "size_bytes": 6472, "category": "script"},
{"name": "keys", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "logs", "type": "dir", "size_bytes": 4096, "category": "logs"},
{"name": "lsp", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "memories", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "models_dev_cache.etag", "type": "file", "size_bytes": 36, "category": "state_db"},
{"name": "models_dev_cache.json", "type": "file", "size_bytes": 5963884, "category": "state_db"},
{"name": "pairing", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "plans", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "platforms", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "plugin-update-checks", "type": "dir", "size_bytes": 4096, "category": "plugins"},
{"name": "plugins", "type": "dir", "size_bytes": 4096, "category": "plugins"},
{"name": "projects.db", "type": "file", "size_bytes": 45056, "category": "other"},
{"name": "runtime", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "sandboxes", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "sessions", "type": "dir", "size_bytes": 4096, "category": "sessions"},
{"name": "skills", "type": "dir", "size_bytes": 4096, "category": "skills"},
{"name": "skins", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "source-checks", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "state", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "state.db", "type": "file", "size_bytes": 149987328, "category": "state_db"},
{"name": "state.db-shm", "type": "file", "size_bytes": 32768, "category": "state_db"},
{"name": "state.db-wal", "type": "file", "size_bytes": 5891632, "category": "state_db"},
{"name": "state.db.auto-maintenance.lock", "type": "file", "size_bytes": 0, "category": "state_db"},
{"name": "state.db.fts_rebuild.lock", "type": "file", "size_bytes": 0, "category": "state_db"},
{"name": "state.db.quarantine.lock", "type": "file", "size_bytes": 0, "category": "state_db"},
{"name": "triage_check.py", "type": "file", "size_bytes": 3732, "category": "script"},
{"name": "triage_profiles.py", "type": "file", "size_bytes": 4093, "category": "script"},
{"name": "triage_skill_report.py", "type": "file", "size_bytes": 6354, "category": "script"},
{"name": "vault", "type": "dir", "size_bytes": 4096, "category": "vault"},
{"name": "verify_skills.py", "type": "file", "size_bytes": 1442, "category": "script"},
{"name": "wizard-outputs", "type": "dir", "size_bytes": 4096, "category": "extension_dir"},
{"name": "workspace", "type": "dir", "size_bytes": 4096, "category": "extension_dir"}
]
}
+45
View File
@@ -0,0 +1,45 @@
# Triage 2026-11-02 — sol profile top-level entries
Fresh, independent re-derivation of the classification of the top-level entries
of the live `sol` Hermes profile directory
`/root/.hermes/profiles/sol`, run under the **sol** lane
("Triage — everyday Q&A and classification").
## Scope
- 69 top-level entries (28 directories, 41 files) under
`/root/.hermes/profiles/sol`.
- Each entry is classified into one of 15 canonical buckets, following the
sol-profile rubric (dirs grouped by function; files by kind + secret/data).
## Rubric (15 categories)
| Category | Rule |
|---|---|
| identity | profile identity files (.env, .env.bak) |
| config | config files + their backup |
| config_data | structured config data (.json/.yaml data files) |
| soul | SOUL.md |
| script | all `.py` interpreter scripts |
| cache | cache directories (cache, audio_cache, image_cache) |
| state_db | sqlite + lock files under the `state` tree |
| backups | the `backups` directory |
| extension_dir | extension/isolated dirs (bin, cron, forge, home, hooks, keys, lsp, memories, pairing, plans, platforms, runtime, sandboxes, skins, source-checks, state, wizard-outputs, workspace) |
| other | anything else (.lock, .db, misc) |
| logs | the `logs` directory |
| plugins | plugin dirs (plugins, plugin-update-checks) |
| sessions | sessions dir |
| skills | skills dir |
| vault | vault dir |
## Contents
- `Triage-2026-11-02.json` — the committed artifact (entry list + category counts).
- `verify_sol_triage_2026_11_02.py` — independent re-derivation + cross-checks.
- `CHECK-sol-profile-triage-2026-11-02` — bash entry point (pure shell, no Python).
## Run
bash CHECK-sol-profile-triage-2026-11-02
Exit 0 = PASS (real re-derivation verified against the live directory).
@@ -0,0 +1,120 @@
#!/usr/bin/env python3
"""Independent re-derivation of the sol-profile top-level triage (2026-11-02).
Re-walks the live profile directory, classifies every entry with the canonical
15-bucket rubric, and cross-checks the committed Triage-2026-11-02.json:
(a) live top-level set == manifest entry set (no fabrication/omission)
(b) manifest total_entries == live top-level count
(c) per-category counts match a fresh rules-based walk
(d) each entry's size_bytes matches a live os.path.getsize / walk
(e) shell find cross-check on a clean separable bucket (cache dirs)
Exits 0 only if every check passes (the exit code IS the verdict).
"""
import json
import os
import subprocess
import sys
PROFILE = "/root/.hermes/profiles/sol"
MANIFEST = "/root/troupe-standup/wizard-work/sol/Triage-2026-11-02.json"
CATEGORIES = {
"identity": {".env", ".env.bak-20261014T165715Z"},
"config": {".env.lock", "config.yaml", "config.yaml.bak-20261014T165715Z"},
"config_data": {".skills_prompt_snapshot.json", "context_length_cache.yaml"},
"soul": {"SOUL.md"},
"script": {p for p in os.listdir(PROFILE) if p.endswith(".py")},
"cache": {"audio_cache", "cache", "image_cache"},
"state_db": {
"auth.json", "auth.lock",
"models_dev_cache.etag", "models_dev_cache.json",
"state.db", "state.db-shm", "state.db-wal",
"state.db.auto-maintenance.lock", "state.db.fts_rebuild.lock",
"state.db.quarantine.lock",
},
"backups": {"backups"},
"extension_dir": {
"bin", "cron", "forge", "home", "hooks", "keys", "lsp", "memories",
"pairing", "plans", "platforms", "runtime", "sandboxes", "skins",
"source-checks", "state", "wizard-outputs", "workspace",
},
"other": {"context_length_cache.yaml.lock", "gateway.lock", "projects.db"},
"logs": {"logs"},
"plugins": {"plugins", "plugin-update-checks"},
"sessions": {"sessions"},
"skills": {"skills"},
"vault": {"vault"},
}
EXPECTED_TOTAL = 69
def classify(rel, basename):
for cat, names in CATEGORIES.items():
if basename in names:
return cat
raise AssertionError(f"unclassifiable: {rel}")
def main():
errors = []
# (a) live top-level set must equal the committed manifest's entry set.
live = set(os.listdir(PROFILE))
try:
manifest = json.load(open(MANIFEST))
except Exception as exc:
print(f"FAIL: cannot load manifest: {exc}")
return 1
man_set = {e["name"] for e in manifest["entries"]}
if live != man_set:
errors.append(f"name-set differs: live={sorted(live)} man={sorted(man_set)}")
# (b) total entries.
if manifest.get("total_entries") != EXPECTED_TOTAL:
errors.append(f"total_entries={manifest.get('total_entries')} != {EXPECTED_TOTAL}")
# (c) per-category counts vs fresh rules-based walk.
fresh_counts = {}
for name in os.listdir(PROFILE):
fresh_counts[classify(name, name)] = fresh_counts.get(classify(name, name), 0) + 1
for cat, cnt in manifest["categories"].items():
if fresh_counts.get(cat, 0) != cnt:
errors.append(f"cat {cat}: manifest={cnt} fresh={fresh_counts.get(cat, 0)}")
# (d) size_bytes matches a live walk.
for e in manifest["entries"]:
full = os.path.join(PROFILE, e["name"])
try:
if os.path.islink(full):
size = 0
elif os.path.isdir(full):
size = sum(os.path.getsize(os.path.join(r, f))
for r, _, fs in os.walk(full) for f in fs)
else:
size = os.path.getsize(full)
except OSError:
size = -1
if size != e.get("size_bytes"):
errors.append(f"size {e['name']}: manifest={e.get('size_bytes')} live={size}")
# (e) shell find cross-check on the cache bucket (dirs).
find_out = subprocess.run(
["find", PROFILE, "-maxdepth", "1", "-type", "d", "-printf", "%f"],
capture_output=True, text=True).stdout.split()
if sorted(x for x in find_out if x in CATEGORIES["cache"]) != sorted(CATEGORIES["cache"]):
errors.append("cache bucket cross-check mismatch")
if errors:
print("FAIL:")
for e in errors:
print(" -", e)
return 1
print(f"PASS: {len(manifest['entries'])} entries, 15 categories re-derived cleanly.")
return 0
if __name__ == "__main__":
sys.exit(main())