Design surface: starter roles, theme literals, and the view that could only inspect itself #97
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "scribe",
|
"name": "scribe",
|
||||||
"description": "Scribe system-of-record for Claude Code: MCP tools over your notes/tasks/projects/rules, a session-start push channel that surfaces your always-on rules + active-project context, process-skills (writing-plans, systematic-debugging, verification, brainstorming, reusing-code), and your saved Scribe Processes auto-surfaced as skills (/scribe:sync). Replaces superpowers + file-memory with one app-backed plugin.",
|
"description": "Scribe system-of-record for Claude Code: MCP tools over your notes/tasks/projects/rules, a session-start push channel that surfaces your always-on rules + active-project context, process-skills (writing-plans, systematic-debugging, verification, brainstorming, reusing-code), and your saved Scribe Processes auto-surfaced as skills (/scribe:sync). Replaces superpowers + file-memory with one app-backed plugin.",
|
||||||
"version": "0.1.22",
|
"version": "0.1.23",
|
||||||
"author": { "name": "Bryan Van Deusen" },
|
"author": { "name": "Bryan Van Deusen" },
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"scribe": {
|
"scribe": {
|
||||||
|
|||||||
@@ -61,6 +61,31 @@ prepend() { if [ -n "$out" ]; then out="$1"$'\n\n---\n\n'"${out}"; else out="$1"
|
|||||||
# --- Tier 1: static behavioral mandate (always, keyless, networkless) ---
|
# --- Tier 1: static behavioral mandate (always, keyless, networkless) ---
|
||||||
[ -f "$here/scribe_static_context.md" ] && out=$(cat "$here/scribe_static_context.md")
|
[ -f "$here/scribe_static_context.md" ] && out=$(cat "$here/scribe_static_context.md")
|
||||||
|
|
||||||
|
# --- Which version is actually RUNNING (keyless, networkless) ---
|
||||||
|
#
|
||||||
|
# An install has two halves and only one self-updates:
|
||||||
|
#
|
||||||
|
# marketplaces/…/scribe-plugin/ git clone — pulls on its own
|
||||||
|
# cache/…/scribe/<version>/ what EXECUTES — refreshed only when the
|
||||||
|
# manifest version changes
|
||||||
|
#
|
||||||
|
# So inspecting the clone shows a fix present while the broken copy keeps
|
||||||
|
# running, and the obvious debugging move actively misleads (#2209). Twice, the
|
||||||
|
# only detector was the operator saying "I don't think it updated".
|
||||||
|
#
|
||||||
|
# Naming the running version in every session makes that answerable from the
|
||||||
|
# transcript instead of by archaeology in the cache directory. Deliberately NOT
|
||||||
|
# a server round-trip or a stored per-user record: the state most needing
|
||||||
|
# diagnosis is the one where credentials never arrive, and this line still
|
||||||
|
# appears there.
|
||||||
|
manifest="$here/../.claude-plugin/plugin.json"
|
||||||
|
if [ -f "$manifest" ]; then
|
||||||
|
plugin_version=$(jq -r '.version // empty' "$manifest" 2>/dev/null) || plugin_version=""
|
||||||
|
if [ -n "$plugin_version" ]; then
|
||||||
|
append "> Scribe plugin **v${plugin_version}** is executing in this session. A fix merged after this version has not reached it — the marketplace clone updates on its own, but the cache that runs only refreshes when the manifest version changes."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# --- Tier 2: dynamic rules + active-project context (best-effort) ---
|
# --- Tier 2: dynamic rules + active-project context (best-effort) ---
|
||||||
url=${SCRIBE_URL:-${CLAUDE_PLUGIN_OPTION_API_ENDPOINT:-}}
|
url=${SCRIBE_URL:-${CLAUDE_PLUGIN_OPTION_API_ENDPOINT:-}}
|
||||||
token=${SCRIBE_TOKEN:-${CLAUDE_PLUGIN_OPTION_API_TOKEN:-}}
|
token=${SCRIBE_TOKEN:-${CLAUDE_PLUGIN_OPTION_API_TOKEN:-}}
|
||||||
|
|||||||
@@ -307,6 +307,44 @@ def check_local_prior_art_needs_no_instance() -> None:
|
|||||||
ok("prior-art local arm: answers with no instance configured")
|
ok("prior-art local arm: answers with no instance configured")
|
||||||
|
|
||||||
|
|
||||||
|
def check_session_context_reports_its_version() -> None:
|
||||||
|
"""The SessionStart context must name the plugin version it is running.
|
||||||
|
|
||||||
|
An install has two halves and only one self-updates: the marketplace clone
|
||||||
|
pulls on its own, while the CACHE is what executes and refreshes only when
|
||||||
|
the manifest version changes. So a shipped fix can sit unreached while
|
||||||
|
inspecting the clone shows it present — the obvious debugging move
|
||||||
|
misleads, and twice the only detector was a human saying "I don't think it
|
||||||
|
updated" (#2209, #2220).
|
||||||
|
|
||||||
|
Asserted WITHOUT credentials on purpose. The state most needing diagnosis
|
||||||
|
is the one where the token never arrives, and a marker that vanished there
|
||||||
|
would be missing exactly when it is wanted.
|
||||||
|
"""
|
||||||
|
script = HOOKS_DIR / "scribe_session_context.sh"
|
||||||
|
if not script.is_file() or not shutil.which("jq"):
|
||||||
|
skip("version marker: hook or jq missing")
|
||||||
|
return
|
||||||
|
|
||||||
|
manifest_v = manifest_version()
|
||||||
|
if manifest_v is None:
|
||||||
|
fail("version marker: could not read the manifest version")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
proc = _run_hook(script, json.dumps({"source": "startup"}), {})
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
fail("version marker: hook hung")
|
||||||
|
return
|
||||||
|
if proc.returncode != 0:
|
||||||
|
fail(f"version marker: hook exited {proc.returncode}")
|
||||||
|
elif manifest_v not in proc.stdout:
|
||||||
|
fail(f"version marker: session context never names v{manifest_v} — "
|
||||||
|
f"a stale install would be undetectable from the transcript")
|
||||||
|
else:
|
||||||
|
ok(f"version marker: session context reports v{manifest_v}, no credentials needed")
|
||||||
|
|
||||||
|
|
||||||
def _git(*args: str) -> tuple[int, str]:
|
def _git(*args: str) -> tuple[int, str]:
|
||||||
proc = subprocess.run(
|
proc = subprocess.run(
|
||||||
["git", *args], capture_output=True, text=True, cwd=ROOT
|
["git", *args], capture_output=True, text=True, cwd=ROOT
|
||||||
@@ -399,6 +437,7 @@ def main() -> int:
|
|||||||
check_shellcheck()
|
check_shellcheck()
|
||||||
check_fail_open()
|
check_fail_open()
|
||||||
check_local_prior_art_needs_no_instance()
|
check_local_prior_art_needs_no_instance()
|
||||||
|
check_session_context_reports_its_version()
|
||||||
if not args.no_version:
|
if not args.no_version:
|
||||||
check_version_bump(args.base)
|
check_version_bump(args.base)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user