aiwg 2026.10.7 → 2026.10.8

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.
Files changed (81) hide show
  1. package/agentic/code/plugins/agent-loop/.claude-plugin/plugin.json +1 -1
  2. package/agentic/code/plugins/agent-persistence/.claude-plugin/plugin.json +1 -1
  3. package/agentic/code/plugins/agentic-installer/.claude-plugin/plugin.json +1 -1
  4. package/agentic/code/plugins/aiwg-dev/.claude-plugin/plugin.json +1 -1
  5. package/agentic/code/plugins/aiwg-evals/.claude-plugin/plugin.json +1 -1
  6. package/agentic/code/plugins/auto-memory/.claude-plugin/plugin.json +1 -1
  7. package/agentic/code/plugins/browser-control/.claude-plugin/plugin.json +1 -1
  8. package/agentic/code/plugins/color-palette/.claude-plugin/plugin.json +1 -1
  9. package/agentic/code/plugins/compound-memory/.claude-plugin/plugin.json +1 -1
  10. package/agentic/code/plugins/context-curator/.claude-plugin/plugin.json +1 -1
  11. package/agentic/code/plugins/daemon/.claude-plugin/plugin.json +1 -1
  12. package/agentic/code/plugins/doc-intelligence/.claude-plugin/plugin.json +1 -1
  13. package/agentic/code/plugins/droid-bridge/.claude-plugin/plugin.json +1 -1
  14. package/agentic/code/plugins/forensics/.claude-plugin/plugin.json +1 -1
  15. package/agentic/code/plugins/guided-implementation/.claude-plugin/plugin.json +1 -1
  16. package/agentic/code/plugins/hooks/.claude-plugin/plugin.json +1 -1
  17. package/agentic/code/plugins/knowledge-base/.claude-plugin/plugin.json +1 -1
  18. package/agentic/code/plugins/line-memory/.claude-plugin/plugin.json +1 -1
  19. package/agentic/code/plugins/llm-wiki/.claude-plugin/plugin.json +1 -1
  20. package/agentic/code/plugins/marketing/.claude-plugin/plugin.json +1 -1
  21. package/agentic/code/plugins/media-curator/.claude-plugin/plugin.json +1 -1
  22. package/agentic/code/plugins/nlp-prod/.claude-plugin/plugin.json +1 -1
  23. package/agentic/code/plugins/ops/.claude-plugin/plugin.json +1 -1
  24. package/agentic/code/plugins/prose-integration/.claude-plugin/plugin.json +1 -1
  25. package/agentic/code/plugins/research/.claude-plugin/plugin.json +1 -1
  26. package/agentic/code/plugins/rlm/.claude-plugin/plugin.json +1 -1
  27. package/agentic/code/plugins/sdlc/.claude-plugin/plugin.json +1 -1
  28. package/agentic/code/plugins/security-engineering/.claude-plugin/plugin.json +1 -1
  29. package/agentic/code/plugins/semantic-memory/.claude-plugin/plugin.json +1 -1
  30. package/agentic/code/plugins/skill-factory/.claude-plugin/plugin.json +1 -1
  31. package/agentic/code/plugins/star-prompt/.claude-plugin/plugin.json +1 -1
  32. package/agentic/code/plugins/testing-quality/.claude-plugin/plugin.json +1 -1
  33. package/agentic/code/plugins/twelve-factor/.claude-plugin/plugin.json +1 -1
  34. package/agentic/code/plugins/uat-mcp/.claude-plugin/plugin.json +1 -1
  35. package/agentic/code/plugins/utils/.claude-plugin/plugin.json +1 -1
  36. package/agentic/code/plugins/validation-complete/.claude-plugin/plugin.json +1 -1
  37. package/agentic/code/plugins/verbalized-sampling/.claude-plugin/plugin.json +1 -1
  38. package/agentic/code/plugins/voice/.claude-plugin/plugin.json +1 -1
  39. package/agentic/code/plugins/writing/.claude-plugin/plugin.json +1 -1
  40. package/dist/src/cli/handlers/cost-report.js +7 -1
  41. package/dist/src/cli/handlers/decision.js +33 -8
  42. package/dist/src/cli/handlers/local-executor.js +33 -6
  43. package/dist/src/cost/fleet-report.js +20 -22
  44. package/dist/src/decision/driver.d.ts +2 -2
  45. package/dist/src/decision/driver.js +2 -2
  46. package/dist/src/decision/egress-live-qualification.d.ts +2 -2
  47. package/dist/src/decision/jev-credentials.js +18 -5
  48. package/dist/src/decision/ledger.d.ts +31 -10
  49. package/dist/src/decision/ledger.js +230 -34
  50. package/dist/src/mcp/cli.mjs +105 -19
  51. package/dist/src/mcp/credentials.d.mts +4 -0
  52. package/dist/src/mcp/credentials.mjs +44 -3
  53. package/dist/src/mcp/grok-build-config.mjs +2 -0
  54. package/dist/src/mcp/omp-config.mjs +2 -0
  55. package/dist/src/mcp/registry.js +19 -15
  56. package/dist/src/mcp/registry.mjs +2 -18
  57. package/dist/src/mcp/tools/agentic-sandbox.mjs +46 -28
  58. package/dist/src/models/grok-build-models.js +20 -0
  59. package/dist/src/providers/provider-definitions.js +2 -2
  60. package/dist/src/serve/shared-host-scheduler.js +4 -1
  61. package/dist/src/storage/backends/fortemi.js +107 -49
  62. package/docs/_manifest.json +8 -0
  63. package/docs/agents/providers/grok-build.md +11 -0
  64. package/docs/cli/reference.md +65 -13
  65. package/docs/cli/sensitive-values.md +67 -9
  66. package/docs/decision/jev-quickstart.md +70 -20
  67. package/docs/guides/openrouter-fleet-costs.md +4 -2
  68. package/docs/mcp/README.md +19 -1
  69. package/docs/providers/grok-build-direct.md +17 -11
  70. package/docs/providers/grok-build-models.md +10 -0
  71. package/docs/providers/grok-build-qualification.json +7 -2
  72. package/docs/providers/grok-build-qualification.md +12 -2
  73. package/docs/releases/_manifest.json +1 -0
  74. package/docs/releases/v2026.10.8-announcement.md +174 -0
  75. package/package.json +1 -1
  76. package/prebuilt/fortemi-core/framework/aiwg-fortemi-index-v2.json +1 -1
  77. package/prebuilt/fortemi-core/framework/manifest.json +5 -5
  78. package/prebuilt/fortemi-core/framework/source-stats.json +1 -1
  79. package/prebuilt/framework-relations/manifest.json +3 -3
  80. package/prebuilt/framework-relations/relations.json +1 -1
  81. package/tools/ralph-external/executor-shim.mjs +50 -22
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-loop",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Iterative AI coding loops with automatic recovery - iteration beats perfection",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-persistence",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Human-in-the-loop (HITL) gate definitions for agent operations. Provides reusable YAML gates for destructive-action authorization, false-positive override, and recovery escalation. Loaded by agent loops and orchestrators that need bounded human checkpoints.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-installer",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Structured YAML manifests for reproducible, agent-driven software installation across platforms. Scripts are the primary artifact; agentic instructions handle adaptation and recovery.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiwg-dev",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Developer tooling for building AIWG itself and AIWG addons/frameworks. Not for end users — install explicitly with `aiwg use aiwg-dev`.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiwg-evals",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Automated evaluation framework for agent quality, based on KAMI benchmark methodology and ReAct patterns",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auto-memory",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Automatic memory seed templates for AIWG projects",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-control",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Drive a real, user-installed Chromium-derived browser from an AIWG agent. Wraps @playwright/mcp with a setup wizard, health-check doctor, allow-list enforcement, and an opinionated agent persona that respects authorization and audit boundaries.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "color-palette",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Color palette selection and review tooling with color theory fundamentals, current trend research, and accessibility analysis.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compound-memory",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Governed orchestration across AIWG line memory, semantic memory, and llm-wiki.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-curator",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Context curation and distractor filtering for production-grade agent reliability",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "daemon",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Persistent daemon session capabilities: Concierge front-end, session memory, scheduler integration",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doc-intelligence",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Documentation intelligence addon for scraping, extraction, analysis, and generated-docs auditing.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "droid-bridge",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "MCP server bridging Claude Code to Factory Droid for batch operations and automated fixes",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forensics",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Digital forensics and incident response framework with 14 specialized agents covering target profiling, evidence acquisition, log/memory/container/cloud analysis, IOC extraction, and reporting.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guided-implementation",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Bounded iteration control for autonomous issue-to-code implementation",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hooks",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Claude Code hooks for workflow tracing and observability.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knowledge-base",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Knowledge-base / wiki framework with skills for ingestion, query, and lint. Build a structured, citable corpus with cross-references and concept pages.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "line-memory",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Bounded, plain-text project memory with least-recently-used retention.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-wiki",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "LLM-maintained markdown wiki that compounds as sources are ingested. Thin topology declaration on the semantic memory kernel — ships schema profiles and page templates, no custom mechanics.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marketing",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Marketing automation framework with 37 specialized agents for campaign management.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "media-curator",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Media archive management framework with 7 specialized agents for source discovery, acquisition (yt-dlp / Internet Archive / Bandcamp), quality assessment, metadata tagging, and provenance tracking.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nlp-prod",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Tools, skills, and CLI extensions for designing and productionizing LLM inference pipelines. Pattern-guided, slim by default, eval-first.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ops",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Operational infrastructure framework with 12 specialized agents covering incident response, runbook execution, fleet inventory, certificate lifecycle, and disaster recovery planning.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prose-integration",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Tools for reading, parsing, validating, and executing OpenProse programs from AIWG workflows",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "research",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Research workflow framework with 9 specialized agents for discovery, acquisition, synthesis, citation management, GRADE quality assessment, and OAIS-compliant archival.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rlm",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "RLM-inspired recursive context decomposition for processing arbitrarily large codebases and document corpora through programmatic sub-agent delegation",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdlc",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Complete SDLC framework with 180+ specialized agents for software development lifecycle management.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "security-engineering",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Applied security framework for cryptographic primitive selection, chain-of-trust design, authentication factor analysis, supply-chain trust, and physical-threat modeling. Complements OWASP-style application audits.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "semantic-memory",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Topology-agnostic semantic memory operations: ingest, lint, query-capture, and structured event logging. Consumers declare a memory topology in their manifest.json; kernel skills read that contract to parameterize behavior.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skill-factory",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Build, enhance, validate, and package Claude skills end-to-end. Coordinates skill-builder, skill-enhancer, quality-checker, and skill-packager via the skill-architect agent.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "star-prompt",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Tasteful prompt to encourage users to star the repository after successful command completion",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testing-quality",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Evidence-bound test conformance, platform protocols, normalization transactions and research-guided testing workflows",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "twelve-factor",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Design-time and audit-time workflows for Twelve-Factor and modern 12+ Factor cloud-native application practices.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uat-mcp",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Agent-executable acceptance testing via MCP connections — generate, execute, and report on UAT plans that validate MCP tool surfaces.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "utils",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Core AIWG utilities for context regeneration and workspace management.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "validation-complete",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Validation Complete for AIWG",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "verbalized-sampling",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Training-free prompting technique that improves output diversity by 1.6-2.1x through verbalized probability distributions, addressing RLHF mode collapse",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "voice",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Voice profile system for consistent, authentic writing.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "writing",
3
- "version": "2026.10.7",
3
+ "version": "2026.10.8",
4
4
  "description": "Writing quality validation and AI pattern detection.",
