One implementation of string slice/substring/replace; check inline code passed through process.run - #262
Merged
b-macker merged 3 commits intoSep 28, 2026
Conversation
…er hang Dogfood round 3 reported string.slice "not fixed" (it ran a build without #261), but checking it found that s.slice(...) worked as a METHOD while string.slice(...) did not exist -- and that the method forms disagreed between engines. Four copies (VM method dispatch, two tree-walker method paths, the string module); measured on "hello" / "a-b-c": s.replace("-", "+") VM a+b-c (first only) tree-walker a+b+c s.substring(3, 1) VM "" tree-walker "lo" (wrapped size_t) s.slice(-3) VM llo tree-walker hello (aliased to substring) and "ab".replace("", "+") hung the tree-walker: find("") matches at every position, so it inserted forever with growing memory. --timeout cannot stop it (the loop never returns to the interpreter), and the REST API runs the tree-walker. The VM gave "+ab". The module functions agreed with each other in every case, so they are the reference: include/naab/string_ops.h holds substring, slice (JavaScript semantics) and replaceAll (empty pattern = unchanged), and all four sites call it. string.slice(s, start[, end]) is added as a module function. Tests: tests/differential/corpus/string_methods.naab (the corpus only had module-form string probes, which is why none of this surfaced) and test_dogfood_hints.sh S-06 (string.slice) and E-01 (the hang, both engines, 10s limit). Against the previous build S-06 and E-01 fail in both engines, E-01/tree-walk by being killed at 10s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ELUfjXZvx8kzXo1UJjrAhC
NAAb Governance Report
All governance checks passed! Generated by NAAb Governance Engine v4.0 |
process.run("python3", ["-c", code]) is a <<python>> block by another name,
but it skipped every code check the block and codegen.run() get. Found
dogfooding repo-sentinel: a size helper that swallowed every error
(`except Exception: return 0`) and reported every C++ file as 0 bytes. The
project's own no_incomplete_logic (HARD) blocks that code as a block and in
codegen.run(); through process.run it ran silently.
process.run now recognises python/pypy -c, node -e/-p/--eval/--print,
ruby -e, perl -e/-E, php -r and sh/bash/dash/zsh/ksh -c (through a directory
prefix, .exe, a version suffix, and clustered short flags) and passes the
code to checkPolyglotBlock(). A script file is not inline code and is not
scanned; only the outer interpreter is recognised.
Test: tests/security/test_process_run_inline_gate.sh, 14/14 on both engines;
the prior build fails exactly PI-01 and PI-03 on each. The python -c and
sh -c calls in living-script{,_v2,_extended} and hivemind{,_governed} run
unchanged under their own configs on both builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ELUfjXZvx8kzXo1UJjrAhC
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ELUfjXZvx8kzXo1UJjrAhC
Owner
Author
|
Local results at
CI on Generated by Claude Code |
b-macker
marked this pull request as ready for review
September 28, 2026 20:02
b-macker
deleted the
claude/naab-inadmissible-action-prevention-4cmn1m
branch
September 28, 2026 20:02
b-macker
pushed a commit
that referenced
this pull request
Sep 28, 2026
… failed call Found checking the repo-sentinel F-008 handoff. 1. Coherence moved without telemetry. Natural healing, temporal decay, the clamp at 0 and recoverCoherence() (passed step-up, failed pipeline stage) were reported nowhere, so listed penalties never matched the drop and the dogfood reported CDD's arithmetic as broken. It was exact once healing was added back. CDD_TURN now carries coherence_adjustments (temporal_decay/natural_healing/floor_absorbed/recovery), kept out of penalties_detail because consumers read a non-empty penalties_detail as "a signal paid". validation_recovery reports the credit received. 2. The response after a retry-exhausted API failure was never analyzed. The failure was analyzed at the same turn number the next response carries, took the interval slot, and the response was skipped by all 23 signals while its CDD_TURN said analyzed:"true". Infrastructure errors now return before analysis when exclude_infrastructure_errors is on (default: they feed no signal), and hand the slot back when it is off. The analyzed label now comes from an analysis counter, not a turn-number comparison. 3. Untrack examples/hivemind/src/hivemind-telemetry.jsonl (10 MB). It is the live output target of the hivemind configs, so every run appended to a tracked file; nothing reads it. Test: tests/governance_v4/test_coherence_reconcile.sh, 7/7. The #262 build fails RC-01/RC-02 (11 of 12 rows do not reconcile) and IA-01/IA-02 (the repeated response escapes S21 while labelled analyzed); IA-03 is the control. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ELUfjXZvx8kzXo1UJjrAhC
b-macker
added a commit
that referenced
this pull request
Sep 28, 2026
… failed call (#263) Found checking the repo-sentinel F-008 handoff. 1. Coherence moved without telemetry. Natural healing, temporal decay, the clamp at 0 and recoverCoherence() (passed step-up, failed pipeline stage) were reported nowhere, so listed penalties never matched the drop and the dogfood reported CDD's arithmetic as broken. It was exact once healing was added back. CDD_TURN now carries coherence_adjustments (temporal_decay/natural_healing/floor_absorbed/recovery), kept out of penalties_detail because consumers read a non-empty penalties_detail as "a signal paid". validation_recovery reports the credit received. 2. The response after a retry-exhausted API failure was never analyzed. The failure was analyzed at the same turn number the next response carries, took the interval slot, and the response was skipped by all 23 signals while its CDD_TURN said analyzed:"true". Infrastructure errors now return before analysis when exclude_infrastructure_errors is on (default: they feed no signal), and hand the slot back when it is off. The analyzed label now comes from an analysis counter, not a turn-number comparison. 3. Untrack examples/hivemind/src/hivemind-telemetry.jsonl (10 MB). It is the live output target of the hivemind configs, so every run appended to a tracked file; nothing reads it. Test: tests/governance_v4/test_coherence_reconcile.sh, 7/7. The #262 build fails RC-01/RC-02 (11 of 12 rows do not reconcile) and IA-01/IA-02 (the repeated response escapes S21 while labelled analyzed); IA-03 is the control. Claude-Session: https://claude.ai/code/session_01ELUfjXZvx8kzXo1UJjrAhC Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Round 3 of dogfooding (the repo-sentinel project) turned up two problems. This PR fixes both.
1. String methods disagreed between engines, and one hung
Round 3 reported F-007, the
string.slicehint, as "not fixed". It had run a build without #261, which does suggestsubstring. Checking it turned up something bigger:s.slice(...)worked as a method, whilestring.slice(...)didn't exist as a function.Each operation had four hand-written copies: VM method dispatch, two tree-walker method paths, and the
stringmodule.s.replace("-", "+")a+b-c(first match only)a+b+cs.substring(3, 1)"""lo"(a length calculation underflows)s.slice(-3)llohello(treated assubstring)"ab".replace("", "+")+abThe last row is the serious one. The tree-walker's
replacedidn't guard against an empty pattern. An empty string matches at every position, so it kept inserting forever while memory grew.--timeoutcan't stop it, because the loop never returns to the interpreter, and the REST API runs the tree-walker.2. Inline code in
process.runskipped the code checksrepo-sentinel reported every C++ file as 0 bytes. The cause was a Python helper that swallowed every error:
The project's own
code_quality.no_incomplete_logic(HARD) blocks that exact code in a<<python>>block and incodegen.run(). repo-sentinel ran it asprocess.run("python3", ["-c", code])instead, and it went through with no check at all. NAAb already had the rule that would have caught the bug.Changes
include/naab/string_ops.hwithsubstring,sliceandreplaceAll, called from all four places:stringmodule functions already agreed with each other in every case, so their behaviour is the reference.replacereplaces every occurrence; an empty pattern leaves the string unchanged.substringclamps out-of-range indices and returns""for an empty or reversed range.slicefollows JavaScript: negative indices count from the end.string.slice(s, start[, end])is now a module function, behaving the same as the method.string.substrkeeps its hint pointing tosubstring, because JavaScript'ssubstrtakes a length rather than an end index.process.runinline-code check (src/stdlib/process_impl.cpp): when the command is an interpreter given inline code, that code goes throughcheckPolyglotBlock(), the same check<<python>>blocks andcodegen.run()use. Recognised:-c-e/-p/--eval/--print, also--eval=-e-e/-E-r-c.exe, a version suffix (python3.12), and combined short flags when the code flag comes last (-Ic,-ec).languages.allowed/blockednow apply to that inline code too.python3 s.py) isn't scanned, and only the outer interpreter is recognised.Test Plan
tests/differential/corpus/string_methods.naab. The corpus only exercised the module form of these functions, which is why none of this showed up. Differential run: 57 passed, 0 failed.tests/parser/test_dogfood_hints.sh: 21/21 pass. S-06 checksstring.sliceworks; E-01 checks empty-patternreplaceunder a 10 s limit.process.runcheck:tests/security/test_process_run_inline_gate.sh: 14/14 across both engines.<<python>>block is blocked under this config, so the config does exercise the check.python3 -c, harmlesssh -candecho -c <text>still run.python3 -candsh -ccalls in living-script, living-script_v2, living-script_extended, hivemind and hivemind_governed run unchanged under their owngovern.json, on both builds.checkPolyglotBlock's messages.🤖 Generated with Claude Code
https://claude.ai/code/session_01ELUfjXZvx8kzXo1UJjrAhC