arkaos 4.6.0 → 4.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONSTITUTION.md +30 -16
- package/VERSION +1 -1
- package/arka/SKILL.md +26 -36
- package/arka/skills/bootstrap-agent/SKILL.md +6 -0
- package/arka/skills/checkpoint/SKILL.md +1 -1
- package/arka/skills/costs/SKILL.md +14 -5
- package/arka/skills/flow/SKILL.md +30 -15
- package/arka/skills/forge/SKILL.md +19 -15
- package/arka/skills/human-writing/SKILL.md +16 -7
- package/arka/skills/research/SKILL.md +20 -7
- package/arka/templates/skill-template.md +102 -0
- package/bin/arka-py.ps1 +9 -2
- package/config/claude-agents/architect.md +51 -0
- package/config/claude-agents/backend-dev.md +51 -0
- package/config/claude-agents/dba.md +51 -0
- package/config/claude-agents/devops-eng.md +51 -0
- package/config/claude-agents/eduardo-copy.md +14 -7
- package/config/claude-agents/francisca-tech.md +24 -6
- package/config/claude-agents/frontend-dev.md +51 -0
- package/config/claude-agents/marta-cqo.md +28 -8
- package/config/claude-agents/qa-eng.md +51 -0
- package/config/claude-agents/research-assistant.md +50 -0
- package/config/claude-agents/security-eng.md +51 -0
- package/config/constitution.yaml +127 -88
- package/config/hooks/session-start.ps1 +3 -1
- package/config/hooks/session-start.sh +3 -1
- package/config/hooks/user-prompt-submit-v2.sh +4 -11
- package/config/hooks/user-prompt-submit.ps1 +4 -7
- package/config/hooks/user-prompt-submit.sh +8 -1
- package/core/agents/__pycache__/behavioral_compiler.cpython-313.pyc +0 -0
- package/core/agents/behavioral_compiler.py +294 -0
- package/core/budget/__pycache__/__init__.cpython-314.pyc +0 -0
- package/core/budget/__pycache__/manager.cpython-314.pyc +0 -0
- package/core/budget/__pycache__/schema.cpython-314.pyc +0 -0
- package/core/forge/__pycache__/__init__.cpython-314.pyc +0 -0
- package/core/forge/__pycache__/complexity.cpython-314.pyc +0 -0
- package/core/forge/__pycache__/handoff.cpython-314.pyc +0 -0
- package/core/forge/__pycache__/orchestrator.cpython-314.pyc +0 -0
- package/core/forge/__pycache__/persistence.cpython-314.pyc +0 -0
- package/core/forge/__pycache__/renderer.cpython-314.pyc +0 -0
- package/core/forge/__pycache__/runtime_dispatcher.cpython-314.pyc +0 -0
- package/core/forge/__pycache__/schema.cpython-314.pyc +0 -0
- package/core/governance/__pycache__/agent_experiences.cpython-314.pyc +0 -0
- package/core/governance/__pycache__/closing_marker_check.cpython-313.pyc +0 -0
- package/core/governance/__pycache__/closing_marker_check.cpython-314.pyc +0 -0
- package/core/governance/__pycache__/phantom_action_check.cpython-313.pyc +0 -0
- package/core/governance/__pycache__/phantom_action_check.cpython-314.pyc +0 -0
- package/core/governance/__pycache__/qg_verdict.cpython-313.pyc +0 -0
- package/core/governance/__pycache__/quality_api.cpython-314.pyc +0 -0
- package/core/governance/__pycache__/quality_router.cpython-314.pyc +0 -0
- package/core/governance/__pycache__/review_workflow.cpython-314.pyc +0 -0
- package/core/governance/closing_marker_check.py +2 -2
- package/core/governance/phantom_action_check.py +221 -0
- package/core/governance/qg_verdict.py +12 -0
- package/core/hooks/__pycache__/stop.cpython-313.pyc +0 -0
- package/core/hooks/__pycache__/stop.cpython-314.pyc +0 -0
- package/core/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
- package/core/hooks/__pycache__/user_prompt_submit.cpython-314.pyc +0 -0
- package/core/hooks/stop.py +25 -0
- package/core/hooks/user_prompt_submit.py +15 -10
- package/core/knowledge/__pycache__/__init__.cpython-314.pyc +0 -0
- package/core/knowledge/__pycache__/chunker.cpython-314.pyc +0 -0
- package/core/knowledge/__pycache__/embedder.cpython-314.pyc +0 -0
- package/core/knowledge/__pycache__/pattern_cards.cpython-314.pyc +0 -0
- package/core/knowledge/__pycache__/vector_store.cpython-312.pyc +0 -0
- package/core/knowledge/__pycache__/vector_store.cpython-314.pyc +0 -0
- package/core/memory/__pycache__/rehydrator.cpython-314.pyc +0 -0
- package/core/runtime/__pycache__/claude_code.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/codex_cli.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/gemini_cli.cpython-313.pyc +0 -0
- package/core/runtime/claude_code.py +2 -1
- package/core/runtime/codex_cli.py +2 -0
- package/core/runtime/gemini_cli.py +2 -0
- package/core/shared/__pycache__/temp_paths.cpython-312.pyc +0 -0
- package/core/synapse/__pycache__/agent_experiences_layer.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/agent_experiences_layer.cpython-314.pyc +0 -0
- package/core/synapse/__pycache__/engine.cpython-312.pyc +0 -0
- package/core/synapse/__pycache__/engine.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/engine.cpython-314.pyc +0 -0
- package/core/synapse/__pycache__/graph_context_layer.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/graph_context_layer.cpython-314.pyc +0 -0
- package/core/synapse/__pycache__/layers.cpython-312.pyc +0 -0
- package/core/synapse/__pycache__/layers.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/layers.cpython-314.pyc +0 -0
- package/core/synapse/__pycache__/pattern_library_layer.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/pattern_library_layer.cpython-314.pyc +0 -0
- package/core/synapse/agent_experiences_layer.py +4 -0
- package/core/synapse/engine.py +13 -2
- package/core/synapse/graph_context_layer.py +4 -0
- package/core/synapse/layers.py +28 -49
- package/core/synapse/pattern_library_layer.py +4 -0
- package/departments/brand/SKILL.md +5 -13
- package/departments/brand/skills/archetype-finder/SKILL.md +3 -11
- package/departments/brand/skills/colors/SKILL.md +3 -11
- package/departments/brand/skills/design-review/SKILL.md +11 -3
- package/departments/brand/skills/design-system/SKILL.md +3 -11
- package/departments/brand/skills/identity-system/SKILL.md +3 -11
- package/departments/brand/skills/logo-brief/SKILL.md +3 -11
- package/departments/brand/skills/mockup-generate/SKILL.md +3 -11
- package/departments/brand/skills/naming-evaluate/SKILL.md +3 -11
- package/departments/brand/skills/positioning-statement/SKILL.md +3 -11
- package/departments/brand/skills/primal-audit/SKILL.md +3 -11
- package/departments/brand/skills/ux-audit/SKILL.md +3 -11
- package/departments/brand/skills/voice-guide/SKILL.md +3 -11
- package/departments/brand/skills/wireframe/SKILL.md +3 -11
- package/departments/community/SKILL.md +4 -12
- package/departments/community/skills/ai-community/SKILL.md +3 -11
- package/departments/community/skills/betting-setup/SKILL.md +3 -11
- package/departments/community/skills/business-model/SKILL.md +3 -11
- package/departments/community/skills/content-calendar/SKILL.md +3 -11
- package/departments/community/skills/events-plan/SKILL.md +3 -11
- package/departments/community/skills/gamification-design/SKILL.md +3 -11
- package/departments/community/skills/growth-plan/SKILL.md +13 -12
- package/departments/community/skills/metrics-track/SKILL.md +3 -11
- package/departments/community/skills/moderation/SKILL.md +3 -11
- package/departments/community/skills/monetize-plan/SKILL.md +3 -11
- package/departments/community/skills/niche-setup/SKILL.md +3 -11
- package/departments/community/skills/onboarding-flow/SKILL.md +3 -11
- package/departments/community/skills/platform-select/SKILL.md +3 -11
- package/departments/content/SKILL.md +4 -12
- package/departments/content/skills/ai-workflow/SKILL.md +3 -11
- package/departments/content/skills/analytics/SKILL.md +3 -11
- package/departments/content/skills/calendar/SKILL.md +3 -11
- package/departments/content/skills/content-system/SKILL.md +3 -11
- package/departments/content/skills/monetization-plan/SKILL.md +3 -11
- package/departments/content/skills/newsletter-write/SKILL.md +3 -11
- package/departments/content/skills/platform-optimize/SKILL.md +3 -11
- package/departments/content/skills/repurpose-plan/SKILL.md +3 -11
- package/departments/content/skills/script-structure/SKILL.md +3 -11
- package/departments/content/skills/short-form/SKILL.md +3 -11
- package/departments/content/skills/thumbnail-package/SKILL.md +3 -11
- package/departments/content/skills/viral-design/SKILL.md +3 -11
- package/departments/content/skills/youtube-strategy/SKILL.md +3 -11
- package/departments/dev/SKILL.md +4 -12
- package/departments/dev/agents/security-eng.yaml +1 -1
- package/departments/dev/skills/adversarial-review/SKILL.md +10 -2
- package/departments/dev/skills/ai-assisted-dev/SKILL.md +3 -11
- package/departments/dev/skills/architecture-design/SKILL.md +3 -11
- package/departments/dev/skills/clean-code-review/SKILL.md +9 -2
- package/departments/dev/skills/code-review/SKILL.md +12 -12
- package/departments/dev/skills/db-design/SKILL.md +3 -11
- package/departments/dev/skills/ddd-model/SKILL.md +3 -11
- package/departments/dev/skills/demo-gif/SKILL.md +3 -11
- package/departments/dev/skills/deploy/SKILL.md +3 -11
- package/departments/dev/skills/devops-pipeline/SKILL.md +3 -11
- package/departments/dev/skills/docs/SKILL.md +3 -11
- package/departments/dev/skills/mcp/SKILL.md +3 -11
- package/departments/dev/skills/performance-audit/SKILL.md +3 -11
- package/departments/dev/skills/refactor-plan/SKILL.md +3 -11
- package/departments/dev/skills/research/SKILL.md +16 -12
- package/departments/dev/skills/scaffold/SKILL.md +15 -11
- package/departments/dev/skills/security-compliance/SKILL.md +3 -11
- package/departments/dev/skills/spec/SKILL.md +15 -10
- package/departments/dev/skills/stack-check/SKILL.md +3 -11
- package/departments/ecom/SKILL.md +4 -12
- package/departments/ecom/skills/analytics/SKILL.md +3 -11
- package/departments/ecom/skills/browse-competitor/SKILL.md +3 -11
- package/departments/ecom/skills/cart-recovery/SKILL.md +3 -11
- package/departments/ecom/skills/cro-optimize/SKILL.md +3 -11
- package/departments/ecom/skills/customer-journey/SKILL.md +3 -11
- package/departments/ecom/skills/fulfillment-plan/SKILL.md +3 -11
- package/departments/ecom/skills/marketplace-manage/SKILL.md +3 -11
- package/departments/ecom/skills/pricing-strategy/SKILL.md +3 -11
- package/departments/ecom/skills/product-launch/SKILL.md +3 -11
- package/departments/ecom/skills/rfm-segment/SKILL.md +3 -11
- package/departments/ecom/skills/social-commerce/SKILL.md +3 -11
- package/departments/ecom/skills/store-audit/SKILL.md +3 -11
- package/departments/ecom/skills/subscription-model/SKILL.md +3 -11
- package/departments/finance/SKILL.md +4 -12
- package/departments/finance/skills/budget-plan/SKILL.md +3 -11
- package/departments/finance/skills/cashflow-forecast/SKILL.md +3 -11
- package/departments/finance/skills/ciso-advisor/SKILL.md +3 -11
- package/departments/finance/skills/financial-model/SKILL.md +3 -11
- package/departments/finance/skills/pitch-deck/SKILL.md +3 -11
- package/departments/finance/skills/scenario-analysis/SKILL.md +3 -11
- package/departments/finance/skills/unit-economics/SKILL.md +3 -11
- package/departments/finance/skills/valuation-model/SKILL.md +3 -11
- package/departments/kb/SKILL.md +4 -12
- package/departments/kb/skills/ai-research/SKILL.md +3 -11
- package/departments/kb/skills/competitive-intel/SKILL.md +3 -11
- package/departments/kb/skills/knowledge-review/SKILL.md +3 -11
- package/departments/kb/skills/learn-content/SKILL.md +3 -11
- package/departments/kb/skills/moc-create/SKILL.md +3 -11
- package/departments/kb/skills/persona-build/SKILL.md +3 -11
- package/departments/kb/skills/research-plan/SKILL.md +3 -11
- package/departments/kb/skills/search-kb/SKILL.md +3 -11
- package/departments/kb/skills/source-evaluate/SKILL.md +3 -11
- package/departments/kb/skills/taxonomy-manage/SKILL.md +3 -11
- package/departments/kb/skills/write-as-persona/SKILL.md +3 -11
- package/departments/landing/SKILL.md +4 -12
- package/departments/landing/skills/ab-test/SKILL.md +3 -11
- package/departments/landing/skills/affiliate-bridge/SKILL.md +3 -11
- package/departments/landing/skills/awareness-diagnose/SKILL.md +3 -11
- package/departments/landing/skills/copy-framework/SKILL.md +1 -1
- package/departments/landing/skills/email-sequence/SKILL.md +3 -11
- package/departments/landing/skills/funnel-metrics/SKILL.md +3 -11
- package/departments/landing/skills/headline-write/SKILL.md +3 -11
- package/departments/landing/skills/launch-sequence/SKILL.md +3 -11
- package/departments/landing/skills/offer-create/SKILL.md +3 -11
- package/departments/landing/skills/optimize-page/SKILL.md +3 -11
- package/departments/landing/skills/page-architect/SKILL.md +3 -11
- package/departments/landing/skills/persuasion-apply/SKILL.md +3 -11
- package/departments/landing/skills/webinar-funnel/SKILL.md +3 -11
- package/departments/leadership/SKILL.md +4 -12
- package/departments/leadership/skills/change-manage/SKILL.md +3 -11
- package/departments/leadership/skills/conflict-resolve/SKILL.md +3 -11
- package/departments/leadership/skills/culture-audit/SKILL.md +3 -11
- package/departments/leadership/skills/delegation-matrix/SKILL.md +3 -11
- package/departments/leadership/skills/disc-assess/SKILL.md +3 -11
- package/departments/leadership/skills/feedback-give/SKILL.md +3 -11
- package/departments/leadership/skills/hiring-plan/SKILL.md +3 -11
- package/departments/leadership/skills/performance-review/SKILL.md +3 -11
- package/departments/marketing/SKILL.md +4 -12
- package/departments/marketing/skills/ab-test/SKILL.md +3 -11
- package/departments/marketing/skills/analytics-report/SKILL.md +3 -11
- package/departments/marketing/skills/audience-segment/SKILL.md +3 -11
- package/departments/marketing/skills/calendar-plan/SKILL.md +3 -11
- package/departments/marketing/skills/competitor-analysis/SKILL.md +3 -11
- package/departments/marketing/skills/content-audit/SKILL.md +3 -11
- package/departments/marketing/skills/email-sequence/SKILL.md +3 -11
- package/departments/marketing/skills/growth-loop/SKILL.md +15 -13
- package/departments/marketing/skills/marketing-automation/SKILL.md +3 -11
- package/departments/marketing/skills/paid-campaign/SKILL.md +3 -11
- package/departments/marketing/skills/programmatic-seo/SKILL.md +3 -11
- package/departments/marketing/skills/seo-audit/SKILL.md +3 -11
- package/departments/marketing/skills/social-strategy/SKILL.md +3 -11
- package/departments/ops/SKILL.md +4 -12
- package/departments/ops/skills/bottleneck-find/SKILL.md +3 -11
- package/departments/ops/skills/dashboard-build/SKILL.md +3 -11
- package/departments/ops/skills/gdpr-compliance/SKILL.md +3 -11
- package/departments/ops/skills/gtd-setup/SKILL.md +3 -11
- package/departments/ops/skills/integration-design/SKILL.md +3 -11
- package/departments/ops/skills/iso27001/SKILL.md +3 -11
- package/departments/ops/skills/lean-audit/SKILL.md +3 -11
- package/departments/ops/skills/metrics-dashboard/SKILL.md +3 -11
- package/departments/ops/skills/n8n-flow/SKILL.md +3 -11
- package/departments/ops/skills/quality-management/SKILL.md +3 -11
- package/departments/ops/skills/risk-management/SKILL.md +3 -11
- package/departments/ops/skills/soc2-compliance/SKILL.md +3 -11
- package/departments/ops/skills/sop-create/SKILL.md +3 -11
- package/departments/ops/skills/workflow-automate/SKILL.md +3 -11
- package/departments/ops/skills/zapier-flow/SKILL.md +3 -11
- package/departments/org/SKILL.md +4 -12
- package/departments/org/skills/compensation-plan/SKILL.md +3 -11
- package/departments/org/skills/culture-define/SKILL.md +3 -11
- package/departments/org/skills/decision-framework/SKILL.md +3 -11
- package/departments/org/skills/hiring-plan/SKILL.md +3 -11
- package/departments/org/skills/meeting-optimize/SKILL.md +3 -11
- package/departments/org/skills/onboarding-design/SKILL.md +3 -11
- package/departments/org/skills/org-design/SKILL.md +3 -11
- package/departments/org/skills/remote-setup/SKILL.md +3 -11
- package/departments/org/skills/sop-process/SKILL.md +3 -11
- package/departments/org/skills/team-assess/SKILL.md +3 -11
- package/departments/pm/SKILL.md +4 -12
- package/departments/pm/skills/backlog-groom/SKILL.md +3 -11
- package/departments/pm/skills/discovery-plan/SKILL.md +3 -11
- package/departments/pm/skills/estimate-forecast/SKILL.md +3 -11
- package/departments/pm/skills/impact-map/SKILL.md +3 -11
- package/departments/pm/skills/kanban-setup/SKILL.md +3 -11
- package/departments/pm/skills/risk-register/SKILL.md +3 -11
- package/departments/pm/skills/roadmap-build/SKILL.md +3 -11
- package/departments/pm/skills/sprint-plan/SKILL.md +3 -11
- package/departments/pm/skills/stakeholder-map/SKILL.md +3 -11
- package/departments/pm/skills/standup-run/SKILL.md +3 -11
- package/departments/pm/skills/story-write/SKILL.md +3 -11
- package/departments/quality/agents/copy-director.yaml +10 -4
- package/departments/saas/SKILL.md +4 -12
- package/departments/saas/skills/benchmark-compare/SKILL.md +3 -11
- package/departments/saas/skills/churn-analysis/SKILL.md +3 -11
- package/departments/saas/skills/customer-success/SKILL.md +3 -11
- package/departments/saas/skills/growth-plan/SKILL.md +13 -12
- package/departments/saas/skills/gtm-strategy/SKILL.md +3 -11
- package/departments/saas/skills/launch-execute/SKILL.md +3 -11
- package/departments/saas/skills/metrics-dashboard/SKILL.md +3 -11
- package/departments/saas/skills/micro-saas-stack/SKILL.md +3 -11
- package/departments/saas/skills/mvp-build/SKILL.md +3 -11
- package/departments/saas/skills/niche-evaluate/SKILL.md +13 -12
- package/departments/saas/skills/onboarding-optimize/SKILL.md +3 -11
- package/departments/saas/skills/plg-setup/SKILL.md +3 -11
- package/departments/saas/skills/pricing-strategy/SKILL.md +3 -11
- package/departments/saas/skills/validate-idea/SKILL.md +13 -13
- package/departments/sales/SKILL.md +4 -12
- package/departments/sales/skills/challenger-sell/SKILL.md +3 -11
- package/departments/sales/skills/deal-qualify/SKILL.md +3 -11
- package/departments/sales/skills/discovery-call/SKILL.md +3 -11
- package/departments/sales/skills/forecast-revenue/SKILL.md +3 -11
- package/departments/sales/skills/negotiate-plan/SKILL.md +3 -11
- package/departments/sales/skills/objection-handle/SKILL.md +3 -11
- package/departments/sales/skills/pipeline-manage/SKILL.md +3 -11
- package/departments/sales/skills/pricing-negotiate/SKILL.md +3 -11
- package/departments/strategy/SKILL.md +4 -12
- package/departments/strategy/skills/blue-ocean/SKILL.md +3 -11
- package/departments/strategy/skills/bmc/SKILL.md +3 -11
- package/departments/strategy/skills/board-advisor/SKILL.md +3 -11
- package/departments/strategy/skills/cto-advisor/SKILL.md +3 -11
- package/departments/strategy/skills/extract-data/SKILL.md +3 -11
- package/departments/strategy/skills/five-forces/SKILL.md +3 -11
- package/departments/strategy/skills/growth-strategy/SKILL.md +15 -14
- package/departments/strategy/skills/moat-analysis/SKILL.md +3 -11
- package/departments/strategy/skills/position/SKILL.md +3 -11
- package/departments/strategy/skills/scenario-plan/SKILL.md +3 -11
- package/knowledge/commands-registry.json +3006 -1676
- package/knowledge/commands-registry.json.bak +4121 -0
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/scripts/__pycache__/migrate_skills_kb_first.cpython-313.pyc +0 -0
- package/scripts/__pycache__/synapse-bridge.cpython-314.pyc +0 -0
- package/scripts/migrate_skills_kb_first.py +41 -21
- package/scripts/tools/__pycache__/prompt_lint.cpython-313.pyc +0 -0
- package/scripts/tools/prompt_lint.py +276 -0
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
"""Idempotent migration: inject KB-first prefix
|
|
1
|
+
"""Idempotent migration: inject/compact the KB-first prefix in SKILL.md.
|
|
2
2
|
|
|
3
3
|
Targets SKILL.md files in arka/ and departments/ that reference external
|
|
4
4
|
research tools (Context7, WebSearch, WebFetch, Firecrawl). Each file gets
|
|
5
5
|
a standard KB-first block prepended after its frontmatter or H1, wrapped
|
|
6
6
|
in HTML-comment delimiters so re-runs are no-ops.
|
|
7
|
+
|
|
8
|
+
PR-3 of the prompt-surface plan (2026-07-08): the block is now a 2-line
|
|
9
|
+
POINTER instead of the full ~90-word doctrine — the doctrine lives once
|
|
10
|
+
in arka/SKILL.md (orchestrator) and is enforced by the Stop-hook kb-cite
|
|
11
|
+
check; cloning it into ~200 skills cost tokens on every co-loaded skill
|
|
12
|
+
and drifted on every edit. Re-running this script REPLACES any old-form
|
|
13
|
+
block with the compact one (delimiters preserved so marketplace_export
|
|
14
|
+
keeps stripping it).
|
|
7
15
|
"""
|
|
8
16
|
|
|
9
17
|
from __future__ import annotations
|
|
@@ -17,6 +25,9 @@ REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
|
17
25
|
|
|
18
26
|
SCAN_ROOTS = [REPO_ROOT / "arka", REPO_ROOT / "departments"]
|
|
19
27
|
SKIP_ROOTS = [REPO_ROOT / "docs", REPO_ROOT / "config" / "cognition"]
|
|
28
|
+
# The orchestrator SKILL.md is the canonical HOME of the KB-first
|
|
29
|
+
# doctrine (the compact pointers reference it) — never inject/compact it.
|
|
30
|
+
EXCLUDE_FILES = {REPO_ROOT / "arka" / "SKILL.md"}
|
|
20
31
|
|
|
21
32
|
EXTERNAL_TOOL_RE = re.compile(
|
|
22
33
|
r"mcp__context7|WebSearch|WebFetch|firecrawl",
|
|
@@ -26,21 +37,21 @@ EXTERNAL_TOOL_RE = re.compile(
|
|
|
26
37
|
BEGIN_DELIM = "<!-- arka:kb-first-prefix begin -->"
|
|
27
38
|
END_DELIM = "<!-- arka:kb-first-prefix end -->"
|
|
28
39
|
|
|
40
|
+
# No "(non-negotiable)" marker in the pointer: the normative force lives
|
|
41
|
+
# once in the canonical doctrine; repeating the marker ~200x is exactly
|
|
42
|
+
# the instruction-strength inflation the prompt-lint ratchet blocks.
|
|
29
43
|
PREFIX_BLOCK = f"""{BEGIN_DELIM}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
1. Call `mcp__obsidian__search_notes` on the query first.
|
|
35
|
-
2. Cite relevant hits with `[[wikilinks]]` or explicitly declare a KB gap.
|
|
36
|
-
3. Only after (1) and (2) may external tools run.
|
|
37
|
-
|
|
38
|
-
The Synapse L2.5 layer pre-injects top KB matches on every user prompt;
|
|
39
|
-
treat them as your default source. External research supplements, it
|
|
40
|
-
does not replace the vault.
|
|
44
|
+
> **KB-first:** query `mcp__obsidian__search_notes` and cite
|
|
45
|
+
> `[[wikilinks]]` — or declare the gap — BEFORE any external research.
|
|
46
|
+
> Full doctrine: `arka/SKILL.md` (KB-First Research).
|
|
41
47
|
{END_DELIM}
|
|
42
48
|
"""
|
|
43
49
|
|
|
50
|
+
_BLOCK_RE = re.compile(
|
|
51
|
+
re.escape(BEGIN_DELIM) + r".*?" + re.escape(END_DELIM) + r"\n?",
|
|
52
|
+
re.DOTALL,
|
|
53
|
+
)
|
|
54
|
+
|
|
44
55
|
|
|
45
56
|
@dataclass
|
|
46
57
|
class FileResult:
|
|
@@ -55,7 +66,7 @@ def _discover_skill_files() -> list[Path]:
|
|
|
55
66
|
if not root.exists():
|
|
56
67
|
continue
|
|
57
68
|
files.extend(root.rglob("SKILL.md"))
|
|
58
|
-
return sorted(set(files))
|
|
69
|
+
return sorted(set(files) - EXCLUDE_FILES)
|
|
59
70
|
|
|
60
71
|
|
|
61
72
|
def _references_external_tool(text: str) -> bool:
|
|
@@ -86,17 +97,23 @@ def _process_one(path: Path) -> FileResult:
|
|
|
86
97
|
except OSError as exc:
|
|
87
98
|
return FileResult(path, "error", str(exc))
|
|
88
99
|
|
|
100
|
+
if _already_migrated(text):
|
|
101
|
+
new_text = _BLOCK_RE.sub(PREFIX_BLOCK, text, count=1)
|
|
102
|
+
if new_text == text:
|
|
103
|
+
return FileResult(path, "skipped-already-compact")
|
|
104
|
+
return _write(path, new_text, "compacted")
|
|
105
|
+
|
|
89
106
|
if not _references_external_tool(text):
|
|
90
107
|
return FileResult(path, "skipped-no-external-ref")
|
|
91
|
-
|
|
92
|
-
|
|
108
|
+
return _write(path, _inject(text), "migrated")
|
|
109
|
+
|
|
93
110
|
|
|
94
|
-
|
|
111
|
+
def _write(path: Path, text: str, status: str) -> FileResult:
|
|
95
112
|
try:
|
|
96
|
-
path.write_text(
|
|
113
|
+
path.write_text(text, encoding="utf-8")
|
|
97
114
|
except OSError as exc:
|
|
98
115
|
return FileResult(path, "error", str(exc))
|
|
99
|
-
return FileResult(path,
|
|
116
|
+
return FileResult(path, status)
|
|
100
117
|
|
|
101
118
|
|
|
102
119
|
def run(dry_run: bool = False) -> list[FileResult]:
|
|
@@ -105,10 +122,13 @@ def run(dry_run: bool = False) -> list[FileResult]:
|
|
|
105
122
|
for path in files:
|
|
106
123
|
if dry_run:
|
|
107
124
|
text = path.read_text(encoding="utf-8", errors="replace")
|
|
108
|
-
if
|
|
125
|
+
if _already_migrated(text):
|
|
126
|
+
if _BLOCK_RE.sub(PREFIX_BLOCK, text, count=1) == text:
|
|
127
|
+
results.append(FileResult(path, "skipped-already-compact"))
|
|
128
|
+
else:
|
|
129
|
+
results.append(FileResult(path, "would-compact"))
|
|
130
|
+
elif not _references_external_tool(text):
|
|
109
131
|
results.append(FileResult(path, "skipped-no-external-ref"))
|
|
110
|
-
elif _already_migrated(text):
|
|
111
|
-
results.append(FileResult(path, "skipped-already-migrated"))
|
|
112
132
|
else:
|
|
113
133
|
results.append(FileResult(path, "would-migrate"))
|
|
114
134
|
else:
|
|
Binary file
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"""Prompt-surface linter (PR-2 of the 2026-07-08 prompt-surface plan).
|
|
2
|
+
|
|
3
|
+
Locks the coherence invariants that PR-1 (#255) restored, so they cannot
|
|
4
|
+
silently regress. Each check mirrors a defect class found by the prompt
|
|
5
|
+
audit (Obsidian: "Projects/WizardingCode Internal/ArkaOS/Prompt Audit —
|
|
6
|
+
system_prompts_leaks 2026-07-08"):
|
|
7
|
+
|
|
8
|
+
1. model-policy single source — no "ALWAYS ... model: opus" restatements;
|
|
9
|
+
constitution `quality_gate.model_policy` is the only authority.
|
|
10
|
+
2. AI-cliche list sync — constitution `no-ai-cliches` items appear
|
|
11
|
+
verbatim in eduardo-copy.md and equal copy-director.yaml avoid_patterns.
|
|
12
|
+
3. trivial-bypass wording — the "imperative verb" drift may not return.
|
|
13
|
+
4. retired counts — hand-typed agent/skill counts stay out of
|
|
14
|
+
prompt surfaces (docs surfaces are covered by test_docs_consistency).
|
|
15
|
+
5. evidence-flow restatements — the full 4-gate block lives only in the
|
|
16
|
+
canonical spec + the runtime delivery surfaces.
|
|
17
|
+
6. [time:X] tag — the cache-buster stays dead.
|
|
18
|
+
7. NON-NEGOTIABLE ratchet — marker count may only go DOWN (the
|
|
19
|
+
constitution-compaction PR lowers the baseline; growth fails CI).
|
|
20
|
+
|
|
21
|
+
Run: ``python -m scripts.tools.prompt_lint`` (or via arka-py). Exit 0 =
|
|
22
|
+
clean; exit 1 = violations printed one per line as ``file: message``.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import re
|
|
28
|
+
import sys
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
|
|
31
|
+
_ROOT = Path(__file__).resolve().parents[2]
|
|
32
|
+
|
|
33
|
+
# Prompt surfaces governed by this linter (docs/wiki/README are covered by
|
|
34
|
+
# scripts/tools/docs_stats.py + test_docs_consistency.py).
|
|
35
|
+
_GOVERNED_GLOBS: tuple[str, ...] = (
|
|
36
|
+
"CLAUDE.md",
|
|
37
|
+
"arka/SKILL.md",
|
|
38
|
+
"arka/skills/*/SKILL.md",
|
|
39
|
+
"departments/*/SKILL.md",
|
|
40
|
+
"departments/*/agents/*.yaml",
|
|
41
|
+
"config/claude-agents/*.md",
|
|
42
|
+
"config/constitution.yaml",
|
|
43
|
+
"config/hooks/*.sh",
|
|
44
|
+
"config/hooks/*.ps1",
|
|
45
|
+
"core/hooks/*.py",
|
|
46
|
+
"core/synapse/*.py",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Decoupled proximity (QG B1): any restatement with up to 40 chars between
|
|
50
|
+
# ALWAYS and the model pin ("reviewers ALWAYS run on model: opus").
|
|
51
|
+
_MODEL_POLICY_RE = re.compile(
|
|
52
|
+
r"ALWAYS\b[^\n]{0,40}?`?model:\s*opus`?", re.IGNORECASE
|
|
53
|
+
)
|
|
54
|
+
# Digit-anchored (QG B3): '165 agents' / '1190 skills' are legitimate
|
|
55
|
+
# future counts and must NOT be caught by the '65 agents' substring.
|
|
56
|
+
_RETIRED_COUNT_RES: tuple[re.Pattern[str], ...] = tuple(
|
|
57
|
+
re.compile(rf"(?<!\d){re.escape(bad)}\b")
|
|
58
|
+
for bad in (
|
|
59
|
+
"65 agents", "106 agents", "56 agents", "244+ skills", "190 skills",
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
_GATE_TOKENS: tuple[str, ...] = ("G1 CONTEXT", "G2 PLAN", "G3 EXECUTE", "G4 REVIEW")
|
|
63
|
+
# Canonical spec + the constitutional codification + runtime delivery
|
|
64
|
+
# surfaces (SessionStart systemMessage, per-turn [ARKA:WORKFLOW-REQUIRED])
|
|
65
|
+
# — the ONLY places the full block lives.
|
|
66
|
+
_GATE_BLOCK_ALLOWED: frozenset[str] = frozenset({
|
|
67
|
+
"arka/skills/flow/SKILL.md",
|
|
68
|
+
"config/constitution.yaml",
|
|
69
|
+
"config/hooks/session-start.sh",
|
|
70
|
+
"config/hooks/session-start.ps1",
|
|
71
|
+
"core/hooks/user_prompt_submit.py",
|
|
72
|
+
})
|
|
73
|
+
# Ratchet: CASE-INSENSITIVE count across the governed globs (QG M5: a
|
|
74
|
+
# lowercase "non-negotiable" in prose dilutes instruction strength
|
|
75
|
+
# exactly like the shouted marker). May only DECREASE, with ZERO slack —
|
|
76
|
+
# the baseline equals the measured count so adding a single marker fails
|
|
77
|
+
# CI. History: 47 after PR-1 (#255); 28 after PR-3's KB-first pointer
|
|
78
|
+
# compaction (#257); 17 after Constitution 2.0 (PR-5) demoted 20 rules
|
|
79
|
+
# and realigned stale markers with the new levels. Never raise it to
|
|
80
|
+
# make CI pass; remove a marker instead.
|
|
81
|
+
_NON_NEGOTIABLE_BASELINE = 17
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _governed_files(root: Path) -> list[Path]:
|
|
85
|
+
files: list[Path] = []
|
|
86
|
+
for pattern in _GOVERNED_GLOBS:
|
|
87
|
+
files.extend(sorted(root.glob(pattern)))
|
|
88
|
+
return [f for f in files if f.is_file()]
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _read(path: Path) -> str:
|
|
92
|
+
return path.read_text(encoding="utf-8", errors="replace")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _rel(root: Path, path: Path) -> str:
|
|
96
|
+
return str(path.relative_to(root))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def check_model_policy_single_source(root: Path) -> list[str]:
|
|
100
|
+
"""No surface may restate the QG model policy as 'ALWAYS ... opus'."""
|
|
101
|
+
violations: list[str] = []
|
|
102
|
+
for path in _governed_files(root):
|
|
103
|
+
if _MODEL_POLICY_RE.search(_read(path)):
|
|
104
|
+
violations.append(
|
|
105
|
+
f"{_rel(root, path)}: restates QG model policy — reference "
|
|
106
|
+
"constitution `quality_gate.model_policy` instead"
|
|
107
|
+
)
|
|
108
|
+
return violations
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def canonical_cliche_list(root: Path) -> list[str]:
|
|
112
|
+
"""Extract the canonical AI-cliche items from constitution no-ai-cliches."""
|
|
113
|
+
text = _read(root / "config" / "constitution.yaml")
|
|
114
|
+
match = re.search(r"Zero AI cliches:\s*(.+)", text)
|
|
115
|
+
if not match:
|
|
116
|
+
return []
|
|
117
|
+
return re.findall(r"'([^']+(?:'[^',]*)?)'(?=[,\"]|$)", match.group(1))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def check_cliche_list_sync(root: Path) -> list[str]:
|
|
121
|
+
"""Eduardo + copy-director must carry the canonical cliche list verbatim."""
|
|
122
|
+
canonical = canonical_cliche_list(root)
|
|
123
|
+
violations: list[str] = []
|
|
124
|
+
if len(canonical) < 10:
|
|
125
|
+
return [
|
|
126
|
+
"config/constitution.yaml: no-ai-cliches list unparseable "
|
|
127
|
+
f"(got {len(canonical)} items) — keep the 'Zero AI cliches:' format"
|
|
128
|
+
]
|
|
129
|
+
eduardo = root / "config" / "claude-agents" / "eduardo-copy.md"
|
|
130
|
+
eduardo_text = _read(eduardo)
|
|
131
|
+
for item in canonical:
|
|
132
|
+
if f'"{item}"' not in eduardo_text:
|
|
133
|
+
violations.append(
|
|
134
|
+
f"{_rel(root, eduardo)}: missing canonical cliche {item!r}"
|
|
135
|
+
)
|
|
136
|
+
yaml_path = (
|
|
137
|
+
root / "departments" / "quality" / "agents" / "copy-director.yaml"
|
|
138
|
+
)
|
|
139
|
+
yaml_items = re.findall(r'^\s*-\s*"([^"]+)"\s*$', _read(yaml_path), re.M)
|
|
140
|
+
missing = [i for i in canonical if i not in yaml_items]
|
|
141
|
+
for item in missing:
|
|
142
|
+
violations.append(
|
|
143
|
+
f"{_rel(root, yaml_path)}: avoid_patterns missing canonical "
|
|
144
|
+
f"cliche {item!r}"
|
|
145
|
+
)
|
|
146
|
+
return violations
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def check_trivial_bypass_wording(root: Path) -> list[str]:
|
|
150
|
+
"""The '[arka:trivial] + imperative verb' drift may not return."""
|
|
151
|
+
violations: list[str] = []
|
|
152
|
+
for path in _governed_files(root):
|
|
153
|
+
text = _read(path)
|
|
154
|
+
if "imperative verb" in text and "arka:trivial" in text:
|
|
155
|
+
violations.append(
|
|
156
|
+
f"{_rel(root, path)}: trivial-bypass drift — canonical "
|
|
157
|
+
"wording is 'single-file edit under 10 lines' (no "
|
|
158
|
+
"imperative-verb clause; spec: arka/skills/flow/SKILL.md)"
|
|
159
|
+
)
|
|
160
|
+
return violations
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def check_retired_counts(root: Path) -> list[str]:
|
|
164
|
+
"""Hand-typed counts that drifted from docs_stats.py stay banned."""
|
|
165
|
+
violations: list[str] = []
|
|
166
|
+
for path in _governed_files(root):
|
|
167
|
+
text = _read(path)
|
|
168
|
+
for pattern in _RETIRED_COUNT_RES:
|
|
169
|
+
match = pattern.search(text)
|
|
170
|
+
if match:
|
|
171
|
+
violations.append(
|
|
172
|
+
f"{_rel(root, path)}: retired hand-typed count "
|
|
173
|
+
f"{match.group(0)!r} — counts come from "
|
|
174
|
+
"scripts/tools/docs_stats.py or are omitted"
|
|
175
|
+
)
|
|
176
|
+
return violations
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def check_evidence_flow_restatements(root: Path) -> list[str]:
|
|
180
|
+
"""The full 4-gate block lives only in canonical + delivery surfaces.
|
|
181
|
+
|
|
182
|
+
A one-line pointer summary naming the gates is allowed everywhere;
|
|
183
|
+
a RESTATEMENT is all four gate tokens each on its own line (block
|
|
184
|
+
form) or the detailed-block signature phrase.
|
|
185
|
+
"""
|
|
186
|
+
violations: list[str] = []
|
|
187
|
+
line_start = {
|
|
188
|
+
token: re.compile(rf"^[\s>*#-]*{re.escape(token)}", re.M)
|
|
189
|
+
for token in _GATE_TOKENS
|
|
190
|
+
}
|
|
191
|
+
for path in _governed_files(root):
|
|
192
|
+
rel = _rel(root, path)
|
|
193
|
+
if rel in _GATE_BLOCK_ALLOWED:
|
|
194
|
+
continue
|
|
195
|
+
text = _read(path)
|
|
196
|
+
block_hits = sum(1 for rx in line_start.values() if rx.search(text))
|
|
197
|
+
signature = "silence is not approval" in text.lower()
|
|
198
|
+
if block_hits >= 3 or signature:
|
|
199
|
+
detail = (
|
|
200
|
+
f"{block_hits}/4 gate tokens in block form"
|
|
201
|
+
if block_hits >= 3
|
|
202
|
+
else "detailed-block signature phrase"
|
|
203
|
+
)
|
|
204
|
+
violations.append(
|
|
205
|
+
f"{rel}: 4-gate restatement ({detail}) — reduce to a "
|
|
206
|
+
"pointer at arka/skills/flow/SKILL.md"
|
|
207
|
+
)
|
|
208
|
+
return violations
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def check_time_tag_absence(root: Path) -> list[str]:
|
|
212
|
+
"""The time-of-day per-turn cache-buster stays removed.
|
|
213
|
+
|
|
214
|
+
Value-independent (QG B2): [time:night] or [time:noon] busts the
|
|
215
|
+
prompt cache exactly like the original three values did.
|
|
216
|
+
"""
|
|
217
|
+
violations: list[str] = []
|
|
218
|
+
pattern = re.compile(r"\[time:[^\]]+\]")
|
|
219
|
+
for path in _governed_files(root):
|
|
220
|
+
if pattern.search(_read(path)):
|
|
221
|
+
violations.append(
|
|
222
|
+
f"{_rel(root, path)}: time-of-day tag reintroduced — it is a "
|
|
223
|
+
"prompt-cache buster with no consumer rule (removed in #255)"
|
|
224
|
+
)
|
|
225
|
+
return violations
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def check_non_negotiable_ratchet(root: Path) -> list[str]:
|
|
229
|
+
"""NON-NEGOTIABLE marker count may only decrease from the baseline."""
|
|
230
|
+
marker = re.compile(r"NON-NEGOTIABLE", re.IGNORECASE)
|
|
231
|
+
total = sum(
|
|
232
|
+
len(marker.findall(_read(path))) for path in _governed_files(root)
|
|
233
|
+
)
|
|
234
|
+
if total > _NON_NEGOTIABLE_BASELINE:
|
|
235
|
+
return [
|
|
236
|
+
f"prompt surface: {total} NON-NEGOTIABLE markers > baseline "
|
|
237
|
+
f"{_NON_NEGOTIABLE_BASELINE} — inflation dilutes instruction "
|
|
238
|
+
"strength; demote to MUST/SHOULD or remove a marker (never "
|
|
239
|
+
"raise the baseline)"
|
|
240
|
+
]
|
|
241
|
+
return []
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
_ALL_CHECKS = (
|
|
245
|
+
check_model_policy_single_source,
|
|
246
|
+
check_cliche_list_sync,
|
|
247
|
+
check_trivial_bypass_wording,
|
|
248
|
+
check_retired_counts,
|
|
249
|
+
check_evidence_flow_restatements,
|
|
250
|
+
check_time_tag_absence,
|
|
251
|
+
check_non_negotiable_ratchet,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def run_all(root: Path | None = None) -> list[str]:
|
|
256
|
+
"""Run every check; returns the flat list of violations."""
|
|
257
|
+
base = root or _ROOT
|
|
258
|
+
violations: list[str] = []
|
|
259
|
+
for check in _ALL_CHECKS:
|
|
260
|
+
violations.extend(check(base))
|
|
261
|
+
return violations
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def main() -> int:
|
|
265
|
+
violations = run_all()
|
|
266
|
+
for violation in violations:
|
|
267
|
+
print(violation)
|
|
268
|
+
if violations:
|
|
269
|
+
print(f"\nprompt-lint: {len(violations)} violation(s)")
|
|
270
|
+
return 1
|
|
271
|
+
print("prompt-lint: clean")
|
|
272
|
+
return 0
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
if __name__ == "__main__":
|
|
276
|
+
sys.exit(main())
|