5
5
  "author": {
6
6
  "name": "AIWG Contributors",
@@ -1,6 +1,7 @@
1
1
  /** OpenRouter fleet cost-report CLI handler. @issue #1187 */
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
+ import { sensitiveInputOptions } from '../../auth/sensitive-input.js';
4
5
  import { FleetConfigMissingError, formatFleetSpendReport, generateFleetSpendReport, } from '../../cost/fleet-report.js';
5
6
  function option(args, name) {
6
7
  const index = args.indexOf(name);
@@ -9,10 +10,11 @@ function option(args, name) {
9
10
  }
10
11
  function usage() {
11
12
  return [
12
- 'Usage: aiwg cost-report (--fleet | --key <key_ref>) [--source openrouter] [--config <fleet.yaml>] [--json]',
13
+ 'Usage: aiwg cost-report (--fleet | --key <key_ref> [--key-store <name>]) [--source openrouter] [--config <fleet.yaml>] [--json]',
13
14
  '',
14
15
  'Reads bot-to-key references from ~/.config/aiwg/fleet.yaml and credentials from',
15
16
  '~/.config/aiwg/keys/<key_ref> or AIWG_OPENROUTER_KEY_<KEY_REF>.',
17
+ 'Use --key-store <name> for one key, or per-entry key_store references in fleet YAML.',
16
18
  '',
17
19
  'AIWG observes and correlates spend; OpenRouter enforces all key limits and caps.',
18
20
  ].join('\n');
@@ -40,6 +42,9 @@ export const costReportHandler = {
40
42
  ? path.resolve(ctx.cwd, configuredPath)
41
43
  : path.join(os.homedir(), '.config', 'aiwg', 'fleet.yaml');
42
44
  try {
45
+ const keyStore = sensitiveInputOptions(ctx.args, 'key').store;
46
+ if (keyStore !== undefined && !keyRef)
47
+ return { exitCode: 2, message: '--key-store requires --key <key_ref>; use per-entry key_store references for --fleet.' };
43
48
  const capValue = option(ctx.args, '--monthly-cap');
44
49
  const cap = capValue === undefined ? 0 : Number(capValue);
45
50
  if (!Number.isFinite(cap) || cap < 0)
@@ -53,6 +58,7 @@ export const costReportHandler = {
53
58
  bot: option(ctx.args, '--bot') ?? keyRef,
54
59
  machine: option(ctx.args, '--machine') ?? os.hostname(),
55
60
  key_ref: keyRef,
61
+ ...(keyStore !== undefined ? { key_store: keyStore } : {}),
56
62
  monthly_cap: cap,
57
63
  }],
58
64
  } : {}),
@@ -1,12 +1,12 @@
1
1
  import { resolveSensitiveInput, sensitiveInputOptions } from '../../auth/sensitive-input.js';
2
2
  import { decisionPricing } from '../../decision/pricing.js';
3
- import { ATTRIBUTION_FIELD_PATTERN, DecisionAskUsageError, decisionCapabilities, DecisionLedgerSinceError, decisionLedgerHistory, decisionLedgerStats, evaluateRequestPath, listPatterns, livePlan, MAX_ATTRIBUTION_FIELD_LENGTH, materializeSyntheticClassificationSetup, parseDecisionLedgerSince, readDecisionContextFile, runDecisionOffloadCheckpoint, runOfflinePattern, setupJev, showPattern, syntheticClassificationSetup, validateDecisionInput, } from '../../decision/driver.js';
3
+ import { ATTRIBUTION_FIELD_PATTERN, DecisionAskUsageError, decisionCapabilities, DecisionLedgerSinceError, decisionLedgerHistory, decisionLedgerStats, rotateDecisionLedger, parseDecisionLedgerRetention, evaluateRequestPath, listPatterns, livePlan, MAX_ATTRIBUTION_FIELD_LENGTH, materializeSyntheticClassificationSetup, parseDecisionLedgerSince, readDecisionContextFile, runDecisionOffloadCheckpoint, runOfflinePattern, setupJev, showPattern, syntheticClassificationSetup, validateDecisionInput, } from '../../decision/driver.js';
4
4
  function jsonResult(value, exitCode = 0) {
5
5
  return { exitCode, message: JSON.stringify(value, null, 2), rawOutput: true };
6
6
  }
7
7
  function usage() {
8
8
  return [
9
- 'Usage: aiwg decision <capabilities|status|patterns|validate|evaluate|setup|history|stats|pricing> [options]',
9
+ 'Usage: aiwg decision <capabilities|status|patterns|validate|evaluate|setup|history|stats|rotate|pricing> [options]',
10
10
  ' aiwg decision ask --question "<q>" (--yes-no | --choices a,b,c | --scale 1-5) [--context <text> | --context-file <path> | --context-stdin] [--threshold 0.8] [--timeout-ms 15000] [--passes N] [--escalation-passes N] [--provider <id>] [--session <id>] [--caller <tag>] [--record-text] [--json]',
11
11
  '',
12
12
  'Commands:',
@@ -20,9 +20,10 @@ function usage() {
20
20
  ' setup synthetic-classification [--output-dir <dir>]',
21
21
  ' setup jev [--token-interactive | --token-stdin | --token-file <path> | --token-store <name> | --token-env <name>] [--region <r>] [--endpoint <url>] [--verify] [--remove]',
22
22
  ' ask --question "<q>" (--yes-no | --choices a,b,c | --scale 1-5) [--provider <id>] [--session <id>] [--caller <tag>] [--record-text]',
23
- ' history [--since <date>] [--provider <id>] [--session <id>] [--kind yes-no|choices|scale] [--status answered|fallback] [--caller <tag>|<prefix>* | --no-caller] [--json]',
23
+ ' history [--since <date>] [--provider <id>] [--session <id>] [--kind yes-no|choices|scale] [--status answered|fallback] [--caller <tag>|<prefix>* | --no-caller] [--include-archives] [--json]',
24
24
  ' pricing [--refresh --model jev-X.Y.Z] [--dry-run] [--offline | --allow-snapshot] [--json]',
25
- ' stats [--since <date>] [--provider <id>] [--session <id>] [--kind yes-no|choices|scale] [--status answered|fallback] [--caller <tag>|<prefix>* | --no-caller] [--group-by provider|session|kind|caller|passes|escalation] [--json]',
25
+ ' stats [--since <date>] [--provider <id>] [--session <id>] [--kind yes-no|choices|scale] [--status answered|fallback] [--caller <tag>|<prefix>* | --no-caller] [--group-by provider|session|kind|caller|passes|escalation] [--include-archives] [--json]',
26
+ ' rotate [--keep-last <Nd|N> | --all] [--to <path>] [--json]',
26
27
  '',
27
28
  'Notes:',
28
29
  ' Every COMPLETED `ask` call (CLI and MCP) appends one record to the decision',
@@ -42,9 +43,13 @@ function usage() {
42
43
  ` --session and --caller must match ${ATTRIBUTION_FIELD_PATTERN.source} (<= ${MAX_ATTRIBUTION_FIELD_LENGTH} characters).`,
43
44
  ' `history`/`stats` accept `--caller <tag>` (exact), `--caller \'<prefix>*\'` (prefix; the only wildcard), or `--no-caller` (records with no tag; not combinable with `--caller`).',
44
45
  ' `history`/`stats` reject unknown flags and positional arguments with exit 2.',
45
- ' The ledger has no built-in retention: it grows without bound and the',
46
- ' operator may truncate or delete it at any time; readers tolerate a missing',
47
- ' file. The ledger trusts only the local filesystem under the project',
46
+ ' `rotate` keeps the last 90 days by default; --keep-last accepts days or a',
47
+ ' positive count. Rotating everything requires --all. Malformed lines stay',
48
+ ' inline unless --all is used. Archives are private .jsonl files beneath',
49
+ ' archive/decision/ in the resolved artifact root; --to must stay there.',
50
+ ' `history`/`stats` optionally read archives with --include-archives, offline.',
51
+ ' Appenders, rotation and readers share one cross-process lock.',
52
+ ' The ledger trusts only the local filesystem under the project',
48
53
  ' artifact root, owned by the same user running aiwg — it is not a defense',
49
54
  ' against a hostile process already running as that user.',
50
55
  ].join('\n');
@@ -207,7 +212,7 @@ function parseGroupBy(value) {
207
212
  return value;
208
213
  }
209
214
  const HISTORY_VALUE_FLAGS = ['--since', '--provider', '--session', '--kind', '--status', '--caller'];
210
- const HISTORY_BOOL_FLAGS = ['--json', '--no-caller'];
215
+ const HISTORY_BOOL_FLAGS = ['--json', '--no-caller', '--include-archives'];
211
216
  const STATS_VALUE_FLAGS = [...HISTORY_VALUE_FLAGS, '--group-by'];
212
217
  const STATS_BOOL_FLAGS = HISTORY_BOOL_FLAGS;
213
218
  /**
@@ -269,6 +274,7 @@ function parseLedgerFilters(args) {
269
274
  kind: parseKindFilter(takeOption(args, '--kind')),
270
275
  status: parseStatusFilter(takeOption(args, '--status')),
271
276
  ...parseCallerFilter(args),
277
+ ...(args.includes('--include-archives') ? { includeArchives: true } : {}),
272
278
  };
273
279
  }
274
280
  /** One header line stating the caller filter, shown only when one is set. */
@@ -323,6 +329,23 @@ async function decisionStats(ctx) {
323
329
  ]);
324
330
  return { exitCode: 0, message: [...header, ...lines].join('\n'), rawOutput: true };
325
331
  }
332
+ async function decisionRotate(ctx) {
333
+ const args = ctx.args.slice(1);
334
+ assertLedgerArgs(args, ['--keep-last', '--to'], ['--all', '--json']);
335
+ const keepLast = args.includes('--keep-last') ? takeRequiredOption(args, '--keep-last') : undefined;
336
+ const all = args.includes('--all');
337
+ try {
338
+ parseDecisionLedgerRetention(keepLast, all);
339
+ }
340
+ catch (error) {
341
+ throw new DecisionAskUsageError('invalid-retention', error instanceof Error ? error.message : String(error));
342
+ }
343
+ const result = await rotateDecisionLedger({ projectRoot: ctx.cwd, keepLast, all,
344
+ to: args.includes('--to') ? takeRequiredOption(args, '--to') : undefined });
345
+ if (args.includes('--json'))
346
+ return jsonResult(result);
347
+ return { exitCode: 0, rawOutput: true, message: `Archived ${result.archived} line(s)${result.archivePath ? ` to ${result.archivePath}` : ''}; retained ${result.retained} line(s) inline (${result.malformed} malformed).` };
348
+ }
326
349
  async function executeDecision(ctx) {
327
350
  const [command, subcommand, ...rest] = ctx.args;
328
351
  const options = { cwd: ctx.cwd, frameworkRoot: ctx.frameworkRoot, env: process.env };
@@ -335,6 +358,8 @@ async function executeDecision(ctx) {
335
358
  return await decisionAsk(ctx);
336
359
  if (command === 'history')
337
360
  return await decisionHistory(ctx);
361
+ if (command === 'rotate')
362
+ return await decisionRotate(ctx);
338
363
  if (command === 'pricing') {
339
364
  const args = ctx.args.slice(1);
340
365
  assertLedgerArgs(args, ['--model'], ['--refresh', '--dry-run', '--offline', '--allow-snapshot', '--json']);
@@ -21,9 +21,22 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
21
21
  import { createHash, randomUUID } from 'crypto';
22
22
  import { pathToFileURL } from 'node:url';
23
23
  import { projectAiwgPath } from '../../config/project-artifacts.js';
24
+ import { resolveSensitiveInput, sensitiveInputOptions } from '../../auth/sensitive-input.js';
24
25
  const DEFAULT_PORT = 8200;
25
26
  const DEFAULT_BIND = '127.0.0.1';
26
27
  const DEFAULT_AIWG_SERVE = 'http://127.0.0.1:7337';
28
+ /** Optional input: no source keeps registration/cache behavior, even at a terminal. */
29
+ export async function resolveLocalExecutorToken(args, dependencies = {}) {
30
+ const source = sensitiveInputOptions(args, 'token');
31
+ const environment = dependencies.environment ?? process.env;
32
+ const explicit = source.interactive || source.stdin || source.file !== undefined || source.store !== undefined || source.env !== undefined;
33
+ if (!explicit) {
34
+ if (!environment.AIWG_EXECUTOR_TOKEN)
35
+ return undefined;
36
+ source.env = 'AIWG_EXECUTOR_TOKEN';
37
+ }
38
+ return resolveSensitiveInput(source, { ...dependencies, environment });
39
+ }
27
40
  /**
28
41
  * Resolve or generate-once the executor identity.
29
42
  * Written to `.aiwg/local-executor/identity.json` so restarts reuse the same
@@ -122,6 +135,14 @@ export const localExecutorServeHandler = {
122
135
  // The subcommand is: `aiwg local-executor serve [flags]`
123
136
  // ctx.args[0] === 'serve' (consumed by router) or flags directly
124
137
  const flagArgs = ctx.args[0] === 'serve' ? ctx.args.slice(1) : ctx.args;
138
+ let preexistingToken;
139
+ try {
140
+ preexistingToken = await resolveLocalExecutorToken(flagArgs);
141
+ }
142
+ catch (error) {
143
+ return { exitCode: 1, message: error.message };
144
+ }
145
+ const redact = (message) => preexistingToken ? message.split(preexistingToken).join('[REDACTED]') : message;
125
146
  const opts = parseLocalExecutorArgs(flagArgs);
126
147
  warnIfNonLoopback(opts.bind);
127
148
  // ── Dynamic imports (same pattern as serve.ts) ──────────────────────────
@@ -138,7 +159,7 @@ export const localExecutorServeHandler = {
138
159
  }
139
160
  catch (err) {
140
161
  return {
141
- message: `Failed to load executor-shim: ${err.message}`,
162
+ message: `Failed to load executor-shim: ${redact(err.message)}`,
142
163
  exitCode: 1,
143
164
  };
144
165
  }
@@ -148,7 +169,7 @@ export const localExecutorServeHandler = {
148
169
  }
149
170
  catch (err) {
150
171
  return {
151
- message: `Failed to load DaemonSupervisor: ${err.message}`,
172
+ message: `Failed to load DaemonSupervisor: ${redact(err.message)}`,
152
173
  exitCode: 1,
153
174
  };
154
175
  }
@@ -208,7 +229,7 @@ export const localExecutorServeHandler = {
208
229
  restBase,
209
230
  wsBase,
210
231
  aiwgServeUrl: opts.aiwgServe,
211
- token: process.env['AIWG_EXECUTOR_TOKEN'],
232
+ token: preexistingToken,
212
233
  tokenPath: projectAiwgPath(process.cwd(), 'local-executor', 'tokens', `${createHash('sha256').update(`${opts.aiwgServe}\0${opts.executorId}`).digest('hex')}.json`),
213
234
  });
214
235
  // Register with aiwg-serve
@@ -218,7 +239,7 @@ export const localExecutorServeHandler = {
218
239
  }
219
240
  catch (err) {
220
241
  return {
221
- message: `Failed to register with aiwg-serve at ${opts.aiwgServe}: ${err.message}\n` +
242
+ message: `Failed to register with aiwg-serve at ${opts.aiwgServe}: ${redact(err.message)}\n` +
222
243
  'Is aiwg serve running? Start it with: aiwg serve --no-open',
223
244
  exitCode: 1,
224
245
  };
@@ -235,7 +256,7 @@ export const localExecutorServeHandler = {
235
256
  catch (err) {
236
257
  await shim.deregister();
237
258
  return {
238
- message: `Failed to start executor server: ${err.message}`,
259
+ message: `Failed to start executor server: ${redact(err.message).split(token).join('[REDACTED]')}`,
239
260
  exitCode: 1,
240
261
  };
241
262
  }
@@ -304,9 +325,15 @@ export const localExecutorHandler = {
304
325
  ' --aiwg-serve <url> Registration target (default: http://127.0.0.1:7337)\n' +
305
326
  ' --max-concurrency <n> Max concurrent missions (default: 4)\n' +
306
327
  ' --executor-id <uuid> Override stable executor ID\n' +
328
+ ' --token-interactive Read optional existing bearer without echo\n' +
329
+ ' --token-stdin Read optional existing bearer from stdin\n' +
330
+ ' --token-file <path> Read optional existing bearer from a private file\n' +
331
+ ' --token-store <name> Read optional existing bearer from the OS store\n' +
332
+ ' --token-env <NAME> Read optional existing bearer from a named variable\n' +
307
333
  '\n' +
308
334
  'Environment:\n' +
309
- ' AIWG_SERVE_ENDPOINT Override --aiwg-serve default\n');
335
+ ' AIWG_SERVE_ENDPOINT Override --aiwg-serve default\n' +
336
+ ' AIWG_EXECUTOR_TOKEN Optional preexisting executor bearer\n');
310
337
  return { exitCode: 0 };
311
338
  }
312
339
  return {