Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This directory contains repo-local copies of canonical skills from
`The-Interdependency/skill-lib`.

Source commit: `a1c6a7124af537ee9937b6fc6084940091982fe5`
Source commit: `c14ee9d500579a4b5d6821f62c9d82ca96e73608`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update every canonical skill-lib pin together

In the inspected .github/workflows/skill-compliance.yml, both the canonical checkout and strict drift checker remain pinned to a1c6a7124af537ee9937b6fc6084940091982fe5; changing the vendored bytes and this declaration to c14ee9d... therefore guarantees the byte-for-byte drift job fails. Update the workflow and repository authority references to the new identity, or retain the old snapshot.

AGENTS.md reference: AGENTS.md:L35-L41

Useful? React with 👍 / 👎.


Repo-local copies are not the source of truth. Edit `skill-lib` first,
then propagate from the canonical source.
Expand Down
325 changes: 65 additions & 260 deletions .agents/skills/gonol-build/SKILL.md

Large diffs are not rendered by default.

31 changes: 24 additions & 7 deletions .agents/skills/msdmd/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,16 @@ claims to prove those obligations. See
- **Fence**: `=== <BLOCK_NAME> ===` opens, `=== END <BLOCK_NAME> ===`
closes. Block name is uppercase snake_case (e.g. `CONTRACTS`,
`CHECKS`, `DOCS`, `CAPABILITIES`, `OWNERS`).
- **Comment marker**: whatever is idiomatic for the file's language.
`#` for Python / Ruby / Elixir / shell. `//` for TS / JS / Rust / Go /
Java / C / C++ / Swift. `--` for SQL / Lua / Haskell. The marker
appears at the start of every line inside the block.
- **Comment marker**: whatever is idiomatic for the file's language. The
reference parsers auto-detect these line-comment families by extension:
`#` for Python, Ruby, Elixir, shell, Perl, R, Julia, PowerShell, Tcl, and
Raku; `//` for TypeScript/JavaScript, Rust, Go, Java, C, C++ (including
`.c+`, `.c++`, `.cxx`, and header variants), Swift, Kotlin, C#,
Objective-C++, Scala, Dart, Zig, Groovy, and PHP; `--` for SQL, Lua,
Haskell, Ada, VHDL, and Lean; `%` for Erlang and Prolog; `;` for
Clojure/Lisp/Scheme/Racket; `!` for Fortran; `'` for Visual Basic; and
`*>` for COBOL. The marker appears at the start of every line in the block.
`COMMENT_MARKERS` in both universal parsers is the exact extension registry.
- **Entry boundary**: every entry begins with `id:`. The id must be
unique within its block and stable across refactors (so it can be
referenced from external tooling).
Expand Down Expand Up @@ -138,6 +144,17 @@ A reference implementation in pure stdlib Python lives at
Both commit to zero non-stdlib dependencies so you can copy them into
any project.

Extension detection refuses ambiguous suffixes rather than sniffing content.
For example, `.m` can mean Objective-C or MATLAB/Octave and therefore has no
automatic marker. A caller that already knows the language may still call
`parse_text` / `parseText` with an explicit marker. Languages that cannot carry
the msdmd shape as repeated line comments need a future versioned syntax
extension; they are not approximated with an invalid fence.

The paired RATIOS helper preserves the interpreter boundary: a non-empty
line-1 shebang may precede opening RATIOS, which must then occupy line 2 with no
gap. See [`ratios/SKILL.md`](../ratios/SKILL.md) for the complete seal contract.

## Repo collection point and visualizer

