feat(WARDEN-WP-0018): activate whynot-design npm publish lane + resolvable flag

railiance-platform finished provisioning the whynot-design npm publish lane
(CCR-2026-0001, commit 8f617fc: active, readiness=ready, resolvable=true, positive
fetch + negative denial verified). First concrete warden access --fetch-resolvable
non-SSH lane — end-to-end proof of the WP-0014 conduit + WP-0017 discoverability.

T1 — catalog entry whynot-design-npm-publish (active, exec_capable) with the
owner-confirmed zero-placeholder handoff: path platform/workloads/coulomb/whynot-design/
npm-publish (the superseded whynot-design/whynot-design/... form is not used), field
NPM_AUTH_TOKEN, OIDC role whynot-design-workload-kv-read, policy + flex-auth ref. Added
wiki/playbooks/whynot-design-npm-publish.md.

T2 — RouteEntry.resolvable (active + exec_capable + no <…> placeholder), surfaced in
route/access --json; Catalog.find resolves an exact catalog-id first so
`warden access whynot-design-npm-publish` is deterministic. Tests added; fixed a
no-match test query that substring-collided (no ⊂ whynot). 213 pass, lint clean.

T3 — notified whynot-design (zero-placeholder command + resolvable gate + path
correction) and confirmed activation to railiance-platform. Sibling lanes stay draft
per their deferral.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-29 00:32:00 +02:00
parent 46b340f45f
commit e8bb469033
9 changed files with 252 additions and 2 deletions

View File

@@ -553,6 +553,9 @@ def _entry_summary(entry) -> dict:
else "route"
),
"exec_capable": entry.exec_capable,
# resolvable: can `warden access --fetch` run this now with no <…> to fill?
# Lets an automated caller gate on readiness before attempting a fetch.
"resolvable": entry.resolvable,
"wiki_ref": entry.wiki_ref,
"canon_ref": entry.canon_ref,
"reviewed": entry.reviewed,

View File

@@ -126,7 +126,15 @@ class Catalog:
return [e for e in self.entries if e.is_active]
def find(self, query: str, include_draft: bool = False, limit: int = 5) -> List[RouteEntry]:
"""Rank entries by keyword overlap with the query. Highest first."""
"""Rank entries by keyword overlap with the query. Highest first.
An exact catalog-id match wins outright — this is what makes a stable keyed
command (`warden access whynot-design-npm-publish`) resolve deterministically
regardless of keyword collisions with other lanes.
"""
exact = self.get(query.strip())
if exact is not None and (include_draft or exact.is_active):
return [exact]
tokens = [t for t in query.lower().replace("-", " ").split() if t]
pool = self.listed(include_draft=include_draft)
scored = [(e.match_score(tokens), e) for e in pool]

View File

@@ -53,6 +53,21 @@ class RouteEntry:
"""True when structured assist fields are present (advisory richness)."""
return any((self.auth_method, self.path_template, self.fetch_command))
@property
def resolvable(self) -> bool:
"""True when `warden access --fetch` can run this lane with no further input.
A resolvable lane is active, exec_capable, and its fetch command (with the path
inlined) carries no unresolved ``<...>`` placeholder. Template lanes — like the
generic ``openbao-api-key`` or the ``<domain>``-parameterized login — are *not*
resolvable until an owner ships concrete names. Lets an automated caller know
whether ``--fetch`` will work *before* attempting it (whynot-design request).
"""
if not (self.is_active and self.exec_capable and self.fetch_command):
return False
blob = f"{self.fetch_command} {self.path_template or ''}"
return "<" not in blob and ">" not in blob
def match_score(self, tokens: List[str]) -> int:
"""Keyword-overlap score against need_keywords, title, and id.