Compare commits
3 Commits
79c9089122
...
v2.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 9385c77ac7 | |||
| 54d7bd80ba | |||
| 75a13c82f6 |
@@ -129,6 +129,24 @@ clause**, and a **boundary clause**. Capability enumeration, output-format detai
|
|||||||
dependency, and none needs to. Verified: a tree holding only `plugins/` and the root `apm.yml`,
|
dependency, and none needs to. Verified: a tree holding only `plugins/` and the root `apm.yml`,
|
||||||
with no `.claude/` or `.agents/` anywhere, now produces findings identical to the working tree —
|
with no `.claude/` or `.agents/` anywhere, now produces findings identical to the working tree —
|
||||||
26 description FAILs, 9 body FAILs, 2 dangling targets, 0 missing references, 58 SUGGESTIONs.
|
26 description FAILs, 9 body FAILs, 2 dangling targets, 0 missing references, 58 SUGGESTIONs.
|
||||||
|
- **The universe is the apm marketplace, and nothing else.** A routing target resolves to a skill or
|
||||||
|
an agent, or it does not resolve. Host built-ins are deliberately outside it: `/compact`, `/clear`
|
||||||
|
and `/init` are Claude Code slash commands with no counterpart in Copilot CLI or Codex, so a
|
||||||
|
vendor-neutral `.apm/` description routing to one is a portability defect and the hard FAIL is a
|
||||||
|
true positive, not a false one. An allowlist of known built-ins was **rejected**: it answers a
|
||||||
|
different question ("does this exist on *some* host?"), it cannot answer that portably from a
|
||||||
|
single source file, and it goes stale the next time a host ships a command — reintroducing the
|
||||||
|
same-commit-two-verdicts failure the bullet above exists to close. An author who needs to mention
|
||||||
|
one writes it un-slashed (``the `compact` built-in``), which is not route notation and makes no
|
||||||
|
routing claim.
|
||||||
|
- **Blocking is scoped to a sentence, which makes sentence boundaries load-bearing.** A prose-form
|
||||||
|
target earns a hard error only when its own sentence names another target that *resolves*; route
|
||||||
|
notation (`/name`, `→ name`) is exempt and always blocks. So the splitter is part of the contract,
|
||||||
|
not a detail of it. `e.g. "…"` is not a sentence end, and a sentence opening with a code span or a
|
||||||
|
lowercase skill name is a start; getting either wrong moves targets between the two tiers in
|
||||||
|
opposite directions — a stranded corroborator silently demotes a real finding to SUGGESTION, and a
|
||||||
|
missed boundary lets one sentence vouch for a target it never stood beside, producing a hard FAIL
|
||||||
|
with no escape hatch.
|
||||||
- **The blanket pushiness rules are deleted.** `skill-author/SKILL.md:104` and
|
- **The blanket pushiness rules are deleted.** `skill-author/SKILL.md:104` and
|
||||||
`description-quality.md:21` are replaced by a conditional: add an indirect trigger only where the
|
`description-quality.md:21` are replaced by a conditional: add an indirect trigger only where the
|
||||||
user's natural phrasing genuinely omits the domain word — true for the `gitea-*` family, false for
|
user's natural phrasing genuinely omits the domain word — true for the `gitea-*` family, false for
|
||||||
|
|||||||
@@ -554,7 +554,28 @@ BACKTICK = re.compile(r"`(%s)`" % NAME_HYPH, re.I)
|
|||||||
# ADR-0020's compressed arrow form `Not <thing> -> <name>`.
|
# ADR-0020's compressed arrow form `Not <thing> -> <name>`.
|
||||||
BOUNDARY_MARKER = re.compile(r"\b(?:do\s+not|instead|rather\s+than|not\s+for)\b", re.I)
|
BOUNDARY_MARKER = re.compile(r"\b(?:do\s+not|instead|rather\s+than|not\s+for)\b", re.I)
|
||||||
BOUNDARY_ARROW = re.compile(r"\bnot\b[^.;]*?(?:->|→)", re.I)
|
BOUNDARY_ARROW = re.compile(r"\bnot\b[^.;]*?(?:->|→)", re.I)
|
||||||
SENTENCE_SPLIT = re.compile(u'(?<=[.!?])\\s+(?=[A-Z"“(])')
|
# Sentence boundaries decide the CORROBORATION scope above, so getting one wrong
|
||||||
|
# is not cosmetic — it moves a target between SUGGESTION and blocking ERROR. Two
|
||||||
|
# shapes common in these descriptions defeat the naive "period, space, capital"
|
||||||
|
# rule, in OPPOSITE directions:
|
||||||
|
# OVER-SPLIT. `e.g. "set up the manifest"` ends no sentence, but the quote
|
||||||
|
# looks like one starting. The clause is cut in half, the corroborating
|
||||||
|
# target lands on the far side of the cut, and a genuinely dangling target
|
||||||
|
# silently demotes to SUGGESTION — the gate takes a measurement and then
|
||||||
|
# throws it away, which is the vacuous-green shape this file exists to stop.
|
||||||
|
# UNDER-SPLIT. A real sentence opening with a code span or a lowercase skill
|
||||||
|
# name ("... Composes it. `gitea-prs` also uses it.") is not seen as a start
|
||||||
|
# at all, so two sentences merge and a resolving target vouches for an
|
||||||
|
# unresolvable one it never stood beside — a hard FAIL with no escape hatch,
|
||||||
|
# which is exactly the failure the corroboration rule was added to prevent.
|
||||||
|
# Both are closed here: the five abbreviations that actually occur in routing
|
||||||
|
# prose are excluded as sentence ends, and the opener class admits a backtick or
|
||||||
|
# a lowercase letter. Verified zero-delta on the current corpus (37 ERROR / 58
|
||||||
|
# SUGGESTION / 2 dangling before and after) — this protects the descriptions
|
||||||
|
# issue #99 is about to rewrite, not the ones already measured.
|
||||||
|
SENTENCE_SPLIT = re.compile(
|
||||||
|
u'(?<!\\be\\.g\\.)(?<!\\bi\\.e\\.)(?<!\\betc\\.)(?<!\\bvs\\.)(?<!\\bcf\\.)'
|
||||||
|
u'(?<=[.!?])\\s+(?=[A-Za-z`"“(])')
|
||||||
|
|
||||||
# The token that may follow a route target without turning it into a compound
|
# The token that may follow a route target without turning it into a compound
|
||||||
# modifier: punctuation, end of sentence, a conjunction, a boundary word, or a
|
# modifier: punctuation, end of sentence, a conjunction, a boundary word, or a
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ that package declares in `apm.yml` under `dependencies.apm`. A sibling plugin in
|
|||||||
therefore resolves; a skill in an unrelated repo does not. A target outside that universe sends the
|
therefore resolves; a skill in an unrelated repo does not. A target outside that universe sends the
|
||||||
router nowhere. Verify it before writing it — do not invent a plausible sibling.
|
router nowhere. Verify it before writing it — do not invent a plausible sibling.
|
||||||
|
|
||||||
|
That universe is the apm marketplace and stops there. A **host built-in is not a routing target**:
|
||||||
|
`/compact`, `/clear` and `/init` are Claude Code slash commands with no counterpart in Copilot CLI
|
||||||
|
or Codex, and `.apm/` source compiles for all three, so routing to one is a portability defect. The
|
||||||
|
gate is right to fail it and there is no allowlist. If a built-in genuinely needs mentioning, write
|
||||||
|
it un-slashed — ``the `compact` built-in`` — which makes no routing claim and is not checked.
|
||||||
|
|
||||||
**Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only
|
**Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only
|
||||||
with YAML folding resolved. Treat 250 as the target: the SUGGESTION tier is what moves the corpus
|
with YAML folding resolved. Treat 250 as the target: the SUGGESTION tier is what moves the corpus
|
||||||
average, the FAIL tier only stops outliers.
|
average, the FAIL tier only stops outliers.
|
||||||
|
|||||||
@@ -480,7 +480,28 @@ BACKTICK = re.compile(r"`(%s)`" % NAME_HYPH, re.I)
|
|||||||
# ADR-0020's compressed arrow form `Not <thing> -> <name>`.
|
# ADR-0020's compressed arrow form `Not <thing> -> <name>`.
|
||||||
BOUNDARY_MARKER = re.compile(r"\b(?:do\s+not|instead|rather\s+than|not\s+for)\b", re.I)
|
BOUNDARY_MARKER = re.compile(r"\b(?:do\s+not|instead|rather\s+than|not\s+for)\b", re.I)
|
||||||
BOUNDARY_ARROW = re.compile(r"\bnot\b[^.;]*?(?:->|→)", re.I)
|
BOUNDARY_ARROW = re.compile(r"\bnot\b[^.;]*?(?:->|→)", re.I)
|
||||||
SENTENCE_SPLIT = re.compile(u'(?<=[.!?])\\s+(?=[A-Z"“(])')
|
# Sentence boundaries decide the CORROBORATION scope above, so getting one wrong
|
||||||
|
# is not cosmetic — it moves a target between SUGGESTION and blocking ERROR. Two
|
||||||
|
# shapes common in these descriptions defeat the naive "period, space, capital"
|
||||||
|
# rule, in OPPOSITE directions:
|
||||||
|
# OVER-SPLIT. `e.g. "set up the manifest"` ends no sentence, but the quote
|
||||||
|
# looks like one starting. The clause is cut in half, the corroborating
|
||||||
|
# target lands on the far side of the cut, and a genuinely dangling target
|
||||||
|
# silently demotes to SUGGESTION — the gate takes a measurement and then
|
||||||
|
# throws it away, which is the vacuous-green shape this file exists to stop.
|
||||||
|
# UNDER-SPLIT. A real sentence opening with a code span or a lowercase skill
|
||||||
|
# name ("... Composes it. `gitea-prs` also uses it.") is not seen as a start
|
||||||
|
# at all, so two sentences merge and a resolving target vouches for an
|
||||||
|
# unresolvable one it never stood beside — a hard FAIL with no escape hatch,
|
||||||
|
# which is exactly the failure the corroboration rule was added to prevent.
|
||||||
|
# Both are closed here: the five abbreviations that actually occur in routing
|
||||||
|
# prose are excluded as sentence ends, and the opener class admits a backtick or
|
||||||
|
# a lowercase letter. Verified zero-delta on the current corpus (37 ERROR / 58
|
||||||
|
# SUGGESTION / 2 dangling before and after) — this protects the descriptions
|
||||||
|
# issue #99 is about to rewrite, not the ones already measured.
|
||||||
|
SENTENCE_SPLIT = re.compile(
|
||||||
|
u'(?<!\\be\\.g\\.)(?<!\\bi\\.e\\.)(?<!\\betc\\.)(?<!\\bvs\\.)(?<!\\bcf\\.)'
|
||||||
|
u'(?<=[.!?])\\s+(?=[A-Za-z`"“(])')
|
||||||
|
|
||||||
# The token that may follow a route target without turning it into a compound
|
# The token that may follow a route target without turning it into a compound
|
||||||
# modifier: punctuation, end of sentence, a conjunction, a boundary word, or a
|
# modifier: punctuation, end of sentence, a conjunction, a boundary word, or a
|
||||||
|
|||||||
@@ -57,6 +57,12 @@ therefore resolves; a skill in an unrelated repo does not. A boundary clause nam
|
|||||||
outside that universe sends the router nowhere and fails the audit. Check the target exists before
|
outside that universe sends the router nowhere and fails the audit. Check the target exists before
|
||||||
writing it — do not invent a plausible sibling name.
|
writing it — do not invent a plausible sibling name.
|
||||||
|
|
||||||
|
That universe is the apm marketplace and stops there. A **host built-in is not a routing target**:
|
||||||
|
`/compact`, `/clear` and `/init` are Claude Code slash commands with no counterpart in Copilot CLI
|
||||||
|
or Codex, and `.apm/` source compiles for all three, so routing to one is a portability defect. The
|
||||||
|
gate is right to fail it and there is no allowlist. If a built-in genuinely needs mentioning, write
|
||||||
|
it un-slashed — ``the `compact` built-in`` — which makes no routing claim and is not checked.
|
||||||
|
|
||||||
**Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only
|
**Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only
|
||||||
with YAML folding resolved. The agentskills.io 1,024-character spec limit is unchanged and sits
|
with YAML folding resolved. The agentskills.io 1,024-character spec limit is unchanged and sits
|
||||||
above both. The SUGGESTION tier is the one that moves the average; treat 250 as the target and 400
|
above both. The SUGGESTION tier is the one that moves the average; treat 250 as the target and 400
|
||||||
|
|||||||
@@ -554,7 +554,28 @@ BACKTICK = re.compile(r"`(%s)`" % NAME_HYPH, re.I)
|
|||||||
# ADR-0020's compressed arrow form `Not <thing> -> <name>`.
|
# ADR-0020's compressed arrow form `Not <thing> -> <name>`.
|
||||||
BOUNDARY_MARKER = re.compile(r"\b(?:do\s+not|instead|rather\s+than|not\s+for)\b", re.I)
|
BOUNDARY_MARKER = re.compile(r"\b(?:do\s+not|instead|rather\s+than|not\s+for)\b", re.I)
|
||||||
BOUNDARY_ARROW = re.compile(r"\bnot\b[^.;]*?(?:->|→)", re.I)
|
BOUNDARY_ARROW = re.compile(r"\bnot\b[^.;]*?(?:->|→)", re.I)
|
||||||
SENTENCE_SPLIT = re.compile(u'(?<=[.!?])\\s+(?=[A-Z"“(])')
|
# Sentence boundaries decide the CORROBORATION scope above, so getting one wrong
|
||||||
|
# is not cosmetic — it moves a target between SUGGESTION and blocking ERROR. Two
|
||||||
|
# shapes common in these descriptions defeat the naive "period, space, capital"
|
||||||
|
# rule, in OPPOSITE directions:
|
||||||
|
# OVER-SPLIT. `e.g. "set up the manifest"` ends no sentence, but the quote
|
||||||
|
# looks like one starting. The clause is cut in half, the corroborating
|
||||||
|
# target lands on the far side of the cut, and a genuinely dangling target
|
||||||
|
# silently demotes to SUGGESTION — the gate takes a measurement and then
|
||||||
|
# throws it away, which is the vacuous-green shape this file exists to stop.
|
||||||
|
# UNDER-SPLIT. A real sentence opening with a code span or a lowercase skill
|
||||||
|
# name ("... Composes it. `gitea-prs` also uses it.") is not seen as a start
|
||||||
|
# at all, so two sentences merge and a resolving target vouches for an
|
||||||
|
# unresolvable one it never stood beside — a hard FAIL with no escape hatch,
|
||||||
|
# which is exactly the failure the corroboration rule was added to prevent.
|
||||||
|
# Both are closed here: the five abbreviations that actually occur in routing
|
||||||
|
# prose are excluded as sentence ends, and the opener class admits a backtick or
|
||||||
|
# a lowercase letter. Verified zero-delta on the current corpus (37 ERROR / 58
|
||||||
|
# SUGGESTION / 2 dangling before and after) — this protects the descriptions
|
||||||
|
# issue #99 is about to rewrite, not the ones already measured.
|
||||||
|
SENTENCE_SPLIT = re.compile(
|
||||||
|
u'(?<!\\be\\.g\\.)(?<!\\bi\\.e\\.)(?<!\\betc\\.)(?<!\\bvs\\.)(?<!\\bcf\\.)'
|
||||||
|
u'(?<=[.!?])\\s+(?=[A-Za-z`"“(])')
|
||||||
|
|
||||||
# The token that may follow a route target without turning it into a compound
|
# The token that may follow a route target without turning it into a compound
|
||||||
# modifier: punctuation, end of sentence, a conjunction, a boundary word, or a
|
# modifier: punctuation, end of sentence, a conjunction, a boundary word, or a
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ that package declares in `apm.yml` under `dependencies.apm`. A sibling plugin in
|
|||||||
therefore resolves; a skill in an unrelated repo does not. A target outside that universe sends the
|
therefore resolves; a skill in an unrelated repo does not. A target outside that universe sends the
|
||||||
router nowhere. Verify it before writing it — do not invent a plausible sibling.
|
router nowhere. Verify it before writing it — do not invent a plausible sibling.
|
||||||
|
|
||||||
|
That universe is the apm marketplace and stops there. A **host built-in is not a routing target**:
|
||||||
|
`/compact`, `/clear` and `/init` are Claude Code slash commands with no counterpart in Copilot CLI
|
||||||
|
or Codex, and `.apm/` source compiles for all three, so routing to one is a portability defect. The
|
||||||
|
gate is right to fail it and there is no allowlist. If a built-in genuinely needs mentioning, write
|
||||||
|
it un-slashed — ``the `compact` built-in`` — which makes no routing claim and is not checked.
|
||||||
|
|
||||||
**Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only
|
**Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only
|
||||||
with YAML folding resolved. Treat 250 as the target: the SUGGESTION tier is what moves the corpus
|
with YAML folding resolved. Treat 250 as the target: the SUGGESTION tier is what moves the corpus
|
||||||
average, the FAIL tier only stops outliers.
|
average, the FAIL tier only stops outliers.
|
||||||
|
|||||||
@@ -480,7 +480,28 @@ BACKTICK = re.compile(r"`(%s)`" % NAME_HYPH, re.I)
|
|||||||
# ADR-0020's compressed arrow form `Not <thing> -> <name>`.
|
# ADR-0020's compressed arrow form `Not <thing> -> <name>`.
|
||||||
BOUNDARY_MARKER = re.compile(r"\b(?:do\s+not|instead|rather\s+than|not\s+for)\b", re.I)
|
BOUNDARY_MARKER = re.compile(r"\b(?:do\s+not|instead|rather\s+than|not\s+for)\b", re.I)
|
||||||
BOUNDARY_ARROW = re.compile(r"\bnot\b[^.;]*?(?:->|→)", re.I)
|
BOUNDARY_ARROW = re.compile(r"\bnot\b[^.;]*?(?:->|→)", re.I)
|
||||||
SENTENCE_SPLIT = re.compile(u'(?<=[.!?])\\s+(?=[A-Z"“(])')
|
# Sentence boundaries decide the CORROBORATION scope above, so getting one wrong
|
||||||
|
# is not cosmetic — it moves a target between SUGGESTION and blocking ERROR. Two
|
||||||
|
# shapes common in these descriptions defeat the naive "period, space, capital"
|
||||||
|
# rule, in OPPOSITE directions:
|
||||||
|
# OVER-SPLIT. `e.g. "set up the manifest"` ends no sentence, but the quote
|
||||||
|
# looks like one starting. The clause is cut in half, the corroborating
|
||||||
|
# target lands on the far side of the cut, and a genuinely dangling target
|
||||||
|
# silently demotes to SUGGESTION — the gate takes a measurement and then
|
||||||
|
# throws it away, which is the vacuous-green shape this file exists to stop.
|
||||||
|
# UNDER-SPLIT. A real sentence opening with a code span or a lowercase skill
|
||||||
|
# name ("... Composes it. `gitea-prs` also uses it.") is not seen as a start
|
||||||
|
# at all, so two sentences merge and a resolving target vouches for an
|
||||||
|
# unresolvable one it never stood beside — a hard FAIL with no escape hatch,
|
||||||
|
# which is exactly the failure the corroboration rule was added to prevent.
|
||||||
|
# Both are closed here: the five abbreviations that actually occur in routing
|
||||||
|
# prose are excluded as sentence ends, and the opener class admits a backtick or
|
||||||
|
# a lowercase letter. Verified zero-delta on the current corpus (37 ERROR / 58
|
||||||
|
# SUGGESTION / 2 dangling before and after) — this protects the descriptions
|
||||||
|
# issue #99 is about to rewrite, not the ones already measured.
|
||||||
|
SENTENCE_SPLIT = re.compile(
|
||||||
|
u'(?<!\\be\\.g\\.)(?<!\\bi\\.e\\.)(?<!\\betc\\.)(?<!\\bvs\\.)(?<!\\bcf\\.)'
|
||||||
|
u'(?<=[.!?])\\s+(?=[A-Za-z`"“(])')
|
||||||
|
|
||||||
# The token that may follow a route target without turning it into a compound
|
# The token that may follow a route target without turning it into a compound
|
||||||
# modifier: punctuation, end of sentence, a conjunction, a boundary word, or a
|
# modifier: punctuation, end of sentence, a conjunction, a boundary word, or a
|
||||||
|
|||||||
@@ -57,6 +57,12 @@ therefore resolves; a skill in an unrelated repo does not. A boundary clause nam
|
|||||||
outside that universe sends the router nowhere and fails the audit. Check the target exists before
|
outside that universe sends the router nowhere and fails the audit. Check the target exists before
|
||||||
writing it — do not invent a plausible sibling name.
|
writing it — do not invent a plausible sibling name.
|
||||||
|
|
||||||
|
That universe is the apm marketplace and stops there. A **host built-in is not a routing target**:
|
||||||
|
`/compact`, `/clear` and `/init` are Claude Code slash commands with no counterpart in Copilot CLI
|
||||||
|
or Codex, and `.apm/` source compiles for all three, so routing to one is a portability defect. The
|
||||||
|
gate is right to fail it and there is no allowlist. If a built-in genuinely needs mentioning, write
|
||||||
|
it un-slashed — ``the `compact` built-in`` — which makes no routing claim and is not checked.
|
||||||
|
|
||||||
**Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only
|
**Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only
|
||||||
with YAML folding resolved. The agentskills.io 1,024-character spec limit is unchanged and sits
|
with YAML folding resolved. The agentskills.io 1,024-character spec limit is unchanged and sits
|
||||||
above both. The SUGGESTION tier is the one that moves the average; treat 250 as the target and 400
|
above both. The SUGGESTION tier is the one that moves the average; treat 250 as the target and 400
|
||||||
|
|||||||
@@ -564,7 +564,28 @@ BACKTICK = re.compile(r"`(%s)`" % NAME_HYPH, re.I)
|
|||||||
# ADR-0020's compressed arrow form `Not <thing> -> <name>`.
|
# ADR-0020's compressed arrow form `Not <thing> -> <name>`.
|
||||||
BOUNDARY_MARKER = re.compile(r"\b(?:do\s+not|instead|rather\s+than|not\s+for)\b", re.I)
|
BOUNDARY_MARKER = re.compile(r"\b(?:do\s+not|instead|rather\s+than|not\s+for)\b", re.I)
|
||||||
BOUNDARY_ARROW = re.compile(r"\bnot\b[^.;]*?(?:->|→)", re.I)
|
BOUNDARY_ARROW = re.compile(r"\bnot\b[^.;]*?(?:->|→)", re.I)
|
||||||
SENTENCE_SPLIT = re.compile(u'(?<=[.!?])\\s+(?=[A-Z"“(])')
|
# Sentence boundaries decide the CORROBORATION scope above, so getting one wrong
|
||||||
|
# is not cosmetic — it moves a target between SUGGESTION and blocking ERROR. Two
|
||||||
|
# shapes common in these descriptions defeat the naive "period, space, capital"
|
||||||
|
# rule, in OPPOSITE directions:
|
||||||
|
# OVER-SPLIT. `e.g. "set up the manifest"` ends no sentence, but the quote
|
||||||
|
# looks like one starting. The clause is cut in half, the corroborating
|
||||||
|
# target lands on the far side of the cut, and a genuinely dangling target
|
||||||
|
# silently demotes to SUGGESTION — the gate takes a measurement and then
|
||||||
|
# throws it away, which is the vacuous-green shape this file exists to stop.
|
||||||
|
# UNDER-SPLIT. A real sentence opening with a code span or a lowercase skill
|
||||||
|
# name ("... Composes it. `gitea-prs` also uses it.") is not seen as a start
|
||||||
|
# at all, so two sentences merge and a resolving target vouches for an
|
||||||
|
# unresolvable one it never stood beside — a hard FAIL with no escape hatch,
|
||||||
|
# which is exactly the failure the corroboration rule was added to prevent.
|
||||||
|
# Both are closed here: the five abbreviations that actually occur in routing
|
||||||
|
# prose are excluded as sentence ends, and the opener class admits a backtick or
|
||||||
|
# a lowercase letter. Verified zero-delta on the current corpus (37 ERROR / 58
|
||||||
|
# SUGGESTION / 2 dangling before and after) — this protects the descriptions
|
||||||
|
# issue #99 is about to rewrite, not the ones already measured.
|
||||||
|
SENTENCE_SPLIT = re.compile(
|
||||||
|
u'(?<!\\be\\.g\\.)(?<!\\bi\\.e\\.)(?<!\\betc\\.)(?<!\\bvs\\.)(?<!\\bcf\\.)'
|
||||||
|
u'(?<=[.!?])\\s+(?=[A-Za-z`"“(])')
|
||||||
|
|
||||||
# The token that may follow a route target without turning it into a compound
|
# The token that may follow a route target without turning it into a compound
|
||||||
# modifier: punctuation, end of sentence, a conjunction, a boundary word, or a
|
# modifier: punctuation, end of sentence, a conjunction, a boundary word, or a
|
||||||
|
|||||||
@@ -564,6 +564,30 @@ grammar_case tp-backticked errors "routes to 'no-such-backticked-skill'" \
|
|||||||
grammar_case tp-bare-terminal errors "routes to 'no-such-bare-skill'" \
|
grammar_case tp-bare-terminal errors "routes to 'no-such-bare-skill'" \
|
||||||
"Use when doing the thing. Do not use for improvements — use sibling-skill or no-such-bare-skill instead."
|
"Use when doing the thing. Do not use for improvements — use sibling-skill or no-such-bare-skill instead."
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--- corroboration is scoped to a REAL sentence, not to whatever the splitter says ---"
|
||||||
|
# Corroboration decides SUGGESTION vs blocking ERROR, so a mis-placed sentence
|
||||||
|
# boundary moves a target between the two tiers. The naive "period, space,
|
||||||
|
# capital" rule got this wrong in both directions, and both were live:
|
||||||
|
#
|
||||||
|
# OVER-SPLIT. `e.g. "..."` is not a sentence end, but the quote looks like a
|
||||||
|
# start. The clause was cut in half and the corroborator stranded on the far
|
||||||
|
# side, so a target that DOES sit beside a resolving sibling silently demoted
|
||||||
|
# to SUGGESTION — a measurement taken and then discarded.
|
||||||
|
grammar_case abbrev-split errors "routes to 'no-such-abbrev-skill'" \
|
||||||
|
"Use when doing the thing. Do not use for improvements — use sibling-skill first, e.g. \"run the audit\", then use no-such-abbrev-skill instead."
|
||||||
|
#
|
||||||
|
# UNDER-SPLIT. A sentence opening with a lowercase word or a code span was not
|
||||||
|
# seen as a start at all, so two sentences merged and a resolving target in the
|
||||||
|
# FIRST vouched for an unresolvable one in the SECOND that it never stood
|
||||||
|
# beside — a hard FAIL with no escape hatch, which is the exact failure
|
||||||
|
# corroboration was added to prevent. The target must still be REPORTED; only
|
||||||
|
# the power to block is withdrawn.
|
||||||
|
grammar_case lowercase-start suggests "routes to 'no-such-lower-skill'" \
|
||||||
|
"Use when doing the thing. Use sibling-skill for the main case. do not use for improvements — use no-such-lower-skill instead."
|
||||||
|
grammar_case backtick-start suggests "routes to 'no-such-tick-skill'" \
|
||||||
|
"Use when doing the thing. Use sibling-skill for the main case. \`no-such-tick-skill\` is not for this — do not use it instead."
|
||||||
|
|
||||||
# And the confirming half of the grammar rule: a compound-modifier target is
|
# And the confirming half of the grammar rule: a compound-modifier target is
|
||||||
# CONFIRM-ONLY, not ignored. When the name does exist it still counts as a route
|
# CONFIRM-ONLY, not ignored. When the name does exist it still counts as a route
|
||||||
# — the rule suppresses the ERROR, it does not delete the target.
|
# — the rule suppresses the ERROR, it does not delete the target.
|
||||||
|
|||||||
Reference in New Issue
Block a user