Every consuming repo SHOULD maintain one repo-level collection point named
Expand Down Expand Up @@ -219,9 +236,9 @@ Implementation rules every runner MUST follow:
1. **Walk the source tree** under a configurable root, skipping
conventional non-source paths (`__pycache__`, `node_modules`,
`.git`, build outputs, the runner's own test directory).
2. **Detect comment marker by extension**, not by content sniffing.
`.py / .rb / .ex / .sh → #`. `.ts / .js / .tsx / .jsx / .rs / .go /
.java / .c / .cpp / .swift → //`. `.sql / .lua / .hs → --`.
2. **Detect comment marker by extension**, not by content sniffing. Consume the
parser's `COMMENT_MARKERS` registry rather than maintaining a runner-local
language list. Python and TypeScript registries must remain identical.
3. **Parse all matching blocks** in each file. Multiple blocks of the
same type concatenate; entries from different blocks are
distinguishable only by id, not by source block.
Expand Down
4 changes: 2 additions & 2 deletions .agents/skills/msdmd/collection.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ratios: loc_comments=67:0 imports_exports=0:0 calls_definitions=1:0
// ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm
/**
* Shared TypeScript shapes for repo-level msdmd collection points.
*
Expand Down Expand Up @@ -72,4 +72,4 @@ export interface MsdmdCollection {
export function defineMsdmdCollection(collection: MsdmdCollection): MsdmdCollection {
return collection;
}
// ratios: loc_comments=67:0 imports_exports=0:0 calls_definitions=1:0
// ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm
84 changes: 63 additions & 21 deletions .agents/skills/msdmd/parsers/universal.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ratios: loc_comments=128:49 imports_exports=4:7 calls_definitions=51:10
# ratios: loc_comments=161:57 imports_exports=4:7 calls_definitions=55:10
"""Universal msdmd parser — pure stdlib.

Implements the parser contract from ``msdmd/SKILL.md``: extracts every
Expand All @@ -7,6 +7,8 @@

Comment marker is auto-detected by file extension. The block syntax
itself is identical across languages; only the per-line marker changes.
``COMMENT_MARKERS`` is public so runners can distinguish parser support
from their narrower language-specific execution or metric coverage.

Public API:

Expand All @@ -15,12 +17,13 @@
walk_tree(root, block_name, *, skip=None, extensions=None) -> tuple[annotated, untested]

RATIOS is the one msdmd declaration that is *not* a fenced block — it is a
single comment line carried on a file's first and last non-blank lines. The
reader for it lives here too, as a sanctioned extension rather than a fork:
single comment line carried on a file's opening and closing source boundaries.
A valid interpreter shebang owns literal line 1, so the opening RATIOS line is
literal line 2 in that case. The reader lives here as a sanctioned extension:

parse_ratios(text, marker="#") -> list[dict]
parse_ratios_file(path) -> list[dict]
ratios_placement(text, marker="#") -> tuple[first_ok, last_ok]
ratios_placement(text, marker="#") -> tuple[opening_ok, closing_ok]

This module has zero non-stdlib dependencies and is safe to copy
verbatim into any project that wants msdmd support.
Expand All @@ -30,13 +33,39 @@
from pathlib import Path
from typing import Iterable

# extension → comment marker
_MARKERS: dict[str, str] = {
".py": "#", ".rb": "#", ".ex": "#", ".exs": "#", ".sh": "#",
".ts": "//", ".tsx": "//", ".js": "//", ".jsx": "//", ".mjs": "//",
".rs": "//", ".go": "//", ".java": "//", ".c": "//", ".cpp": "//",
".cc": "//", ".h": "//", ".hpp": "//", ".swift": "//", ".kt": "//",
# extension → line-comment marker. Keep this registry entry-for-entry equivalent
# to universal.ts; tests fail if either parser gains or loses an extension alone.
COMMENT_MARKERS: dict[str, str] = {
".py": "#", ".pyw": "#", ".pyi": "#",
".rb": "#", ".rake": "#", ".gemspec": "#",
".ex": "#", ".exs": "#",
".sh": "#", ".bash": "#", ".zsh": "#", ".fish": "#",
".pl": "#", ".pm": "#", ".t": "#",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refuse the ambiguous .pl extension

The new registry assigns every .pl file to Perl's # marker, but .pl is also a conventional Prolog extension and Prolog metadata uses %, which this registry recognizes only for .prolog. Consequently, parse_file silently misses valid % === ... blocks in ordinary Prolog .pl sources and walk_tree reports them as unannotated, contrary to the newly documented rule that ambiguous suffixes are refused rather than guessed; remove .pl auto-detection or require an explicit language choice, and mirror the fix in the TypeScript registry.

Useful? React with 👍 / 👎.

".r": "#", ".jl": "#",
".ps1": "#", ".psm1": "#", ".tcl": "#",
".raku": "#", ".rakumod": "#",
".ts": "//", ".tsx": "//", ".mts": "//", ".cts": "//",
".js": "//", ".jsx": "//", ".mjs": "//", ".cjs": "//",
".rs": "//", ".go": "//", ".java": "//",
".c": "//", ".cc": "//", ".cp": "//", ".cpp": "//",
".cxx": "//", ".c+": "//", ".c++": "//",
".h": "//", ".hh": "//", ".hp": "//", ".hpp": "//",
".hxx": "//", ".h+": "//", ".h++": "//",
".tcc": "//", ".ipp": "//", ".inl": "//",
".swift": "//", ".kt": "//", ".kts": "//", ".cs": "//",
".mm": "//", ".scala": "//", ".dart": "//", ".zig": "//",
".groovy": "//", ".gradle": "//", ".php": "//",
".sql": "--", ".lua": "--", ".hs": "--",
".adb": "--", ".ads": "--", ".vhd": "--", ".vhdl": "--",
".lean": "--",
".erl": "%", ".hrl": "%", ".prolog": "%",
".clj": ";", ".cljs": ";", ".cljc": ";", ".bb": ";",
".lisp": ";", ".lsp": ";", ".cl": ";",
".scm": ";", ".ss": ";", ".rkt": ";",
".f": "!", ".for": "!", ".f90": "!", ".f95": "!",
".f03": "!", ".f08": "!",
".vb": "'", ".vbs": "'",
".cob": "*>", ".cbl": "*>",
}

_DEFAULT_SKIP = (
Expand All @@ -48,7 +77,7 @@

def marker_for(path: Path) -> str | None:
"""Return the comment marker for a file path, or None if unsupported."""
return _MARKERS.get(path.suffix.lower())
return COMMENT_MARKERS.get(path.suffix.lower())


def _block_regex(block_name: str, marker: str) -> re.Pattern[str]:
Expand Down Expand Up @@ -124,7 +153,7 @@ def walk_tree(
ext_set = (
set(e.lower() if e.startswith(".") else "." + e.lower() for e in extensions)
if extensions is not None
else set(_MARKERS.keys())
else set(COMMENT_MARKERS.keys())
)

def iter_source_files(path: Path) -> Iterable[Path]:
Expand Down Expand Up @@ -155,8 +184,9 @@ def iter_source_files(path: Path) -> Iterable[Path]:

# --- RATIOS single-line declaration (msdmd extension) --------------------
# Unlike every other declaration, RATIOS is not fenced. It is a single
# comment line carrying the three canonical ratios, placed on the file's
# first and last non-blank lines:
# comment line carrying the three canonical ratios at the opening source
# boundary and last non-blank line. A valid line-1 shebang moves the opening
# boundary to literal line 2:
# <marker> ratios: loc_comments=N:M imports_exports=N:M calls_definitions=N:M
RATIO_IDS = ("loc_comments", "imports_exports", "calls_definitions")
_RATIOS_TOKEN_RE = re.compile(r"(?P<key>[a-z_]+)=(?P<val>\S+)")
Expand All @@ -171,9 +201,9 @@ def parse_ratios(text: str, marker: str = "#") -> list[dict]:

RATIOS is not a fenced block: it is one comment line of the form
``<marker> ratios: loc_comments=N:M imports_exports=N:M calls_definitions=N:M``
placed on the file's first and last non-blank lines. Returns one flat
``{"id", "value"}`` dict per (declaration line x ratio token) so a drift
gate can verify every occurrence.
placed at the file's opening and closing source boundaries. Returns one
flat ``{"id", "value"}`` dict per (declaration line x ratio token) so a
drift gate can verify every occurrence.
"""
line_re = _ratios_line_re(marker)
out: list[dict] = []
Expand All @@ -198,17 +228,29 @@ def parse_ratios_file(path: Path) -> list[dict]:


def ratios_placement(text: str, marker: str = "#") -> tuple[bool, bool]:
"""Return ``(first_line_has_ratios, last_non_blank_line_has_ratios)``."""
"""Return ``(opening_ratios_ok, closing_ratios_ok)``.

A non-empty ``#!`` interpreter directive may occupy literal line 1. It is
the only accepted preamble and RATIOS must immediately follow it.
"""
line_re = _ratios_line_re(marker)
lines = text.splitlines()
if not lines:
return (False, False)
first_ok = bool(line_re.match(lines[0].rstrip()))
has_shebang = lines[0].startswith("#!") and bool(lines[0][2:].strip())
opening_index = 1 if has_shebang else 0
opening_ok = (
len(lines) > opening_index
and bool(line_re.match(lines[opening_index].rstrip()))
)
if opening_index == 0 and len(lines) > 1:
displaced = lines[1].startswith("#!") and bool(lines[1][2:].strip())
opening_ok = opening_ok and not displaced
last_ok = False
for raw in reversed(lines):
if raw.strip() == "":
continue
last_ok = bool(line_re.match(raw.rstrip()))
break
return (first_ok, last_ok)
# ratios: loc_comments=128:49 imports_exports=4:7 calls_definitions=51:10
return (opening_ok, last_ok)
# ratios: loc_comments=161:57 imports_exports=4:7 calls_definitions=55:10
72 changes: 55 additions & 17 deletions .agents/skills/msdmd/parsers/universal.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ratios: loc_comments=176:0 imports_exports=2:0 calls_definitions=53:0
// ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm
/**
* Universal msdmd parser — pure Node stdlib (fs, path).
*
Expand All @@ -9,12 +9,13 @@
*
* Comment marker auto-detected by file extension. The block syntax
* itself is identical across languages; only the per-line marker
* changes.
* changes. COMMENT_MARKERS is public so runners can keep their narrower
* language-specific execution or metric coverage separate.
*
* RATIOS is the one msdmd declaration that is not a fenced block — it is a
* single comment line on a file's first and last non-blank lines. Its reader
* (parseRatios / parseRatiosFile / ratiosPlacement) lives here too, as a
* sanctioned extension rather than a fork.
* single comment line on a file's opening and closing source boundaries. A
* valid interpreter shebang owns literal line 1, moving opening RATIOS to
* literal line 2. Its reader lives here as a sanctioned extension.
*
* Zero non-stdlib dependencies. Safe to copy verbatim into any
* Node/Deno/Bun project that wants msdmd support.
Expand All @@ -24,12 +25,39 @@ import { join, extname } from "node:path";

export type Entry = Record<string, string>;

const MARKERS: Record<string, string> = {
".py": "#", ".rb": "#", ".ex": "#", ".exs": "#", ".sh": "#",
".ts": "//", ".tsx": "//", ".js": "//", ".jsx": "//", ".mjs": "//",
".rs": "//", ".go": "//", ".java": "//", ".c": "//", ".cpp": "//",
".cc": "//", ".h": "//", ".hpp": "//", ".swift": "//", ".kt": "//",
// Keep this registry entry-for-entry equivalent to universal.py; tests fail if
// either parser gains or loses an extension alone.
export const COMMENT_MARKERS: Record<string, string> = {
".py": "#", ".pyw": "#", ".pyi": "#",
".rb": "#", ".rake": "#", ".gemspec": "#",
".ex": "#", ".exs": "#",
".sh": "#", ".bash": "#", ".zsh": "#", ".fish": "#",
".pl": "#", ".pm": "#", ".t": "#",
".r": "#", ".jl": "#",
".ps1": "#", ".psm1": "#", ".tcl": "#",
".raku": "#", ".rakumod": "#",
".ts": "//", ".tsx": "//", ".mts": "//", ".cts": "//",
".js": "//", ".jsx": "//", ".mjs": "//", ".cjs": "//",
".rs": "//", ".go": "//", ".java": "//",
".c": "//", ".cc": "//", ".cp": "//", ".cpp": "//",
".cxx": "//", ".c+": "//", ".c++": "//",
".h": "//", ".hh": "//", ".hp": "//", ".hpp": "//",
".hxx": "//", ".h+": "//", ".h++": "//",
".tcc": "//", ".ipp": "//", ".inl": "//",
".swift": "//", ".kt": "//", ".kts": "//", ".cs": "//",
".mm": "//", ".scala": "//", ".dart": "//", ".zig": "//",
".groovy": "//", ".gradle": "//", ".php": "//",
".sql": "--", ".lua": "--", ".hs": "--",
".adb": "--", ".ads": "--", ".vhd": "--", ".vhdl": "--",
".lean": "--",
".erl": "%", ".hrl": "%", ".prolog": "%",
".clj": ";", ".cljs": ";", ".cljc": ";", ".bb": ";",
".lisp": ";", ".lsp": ";", ".cl": ";",
".scm": ";", ".ss": ";", ".rkt": ";",
".f": "!", ".for": "!", ".f90": "!", ".f95": "!",
".f03": "!", ".f08": "!",
".vb": "'", ".vbs": "'",
".cob": "*>", ".cbl": "*>",
};

const DEFAULT_SKIP = new Set([
Expand All @@ -43,7 +71,7 @@ function escapeRegex(s: string): string {
}

export function markerFor(path: string): string | null {
return MARKERS[extname(path).toLowerCase()] ?? null;
return COMMENT_MARKERS[extname(path).toLowerCase()] ?? null;
}

export function parseText(
Expand Down Expand Up @@ -104,7 +132,7 @@ export function walkTree(
): { annotated: Array<[string, Entry[]]>; untested: string[] } {
const skip = opts.skip ?? DEFAULT_SKIP;
const extensions =
opts.extensions ?? new Set(Object.keys(MARKERS));
opts.extensions ?? new Set(Object.keys(COMMENT_MARKERS));

const annotated: Array<[string, Entry[]]> = [];
const untested: string[] = [];
Expand Down Expand Up @@ -145,8 +173,9 @@ export function walkTree(

// --- RATIOS single-line declaration (msdmd extension) --------------------
// Unlike every other declaration, RATIOS is not fenced. It is a single
// comment line carrying the three canonical ratios, placed on the file's
// first and last non-blank lines:
// comment line carrying the three canonical ratios at the opening source
// boundary and last non-blank line. A valid line-1 shebang moves the opening
// boundary to literal line 2:
// <marker> ratios: loc_comments=N:M imports_exports=N:M calls_definitions=N:M
export const RATIO_IDS = ["loc_comments", "imports_exports", "calls_definitions"] as const;

Expand Down Expand Up @@ -184,13 +213,22 @@ export function ratiosPlacement(text: string, marker: string = "#"): [boolean, b
const lineRe = ratiosLineRe(marker);
const lines = text.split("\n");
if (lines.length === 0) return [false, false];
const firstOk = lineRe.test(lines[0].replace(/\s+$/, ""));
const hasShebang = lines[0].startsWith("#!") && lines[0].slice(2).trim().length > 0;
const openingIndex = hasShebang ? 1 : 0;
const openingOk =
lines.length > openingIndex &&
lineRe.test(lines[openingIndex].replace(/\s+$/, ""));
const displacedShebang =
openingIndex === 0 &&
lines.length > 1 &&
lines[1].startsWith("#!") &&
lines[1].slice(2).trim().length > 0;
let lastOk = false;
for (let i = lines.length - 1; i >= 0; i--) {
if (lines[i].trim() === "") continue;
lastOk = lineRe.test(lines[i].replace(/\s+$/, ""));
break;
}
return [firstOk, lastOk];
return [openingOk && !displacedShebang, lastOk];
}
// ratios: loc_comments=176:0 imports_exports=2:0 calls_definitions=53:0
// ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm
Loading