Merge remote-tracking branch 'origin/main' into feat/the-agent-account-is-declared
mesh/merge-gate pass: builds claude-code, claude-licence-manager, restic, sudo → ace, g14, novox, shanks; no bus step; every machine composes with the chan…
mesh/repo-check pass: THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges; it…
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate pass: builds claude-code, claude-licence-manager, restic, sudo → ace, g14, novox, shanks; no bus step; every machine composes with the chan…
mesh/repo-check pass: THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges; it…
mesh/delivery superseded: a newer head of the same pull request
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The daemons' lines (novox/hq ADR 0272, its insight of 2026-10-09): the operator types one command, `nox`
|
||||
// (`mesh-cli`). The node-engine (`nox-mesh-host`) and the controller (`mesh-controller`) are daemons, and a
|
||||
// person never types their names — so no text a module can show names a line of theirs. The list is the
|
||||
// copy in retired-lines at the catalogue's root, which novox/hq's words.py prints (`--list lines`) and
|
||||
// compares; one line each, `<daemon> <command>`, and a trailing ` …` for a command that is a line only with
|
||||
// an argument after it (`mesh-controller module check` is a line; "the mesh-controller module" is prose).
|
||||
|
||||
// retiredLine is one daemon's line: the daemon, its command, and whether an argument must follow.
|
||||
type retiredLine struct {
|
||||
daemon, command string
|
||||
withArgument bool
|
||||
}
|
||||
|
||||
// readLines reads retired-lines: one line a line; blank lines and lines starting with # are not lines.
|
||||
func readLines(path string) ([]retiredLine, error) {
|
||||
entries, err := readList(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []retiredLine
|
||||
for _, e := range entries {
|
||||
withArgument := strings.HasSuffix(e, " …")
|
||||
e = strings.TrimSuffix(e, " …")
|
||||
parts := strings.Fields(e)
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("retired-lines: %q is not `<daemon> <command>`", e)
|
||||
}
|
||||
out = append(out, retiredLine{daemon: parts[0], command: parts[1], withArgument: withArgument})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// linePattern matches the line whole: the daemon, white space, the command. A command that is a line only
|
||||
// with an argument is matched as a line is written — at the start of a line or a code span, a prompt allowed,
|
||||
// with an argument after it — so prose that names the daemon beside the word ("the mesh-controller module is
|
||||
// assigned") is not one.
|
||||
func linePattern(l retiredLine) *regexp.Regexp {
|
||||
daemon, command := regexp.QuoteMeta(l.daemon), regexp.QuoteMeta(l.command)
|
||||
if l.withArgument {
|
||||
tick := "`"
|
||||
return regexp.MustCompile(`(?m)(?:^|` + tick + `)[ \t]*(?:\$[ \t]*)?(` + daemon + `\s+` + command + `\s+[^\s` + tick + `])`)
|
||||
}
|
||||
return regexp.MustCompile(`(?:^|[^\w-])(` + daemon + `\s+` + command + `)(?:$|[^\w-])`)
|
||||
}
|
||||
|
||||
// checkLines finds every daemon's line in the texts.
|
||||
func checkLines(lines []retiredLine, texts []text) []string {
|
||||
var out []string
|
||||
for _, l := range lines {
|
||||
rx := linePattern(l)
|
||||
for _, t := range texts {
|
||||
if m := rx.FindStringSubmatchIndex(t.s); m != nil {
|
||||
line := t.line
|
||||
if line > 0 {
|
||||
line += strings.Count(t.s[:m[2]], "\n")
|
||||
}
|
||||
out = append(out, fmt.Sprintf("%s:%d: `%s %s` is a daemon's line — the operator types `nox …` (novox/hq "+
|
||||
"ADR 0272) — in %q", t.file, line, l.daemon, l.command, excerpt(t.s, m[2], m[3])))
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
+23
-2
@@ -2,7 +2,9 @@
|
||||
// 0244): no word the glossary retired for the tools' descriptions — the copy in retired-words at the
|
||||
// catalogue's root — in any text a module's tools can show. That text is every string literal in a module's
|
||||
// own code that is not a test (a tool's description, the notes and errors it answers with) and every
|
||||
// description in its manifest. Comments are not read: an agent never sees them.
|
||||
// description in its manifest. Comments are not read: an agent never sees them. And no daemon's line
|
||||
// (novox/hq ADR 0272, lines.go): the copy in retired-lines, the lines a person would otherwise be told to
|
||||
// type of the node-engine's or the controller's binary, where the operator's command is `nox`.
|
||||
//
|
||||
// A word is matched whole and in any case, a space in it matching any run of white space, and its plural
|
||||
// (`s` or `es` on its last part) is matched as the word. A vendor word is
|
||||
@@ -97,7 +99,26 @@ func main() {
|
||||
fmt.Printf("words: %d use(s) of a word the glossary retired (novox/hq ADR 0244) — say it in the glossary's word\n", len(findings))
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("words: %d retired words, none in the %d strings of %d files\n", len(words), len(texts), files)
|
||||
// And no daemon's line (novox/hq ADR 0272): what a module tells the operator to type is a `nox` line.
|
||||
lines, err := readLines(filepath.Join(root, "retired-lines"))
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "words:", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
if len(lines) == 0 {
|
||||
fmt.Fprintln(os.Stderr, "words: retired-lines lists no line — the check would pass on anything")
|
||||
os.Exit(2)
|
||||
}
|
||||
if findings := checkLines(lines, texts); len(findings) > 0 {
|
||||
for _, f := range findings {
|
||||
fmt.Println(f)
|
||||
}
|
||||
fmt.Printf("words: %d daemon's line(s) in what a module shows — the operator types one command, nox (novox/hq ADR 0272)\n",
|
||||
len(findings))
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("words: %d retired words and %d daemons' lines, none in the %d strings of %d files\n", len(words), len(lines),
|
||||
len(texts), files)
|
||||
}
|
||||
|
||||
// readList reads retired-words: one word or phrase a line; blank lines and lines starting with # are not words.
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// A retired word's plural is the word; anything else joined on is another word.
|
||||
func TestPatternMatchesTheWordAndItsPlural(t *testing.T) {
|
||||
@@ -24,3 +27,63 @@ func TestPatternMatchesTheWordAndItsPlural(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A daemon's line is found whole — the daemon, its command, and an argument where the command is a line only with
|
||||
// one — and prose that merely names the daemon beside a word is not one (novox/hq ADR 0272).
|
||||
func TestADaemonsLineIsFoundWhole(t *testing.T) {
|
||||
push := retiredLine{daemon: "mesh-controller", command: "push"}
|
||||
module := retiredLine{daemon: "mesh-controller", command: "module", withArgument: true}
|
||||
handOver := retiredLine{daemon: "nox-mesh-host", command: "hand-over"}
|
||||
cases := []struct {
|
||||
line retiredLine
|
||||
text string
|
||||
want bool
|
||||
}{
|
||||
{push, "run `mesh-controller push laptop` after", true},
|
||||
{push, "mesh-controller push", true},
|
||||
{push, "mesh-controller\n push", true},
|
||||
{push, "mesh-controller pushed it", false},
|
||||
{push, "the mesh-controller pushes", false},
|
||||
{push, "mesh-controller-push", false},
|
||||
{module, "`mesh-controller module check modules/*/module.json`", true},
|
||||
{module, "run\n $ mesh-controller module check x", true},
|
||||
{module, "the mesh-controller module is assigned", false},
|
||||
{module, "mesh-controller module", false},
|
||||
{module, "`mesh-controller module`", false},
|
||||
{handOver, "`nox-mesh-host hand-over /srv/x` at the machine", true},
|
||||
{handOver, "`nox node hand-over laptop /srv/x`", false},
|
||||
{retiredLine{daemon: "mesh-host", command: "hand-over"}, "nox-mesh-host hand-over", false},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := linePattern(c.line).MatchString(c.text); got != c.want {
|
||||
t.Errorf("%s %s on %q = %v, want %v", c.line.daemon, c.line.command, c.text, got, c.want)
|
||||
}
|
||||
}
|
||||
found := checkLines([]retiredLine{push, module}, []text{{file: "m/a.go", line: 3, s: "say\n`mesh-controller push`"},
|
||||
{file: "m/b.go", line: 1, s: "the mesh-controller module"}})
|
||||
if len(found) != 1 || found[0] != "m/a.go:4: `mesh-controller push` is a daemon's line — the operator types `nox …` (novox/hq ADR 0272) — in \"say `mesh-controller push`\"" {
|
||||
t.Fatalf("found %q", found)
|
||||
}
|
||||
}
|
||||
|
||||
// The list's lines read as `<daemon> <command>`, a trailing ` …` meaning an argument must follow; anything else is
|
||||
// refused rather than read as some line.
|
||||
func TestRetiredLinesAreReadAsDaemonAndCommand(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := dir + "/retired-lines"
|
||||
if err := os.WriteFile(path, []byte("# the list\nmesh-controller push\nmesh-controller module …\n\nnox-mesh-host hand-over\n"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lines, err := readLines(path)
|
||||
if err != nil || len(lines) != 3 || lines[0] != (retiredLine{daemon: "mesh-controller", command: "push"}) ||
|
||||
lines[1] != (retiredLine{daemon: "mesh-controller", command: "module", withArgument: true}) ||
|
||||
lines[2] != (retiredLine{daemon: "nox-mesh-host", command: "hand-over"}) {
|
||||
t.Fatalf("read %+v, %v", lines, err)
|
||||
}
|
||||
if err := os.WriteFile(path, []byte("mesh-controller\n"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := readLines(path); err == nil {
|
||||
t.Fatal("a line with no command was read")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user