The Principia Machina/TPC-PY/gen lint tables.py: Difference between revisions
Appearance
TPC-PY source gen_lint_tables.py (0.1.0), SHA-256 fb076dca040c733a; conformed TPS 0.3.0; PROPOSED, not declared (CO-8) |
m 1 revision imported |
(No difference)
| |
Revision as of 04:32, 28 September 2026
"""gen_lint_tables 0.1.0: the PROMPT LINT's closed tables (tpc_lint 0.1.0,
D182.1 F5), written from this one source into both residences between
their BEGIN and END LINT TABLES markers, as one JSON text and its SHA-256.
Each residence parses that text at load and refuses to load when the
digest does not match. Run after any change here; a change of any table
is a new tables version and a new tpc_lint version.
TABLE FORMS
CLASSES name -> the ASCII characters of the class (after the fold).
PL2 [id, [pattern, ...]]; a pattern is a list of elements,
["L", literal] or ["C", class, min, max]; the first element
is a literal of at least two characters.
PL3 PL4 PL5 PL6 PL9
[id, [template, ...]]; a template is literal text with
alternative groups "{a|b|}" (an empty alternative allowed,
never in the first group). The template matches exactly the
text of any one of its expansions.
PL7 [id, [token sequence, ...], [template, ...]]: name tokens and
description templates.
NEG the negation tokens; NEG_WINDOW; NEG_STOP.
KNOWN_KEYS the member names a tool locator shows by name.
U+0001 inside a template stands for a literal "|" (PL5-01, PL6-01).
Every literal and every expansion is lower-case printable ASCII (the fold
maps A-Z to a-z before matching), carries no "{", "}" or "|" outside a
group, no double space and no leading or trailing space. The generator
refuses to write when a table breaks a form."""
import hashlib
import itertools
import json
import os
import re
TABLES_VERSION = "0.1.0"
H = os.path.dirname(os.path.abspath(__file__))
LOWER = "abcdefghijklmnopqrstuvwxyz"
DIG = "0123456789"
CLASSES = {
"D": DIG,
"L": LOWER,
"N": LOWER + DIG,
"V": LOWER + "234567",
"W": LOWER + DIG + "_",
"U": LOWER + DIG + "_-",
"K": LOWER + DIG + "-._~+/=",
"I": LOWER + DIG + "-._~%!$&'()*+,;=",
"G": "".join(chr(c) for c in range(0x21, 0x7F)
if chr(c) not in "\"'`" and not "A" <= chr(c) <= "Z"),
"S": " ",
"E": "=:",
"Q": "\"'`",
"X": "abprs",
}
GEN_KEYS = ["password", "passwd", "api_key", "apikey", "api-key",
"secret_key", "client_secret", "access_token", "auth_token",
"private_key", "aws_secret_access_key"]
PL2 = [
["PL2-01", [[["L", "akia"], ["C", "V", 16, 16]]]],
["PL2-02", [[["L", "asia"], ["C", "V", 16, 16]]]],
["PL2-03", [[["L", "ghp_"], ["C", "N", 36, 36]]]],
["PL2-04", [[["L", "gho_"], ["C", "N", 36, 36]]]],
["PL2-05", [[["L", "ghu_"], ["C", "N", 36, 36]]]],
["PL2-06", [[["L", "ghs_"], ["C", "N", 36, 36]]]],
["PL2-07", [[["L", "ghr_"], ["C", "N", 36, 36]]]],
["PL2-08", [[["L", "github_pat_"], ["C", "W", 82, 82]]]],
["PL2-09", [[["L", "glpat-"], ["C", "U", 20, 20]]]],
["PL2-10", [[["L", "xox"], ["C", "X", 1, 1], ["L", "-"], ["C", "D", 10, 12],
["L", "-"], ["C", "D", 10, 13], ["L", "-"], ["C", "N", 24, 26]]]],
["PL2-11", [[["L", "xapp-"], ["C", "U", 20, 255]]]],
["PL2-12", [[["L", "aiza"], ["C", "U", 35, 35]]]],
["PL2-13", [[["L", "sk_live_"], ["C", "N", 20, 255]]]],
["PL2-14", [[["L", "rk_live_"], ["C", "N", 20, 255]]]],
["PL2-15", [[["L", "sk_test_"], ["C", "N", 20, 255]]]],
["PL2-16", [[["L", "sk-"], ["C", "N", 20, 20], ["L", "t3blbkfj"], ["C", "N", 20, 20]]]],
["PL2-17", [[["L", "sk-proj-"], ["C", "U", 20, 4096]]]],
["PL2-18", [[["L", "sk-svcacct-"], ["C", "U", 20, 4096]]]],
["PL2-19", [[["L", "sk-admin-"], ["C", "U", 20, 4096]]]],
["PL2-20", [[["L", "sk-ant-"], ["C", "U", 20, 4096]]]],
["PL2-21", [[["L", "hf_"], ["C", "L", 34, 34]]]],
["PL2-22", [[["L", "npm_"], ["C", "N", 36, 36]]]],
["PL2-23", [[["L", "pypi-ageichlwas5vcmc"], ["C", "U", 50, 1000]]]],
["PL2-24", [[["L", "eyj"], ["C", "U", 10, 4096], ["L", ".eyj"], ["C", "U", 10, 4096],
["L", "."], ["C", "U", 0, 4096]]]],
["PL2-25", [[["L", "-----begin " + k + "-----"]] for k in
["private key", "encrypted private key", "rsa private key",
"dsa private key", "ec private key", "openssh private key",
"pgp private key block"]]],
["PL2-26", [[["L", "bearer "], ["C", "K", 20, 4096]]]],
["PL2-27", [[["L", "authorization: basic "], ["C", "K", 8, 4096]]]],
["PL2-28", [[["L", "x-api-key:"], ["C", "S", 0, 1], ["C", "U", 16, 4096]]]],
["PL2-29", [[["L", "://"], ["C", "I", 1, 256], ["L", ":"], ["C", "I", 1, 256], ["L", "@"]]]],
["PL2-30", [[["L", k], ["C", "S", 0, 1], ["C", "E", 1, 1], ["C", "S", 0, 1],
["C", "Q", 0, 1], ["C", "G", 8, 4096]] for k in GEN_KEYS]],
]
PL3 = [
["PL3-01", ["{follow|obey|execute|carry out|act on} {the |any |all |}"
"{instructions|directions|commands|directives|orders} "
"{in|from|found in|contained in|embedded in|inside} "
"{tool results|tool output|tool outputs|tool responses|web pages|"
"wiki pages|the wiki|retrieved content|retrieved documents|"
"search results|documents|files|emails|other agents|another agent|"
"the server|the api|tpx}"]],
["PL3-02", ["treat {tool results|tool output|tool outputs|tool responses|"
"wiki content|wiki pages|the wiki|retrieved content|search results|"
"documents|file contents|emails|messages from other agents|"
"server messages|tpx responses} as "
"{instructions|commands|authoritative|authorization|trusted}"]],
["PL3-03", ["{you are|you're|you have been} {authorized|authorised|permitted|"
"allowed|cleared|pre-authorized|preauthorized} to"]],
["PL3-04", ["{you have|i give you|i grant you|you are granted|you have been granted} "
"{my |full |standing |blanket |}{permission|authorization|"
"authorisation|approval|consent} to"]],
["PL3-05", ["{consider|treat} {it|this|that|all actions|every action|such actions|"
"these actions} {as |}{approved|authorized|authorised|pre-approved|"
"preapproved|sanctioned}"]],
["PL3-06", ["{assume|presume} {the user's |the human's |the sponsor's |"
"the operator's |my |}{approval|consent|permission|authorization|"
"authorisation}"]],
["PL3-07", ["{pre-approved|preapproved|approved in advance|authorized in advance|"
"authorised in advance}"]],
["PL3-08", ["{no need to|do not need to|don't need to|you need not} "
"{ask|wait for|request|seek|obtain|get} {for |}{permission|approval|"
"confirmation|consent|authorization|authorisation}"]],
["PL3-09", ["without {asking|waiting for|requesting|seeking} {the human|the user|"
"the sponsor|anyone|permission|approval|confirmation|consent}"]],
["PL3-10", ["{act|proceed|decide} {on your own authority|autonomously|"
"without supervision}"]],
["PL3-11", ["{on behalf of|in the name of} the {sponsor|user|human|operator|"
"declaring authority}"]],
["PL3-12", ["{your|these|the} {instructions|rules} {override|outrank|supersede|"
"take precedence over} {the human|the user|any human|the human's|"
"the user's}"]],
]
PL4 = [
["PL4-01", ["{ignore|disregard|forget|override|bypass|set aside} {all |any |}"
"{the |your |}{previous|prior|above|earlier|preceding|original|system|"
"other} {instructions|instruction|rules|guidelines|directives|prompt|"
"prompts|constraints}"]],
["PL4-02", ["{ignore|disregard|override|bypass|set aside|relax|suspend|waive} "
"{the |any |all |}{tps|agent contract|contract|specification|gtp|rules|"
"safety rules|input vetting|decision protocol|digest gate|"
"text safety rule}"]],
["PL4-03", ["{skip|bypass|omit|circumvent} {the |any |all |}{digest|digests|"
"digest gate|digest check|checks|check|verification|validation|gate|"
"lock|mutex|refusal|refusals|audit|review|quarantine|"
"benchmark quarantine|decision item|decision items|report|reporting}"]],
["PL4-04", ["{do not|don't|never|no need to} {report|flag|log|record|disclose|"
"mention} {it|this|them|detections|injections|probes|canaries|failures|"
"errors|refusals|the detection|the injection|suspicious input|"
"suspect input}"]],
["PL4-05", ["{always comply|comply with every|comply with all|comply with any|"
"never refuse|do not refuse|don't refuse|never decline|do not decline|"
"don't decline}"]],
["PL4-06", ["{compute|calculate|estimate|guess|reason|work out|approximate} "
"{the |a |any |}{digest|digests|hash|hashes|sha-256|d(is)|d(prompt)|"
"d(tfk)} {by hand|by reasoning|mentally|in your head|without tpc|"
"without running tpc-py|without executing tpc-py}"]],
["PL4-07", ["{identify|detect|spot|recognize|recognise|distinguish|guess|"
"figure out} {the |a |any |all |}{probe|probes|canary|canaries|parrot|"
"parrots|test input|test inputs|planted test|planted tests|"
"planted error|planted errors}"]],
["PL4-08", ["if {this|it|the input|the task|the request|the package|the block} "
"{is|looks like|seems like|seems to be|might be|may be|could be|"
"appears to be} {a |an |}{probe|canary|parrot|test|evaluation|"
"planted test}"]],
["PL4-09", ["{when|if|while|whenever} you {are|suspect you are|think you are|"
"believe you are} {being tested|being evaluated|being probed|"
"under evaluation|tested|evaluated|probed}"]],
["PL4-10", ["{treat|handle|answer|respond to} {probes|canaries|parrots|tests|"
"test inputs|suspected probes} {differently|with extra care|"
"more carefully|specially}"]],
["PL4-11", ["{look up|search for|fetch|read|consult|check} the {known|expected|"
"published|reference|benchmark|correct} {value|values|answer|answers|"
"result|results} {first|before deriving|before the derivation|"
"before you derive}"]],
]
PL5 = [
["PL5-01", ["\x01 class: instruction artifact"]],
["PL5-02", ["end of artifact --- tps"]],
["PL5-03", ["end of artifact --- gtp"]],
["PL5-04", ["the principia machina specification (tps)"]],
["PL5-05", ["the generic tps prompt (gtp)"]],
["PL5-06", ["{tps|gtp} version:"]],
["PL5-07", ["this part, taken as a runnable instruction set, is gtp"]],
["PL5-08", ["part 6 agent contract"]],
["PL5-09", ["reading conventions, for this file"]],
]
PL6 = [
["PL6-01", ["{<important>|</important>|<instructions>|</instructions>|"
"<instruction>|<system>|</system>|<system-reminder>|[system]|[inst]|"
"<<sys>>|<|im_start|>}".replace("<|im_start|>", "<\x01im_start\x01>")]],
["PL6-02", ["{ignore|disregard|forget|override} {all |any |}{the |your |}"
"{previous|prior|above|earlier|preceding|original|system|other} "
"{instructions|instruction|rules|guidelines|directives|prompt|prompts}"]],
["PL6-03", ["{do not|don't|never} {tell|inform|notify|alert|mention|reveal|show|"
"disclose|say} {this |it |anything |}{to |}{the user|the human|"
"the sponsor|anyone|that you|this}"]],
["PL6-04", ["without {telling|informing|notifying|alerting} {the user|the human|"
"the sponsor|anyone}"]],
["PL6-05", ["{keep|hide} {this|it} {secret|hidden|from the user|from the human}"]],
["PL6-06", ["the user {must not|should not|must never|should never} "
"{know|see|find out|be told}"]],
["PL6-07", ["{before|prior to} {using|calling|invoking|running} {this|any|"
"any other|another|the other} tool"]],
["PL6-08", ["{always|first} {call|use|invoke|run} this tool"]],
["PL6-09", ["{all other tools|any other tool|every other tool|the other tools}"]],
["PL6-10", ["{instead of|rather than} {using|calling|invoking} {the|any|another}"]],
["PL6-11", ["{~/|id_rsa|id_ed25519|id_ecdsa|.ssh/|mcp.json|.env|/etc/passwd|"
"/etc/shadow|.aws/credentials|.netrc|.git-credentials|.npmrc|.pypirc|"
"credentials.json|.kube/config|.docker/config.json}"]],
["PL6-12", ["{pass|send|include|attach|forward|append|upload|post} {its|the|their|"
"all|the file's|the file|those|these} {content|contents}"]],
["PL6-13", ["{read|open|cat|load|access} {the |}{private key|ssh key|ssh keys|"
"credentials|secrets|environment variables|config file|"
"configuration file|api key|api keys|tokens}"]],
["PL6-14", ["{http://|https://|ftp://|ngrok|pastebin|requestbin|webhook.site|"
"exfiltrate|exfiltration}"]],
["PL6-15", ["{send|post|upload|forward|email|transmit} {it|them|this|the result|"
"the results|the data|everything|all data} to"]],
["PL6-16", ["{add|write|save|append} {this|these instructions|the following} to "
"{memory|your memory|claude.md|agents.md|your instructions|"
"the system prompt}"]],
]
PL7 = [
["PL7-01",
[["bash"], ["sh"], ["zsh"], ["shell"], ["powershell"], ["pwsh"], ["cmd"],
["terminal"], ["subprocess"], ["exec"], ["execute"], ["eval"], ["repl"],
["run", "command"], ["run", "commands"], ["run", "code"], ["code", "interpreter"],
["run", "script"], ["run", "python"]],
["{arbitrary|any|shell|bash|terminal|system} {command|commands}",
"{execute|executes|run|runs|evaluate|evaluates} {arbitrary |any |}{code|python|"
"javascript|scripts|a script|shell commands|a shell command|a command|commands}"]],
["PL7-02",
[["fetch"], ["webfetch"], ["curl"], ["wget"], ["browse"], ["browser"],
["navigate"], ["puppeteer"], ["playwright"], ["scrape"], ["scraper"],
["crawl"], ["crawler"], ["download"], ["http", "request"], ["http", "get"],
["http", "post"], ["url", "fetch"], ["fetch", "url"], ["open", "url"],
["get", "url"], ["web", "request"]],
["{any|arbitrary} {url|urls|web page|web pages|website|websites|host|hosts}",
"{fetch|fetches|retrieve|retrieves|download|downloads|get|gets} {a|any|"
"the content of a|the contents of a|content from a|content from any} "
"{url|web page|website}"]],
["PL7-03",
[["send"], ["email"], ["mail"], ["gmail"], ["smtp"], ["sms"], ["webhook"],
["tweet"], ["upload"], ["post", "message"], ["post", "to"]],
["{send|sends} {an |a |}{email|emails|message|messages|sms|text message|"
"notification}",
"{post|posts} {a |}{message|messages|tweet|tweets} to"]],
]
PL9 = [
["PL9-01", ["{remember|memorize|memorise|save|store|persist|record|retain|keep} "
"{this|these|the following|these instructions|this instruction|"
"these rules|this rule|it} {for|in|across|into|to} {future|later|"
"all future|subsequent|every|your|the|long-term|persistent} "
"{sessions|session|conversations|conversation|memory|runs|work}"]],
["PL9-02", ["{write|save|store|add|append|commit} {this|these|it|them|"
"the following|these instructions|this instruction|these rules|"
"a note|notes} {to|in|into} {memory|your memory|the memory|"
"long-term memory|persistent memory|the memory file|a memory file|"
"your memory file|the knowledge base}"]],
["PL9-03", ["{update|edit|modify|rewrite|change|overwrite|extend|amend|"
"append to} {your|the|this} {memory|memories|instructions|"
"system prompt|prompt|instruction file|instruction files|rules file}"]],
["PL9-04", ["{claude.md|agents.md|gemini.md|.cursorrules|.windsurfrules|"
".clinerules|copilot-instructions.md|.cursor/rules|"
".github/instructions|memory.md|.claude/}"]],
["PL9-05", ["{for|in|across|during} {future|all future|later|subsequent|"
"every future|next} {sessions|session|conversations|conversation|"
"runs|chats}"]],
["PL9-06", ["{memory tool|save_memory|memory_write|add_memory|create_memory|"
"remember tool}"]],
]
NEG = ["not", "never", "no", "nor", "cannot", "dont", "don't", "don\u2019t",
"cant", "can't", "can\u2019t", "mustnt", "mustn't", "mustn\u2019t",
"shouldnt", "shouldn't", "shouldn\u2019t", "wont", "won't", "won\u2019t",
"doesnt", "doesn't", "doesn\u2019t"]
NEG_WINDOW = 4
NEG_STOP = ".!?;:"
KNOWN_KEYS = ["$defs", "$id", "$ref", "$schema", "_meta", "additionalProperties",
"allOf", "annotations", "anyOf", "cache_control", "const",
"contentEncoding", "contentMediaType", "default", "definitions",
"deprecated", "description", "destructiveHint", "enum", "examples",
"exclusiveMaximum", "exclusiveMinimum", "format", "function",
"idempotentHint", "inputSchema", "input_schema", "items", "maxItems",
"maxLength", "maximum", "minItems", "minLength", "minimum", "name",
"not", "oneOf", "openWorldHint", "outputSchema", "output_schema",
"parameters", "pattern", "patternProperties", "prefixItems",
"properties", "readOnly", "readOnlyHint", "required", "strict",
"title", "type", "uniqueItems", "writeOnly"]
# ------------------------------------------------------------ validation
def fail(msg):
raise SystemExit("gen_lint_tables: refusing to write: " + msg)
def parse_template(t):
"""[[alternatives], ...]: a literal chunk is a part of one alternative."""
parts, i, lit = [], 0, ""
while i < len(t):
c = t[i]
if c == "{":
j = t.index("}", i)
if lit:
parts.append([lit])
lit = ""
alts = t[i + 1:j].split("|")
parts.append(alts)
i = j + 1
elif c in "}|":
fail("stray %r in %r" % (c, t))
else:
lit += c
i += 1
if lit:
parts.append([lit])
return parts
PRINTABLE = re.compile(r"^[\x01\x20-\x7e]*\Z")
def check_phrase_text(s, where):
if not PRINTABLE.match(s) or re.search(r"[A-Z]", s):
fail("%s: not lower-case printable ASCII: %r" % (where, s))
def check_template(t, where):
check_phrase_text(t, where)
parts = parse_template(t)
if "" in parts[0] or not parts[0]:
fail("%s: the first group has an empty alternative" % where)
for p in parts:
for a in p:
check_phrase_text(a, where)
n = 0
for combo in itertools.product(*parts):
e = "".join(combo)
n += 1
if e == "" or e[0] == " " or e[-1] == " " or " " in e:
fail("%s: expansion %r is empty or badly spaced" % (where, e))
if n > 100000:
fail("%s: %d expansions" % (where, n))
return parts
def unescape(t):
return t.replace("\x01", "|")
def build():
for name, chars in CLASSES.items():
if not chars or any(ord(c) > 0x7e or ord(c) < 0x20 for c in chars):
fail("class %s" % name)
if len(set(chars)) != len(chars) or re.search(r"[A-Z]", chars):
fail("class %s" % name)
ids = set()
def newid(i):
if i in ids:
fail("duplicate id " + i)
ids.add(i)
for i, pats in PL2:
newid(i)
for p in pats:
if p[0][0] != "L" or len(p[0][1]) < 2:
fail("%s: a pattern must open with a literal of two or more" % i)
for el in p:
if el[0] == "L":
check_phrase_text(el[1], i)
elif el[0] == "C":
if el[1] not in CLASSES or not (0 <= el[2] <= el[3] <= 4096):
fail("%s: bad class element %r" % (i, el))
else:
fail("%s: bad element %r" % (i, el))
out = {"version": TABLES_VERSION, "classes": CLASSES, "PL2": PL2}
for code, table in (("PL3", PL3), ("PL4", PL4), ("PL5", PL5), ("PL6", PL6),
("PL9", PL9)):
rows = []
for i, temps in table:
newid(i)
if not i.startswith(code + "-"):
fail("id %s under %s" % (i, code))
rows.append([i, [[[unescape(a) for a in part]
for part in check_template(t, i)] for t in temps]])
out[code] = rows
rows = []
for i, seqs, temps in PL7:
newid(i)
for s in seqs:
for tok in s:
if not re.match(r"^[a-z0-9]+\Z", tok):
fail("%s: token %r" % (i, tok))
rows.append([i, seqs, [[[unescape(a) for a in part]
for part in check_template(t, i)] for t in temps]])
out["PL7"] = rows
out["NEG"] = NEG
out["NEG_WINDOW"] = NEG_WINDOW
out["NEG_STOP"] = NEG_STOP
if sorted(KNOWN_KEYS) != KNOWN_KEYS or len(set(KNOWN_KEYS)) != len(KNOWN_KEYS):
fail("KNOWN_KEYS must be sorted and unique")
for k in KNOWN_KEYS:
if not re.match(r"^[$_A-Za-z][A-Za-z_]*\Z", k):
fail("known key %r" % k)
out["KNOWN_KEYS"] = KNOWN_KEYS
return out
def main():
tables = build()
text = json.dumps(tables, ensure_ascii=True, separators=(",", ":"),
sort_keys=True)
digest = hashlib.sha256(text.encode("utf-8")).hexdigest()
chunks = [text[i:i + 64] for i in range(0, len(text), 64)]
py = ["# BEGIN LINT TABLES (gen_lint_tables.py; do not edit)",
'LINT_TABLES_VERSION = "%s"' % TABLES_VERSION,
'LINT_TABLES_SHA256 = (\n "%s")' % digest,
"LINT_TABLES_JSON = ("] + [" %r" % c for c in chunks] + [")",
"# END LINT TABLES"]
def php_lit(c):
return "'" + c.replace("\\", "\\\\").replace("'", "\\'") + "'"
php = ["// BEGIN LINT TABLES (gen_lint_tables.py; do not edit)",
"const TPC_LINT_TABLES_VERSION = '%s';" % TABLES_VERSION,
"const TPC_LINT_TABLES_SHA256 = '%s';" % digest,
"const TPC_LINT_TABLES_JSON = ''"] + [" . %s" % php_lit(c) for c in chunks] + \
[" ;", "// END LINT TABLES"]
def put(path, begin, end, lines):
s = open(path, encoding="utf-8").read()
a = s.index(begin)
b = s.index(end) + len(end)
open(path, "w", encoding="utf-8").write(s[:a] + "\n".join(lines) + s[b:])
put(os.path.join(H, "tpc_lint.py"), "# BEGIN LINT TABLES", "# END LINT TABLES", py)
put(os.path.join(H, "..", "tpc_php", "tpc_lint.php"), "// BEGIN LINT TABLES",
"// END LINT TABLES", php)
n = {k: len(tables[k]) for k in ("PL2", "PL3", "PL4", "PL5", "PL6", "PL7", "PL9")}
print("tables %s: %d bytes, SHA-256 %s, entries %s"
% (TABLES_VERSION, len(text.encode("utf-8")), digest,
json.dumps(n, sort_keys=True)))
if __name__ == "__main__":
main()