Commit Graph

12 Commits

Author SHA1 Message Date
claude 700f59ef0d feat(kernel): gate the DoD against discovery scope (#699)
Session 954da1a9 asked for an eight-view web UI and shipped a Vite starter
page. Discovery settled all eight items in brief.scope; the analyst emitted
four criteria, all part="Project Foundation"; the architect planned against
that DoD, so the run scaffolded Vite, Tailwind and TanStack Query and stopped.
The plan-compile gate and the final reviewer both graded the shrunken DoD, so
a plan delivering 5% of the request passed clean.

Each DoD criterion now carries `covers`: the 0-based indexes into discovery
brief.scope it proves. A post-stage scope_coverage gate fails the analyst
retryably when an index has no criterion, handing back the dropped items
verbatim. Pure function of two recorded artifacts, so replay recomputes it and
no verdict event is needed.

Ceiling is index bookkeeping, not semantics: a criterion claiming covers:[3]
without really proving scope[3] still passes. It catches the silent collapse,
not a weak criterion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013dVqqci5H5b3s6xzv6Lojq
2026-08-11 20:17:17 +04:00
kami 516af1ca96 feat: tighten freestyle discovery and analyst handoff 2026-07-26 10:22:05 +04:00
kami 28d369ebce merge: integrate sonnet-vikunja (#299,#300,#297,#301) into codex handoff HEAD
# Conflicts:
#	core/kernel/src/main/kotlin/com/correx/core/kernel/orchestration/OrchestrationTuning.kt
#	examples/workflows/prompts/analyst_freestyle.md
2026-07-21 11:43:05 +04:00
kami 0af2f200d8 fix(prompts): resolve analyst epic-vs-child ambiguity that burned the full reasoning budget (#297)
Live incident: "Write a web-ui for Correx" resolved to a pre-existing parent
epic (webui-8, with children webui-9..14). The old prompt only said "name a
task that covers this work" and, separately, "after decomposing, name the
single ready child" — it never said what to do when an EXISTING task found
via task_search/task_context is itself a parent. The model oscillated
between naming the epic, re-decomposing, or working a child until it burned
all 16384 reasoning tokens and emitted nothing.

Reworded analyst_freestyle.md's task-framing section so every branch
(existing leaf, existing parent, no task yet + single unit, no task yet +
needs decomposition) converges on one rule: never name a parent/epic, always
name the single ready child — removing the decision entirely rather than
asking the model to make it under ambiguity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GeyGFXczJb8RUWGBKmkm6G
2026-07-21 02:05:20 +04:00
kami 1b58bc325e wip(freestyle/acr): grounding & edit-tool fixes + ACR-compiler experiment
This branch's uncommitted WIP, committed together (entangled at file level).
Distinct pieces of work:

Freestyle QA fixes (this session):
- FileEditTool: pre-validate replace anchor in validateRequest — reject a
  missing/ambiguous target BEFORE the approval gate, mirroring read/write's
  file-not-found / read-before-write pre-checks. Shared not-found/ambiguous
  messages between validate and execute so they can't drift.
- PlanGrounder: add `scanned` flag; when no RepoMapComputedEvent was recorded,
  repoMapPaths is "unknown" not "empty workspace" — skip scope grounding
  (which proves a path ABSENT) so real paths (apps/server/**) aren't falsely
  rejected. Build-manifest check still runs.
- FreestyleDriver: wire scanned=(repoMap!=null); on plan rejection emit a
  session-terminal WorkflowFailedEvent so a rejected run reads FAILED, not the
  COMPLETED-lie (last verdict was the planning-phase WorkflowCompleted).
- ServerModule: resolve project-memory workspace root from the session's bound
  workspace (sessionWorkspaceRoot) instead of boot-static pm.repoRoot(), fixing
  the workspace-binding divergence (correx vs empty scratch dir). Retire tracked
  in Vikunja #266.
- LaunchRegistrationRaceTest: join registered jobs before asserting launchCount
  — computeIfAbsent returns the Job immediately but the fire-and-forget launch
  body lagged awaitAll (the 49-vs-50 flake).

ACR concept-compiler experiment (pre-existing WIP on this branch):
- ExecutionPlanCompiler/Model/PlanLinter, #264 needs-seam (sessionArtifacts),
  LSP diagnostics subsystem (LspDiagnosticEvents/Runner/Lsp4j), BootWorkspace,
  config surface, workflow prompts/schemas, orchestrator advance-don't-rerun.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 01:20:37 +04:00
kami 41ed6414c6 feat(guardrails): steering channel + shell-in-file rule + capability-gap detector
Bundles three operator-reliability guardrails (Vikunja #28/#29/#30) plus the
in-flight branch WIP they were built on top of (reasoning_content capture,
operator/project profile editor, write-jail workspaceRoot fix) — the tree is
interdependent (SessionOrchestrator references reasoningArtifactId from the WIP)
and does not compile as separable subsets, so it lands as one commit.

Guardrails:
- #28 mid-stage steering: ClientMessage.SteerSession -> GlobalStreamHandler ->
  orchestrator.submitSteering, reusing SteeringNoteAddedEvent + existing context
  fold (advisory, non-authoritative; invariants #3/#7). Closes the gap where
  steering typed off an approval gate was silently dropped.
- #29 shell-in-file guardrail: ShellInFileContentRule (core:toolintent) blocks a
  file_write whose content is a bare shell command (e.g. "mkdir -p ..."); FileWriteTool
  description now advertises auto-mkdir of parent dirs. Basename-allowlist so the
  extensionless case is caught; scripts/Makefiles/multiline exempt.
- #30 pt1 capability-gap detector: deterministic CapabilityGapDetector maps stage
  intent -> implied ToolCapability, compares to granted tools, emits advisory
  CapabilityGapDetectedEvent in FreestyleDriver.lockAndRun. Recorded, never fails
  the gate and never auto-grants (invariants #3/#4/#5). Reflection rung is pt2.

Verified: ./gradlew check green (whole tree).
2026-07-07 13:27:59 +04:00
kami 18cbd34739 fix(kernel,tools,workflow): session-robustness QA sweep
Uncommitted work from the session-robustness-and-dox branch sweep
(docs/qa/QA-session-robustness-and-dox.md), verified alongside the
compression/context fixes:

- SandboxedToolExecutor: validate tool args centrally before dispatch. A
  malformed/missing-arg call becomes a recoverable ERROR: (surfaced with the
  tool's arg schema so the model can correct + retry) instead of stranding
  the stage with no artifact. + validation test.
- PlanLinter: seed artifacts (analysis) produced by the planning phase count
  as available producers, so a plan stage that `needs` them isn't flagged as
  an unproduced-need; H1 unproduced-needs + trap-state checks. + tests.
- DefaultSessionOrchestrator: live-QA robustness fixes (event-tail /
  per-stage budget + retry handling).
- workflow prompts/configs: DOX AGENTS.md alignment + freestyle/task/role
  prompt tweaks.
- SessionOrchestratorIntegrationTest: coverage for the above.
- FreestylePlanningWorkflowTest: allow list_dir in analyst tools (follows the
  list_dir wiring in 968cbfa).
- QA plan doc for the branch sweep.
2026-07-02 00:56:45 +04:00
kami 21e01da3ac feat(tasks): task_decompose splits a goal into a dependency-linked graph in one approval
The freestyle analyst can now break a large goal with dependency seams or
independent review/handoff points into a parent epic + DEPENDS_ON-linked children
in a single T2 approval, instead of N separate task_create calls. Parent
DEPENDS_ON every child (completes last); each child IMPLEMENTS parent. Resolves
depends_on by ref or index; rejects cycles, unresolved refs, missing title/goal,
and empty batches; same batch dedup + force_reason convention as task_create.

A session works one active task, so multi-task work is multi-session by
construction: the analyst names the single ready task this run works, the architect
threads only that one, and siblings are claimed by later runs via task_ready
(claim-driven; no scheduler, /tasks/next stays rejected).

Doctrine: analyst_freestyle.md picks one-task-vs-decompose and names the ready
task; architect_freestyle.md threads only that one; plus the L0 policy line.
freestyle_planning.toml analyst gains task_decompose (pinned by
FreestylePlanningWorkflowTest).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 10:39:03 +00:00
kami 12d5b9d7dc feat(tasks): analyst opens the task; freestyle threads it into implementation
Two coupled gaps from tracing a real run:

1. Freestyle implements in phase 2 via stages compiled from the architect's
   execution_plan (ExecutionPlanCompiler sets allowedTools = stage.tools), so the
   static allow-lists never reach it and architect_freestyle.md banned every tool
   but the file four. Teach the architect to thread an analysis-referenced task
   through the plan: implementing stages get task_context/task_update and claim +
   submit_for_review; the final/review stage completes it. No task referenced → no
   task tools, and the plan never creates one.

2. Give the analyst task_create so the work is framed as a tracked item up front
   (role_pipeline + freestyle). "Read-only" for the analyst means it writes no
   files; a task is an event-log entry, not a file write — task_create is T2, so
   opening one is approval-gated. The analyst names the new id in the analysis so
   the implementer claims it and the reviewer completes it; the implementer now
   creates only as a fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 15:13:52 +00:00
kami de54be7ecb feat(tasks): wire the task tools into the remaining code-work workflows
Extend the role_pipeline wiring to the other workflows that act on a code work
item, matching each stage's tier:

- freestyle_planning: analyst (read-only) gets task_search/task_context to find
  related work and ground the analysis; prompt updated to match.
- review_loop: implement gets the full set (claim, submit_for_review, notes),
  review gets task_context/task_update to complete on an approved verdict. Its
  prompt files don't ship, so the doctrine rides the L0 policy + tool descriptions.

Left untouched: research (external-research flow producing a report, not a code
work item), qa_ping (smoke test), and healthcheck (diagnostic) — none track work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 10:26:38 +00:00
kami 8ea8d7530d feat(prompts): analyst emits structured clarification questions
Replace the inline "Q:"-prefixed-summary convention with a structured
`questions` array of {prompt, options?, multiSelect?, header?} objects that
rides in the analysis artifact (allowed by additionalProperties:true, skipped
by JsonSchemaValidator). The kernel parses it to drive the producer-exit
clarification loop; the TUI renders it as an interactive form.
2026-06-14 13:04:06 +04:00
kami 37ac767d1f feat(freestyle): two-phase planning->execution driver (Slice 4)
- freestyle_planning.toml: analyst -> (approval) -> architect, producing
  execution_plan; analyst_freestyle.md surfaces open questions.
- TomlWorkflowLoader: requires_approval stage flag -> metadata.
- SessionOrchestrator: inline-prompt branch (metadata[promptInline]) +
  requestStageApproval helper reusing the existing pause/approve path.
- DefaultSessionOrchestrator: enterStage gates on requiresApproval
  (idempotent via resolved-approval lookup), preview derived from the
  gated stage's needs artifact; validatedArtifactContent accessor.
- FreestyleDriver: compiles validated plan, emits ExecutionPlanLockedEvent,
  runs phase 2 in-session via a runPhase2 seam; wired through ServerModule
  + Main (execution_plan kind registered).
2026-06-08 02:50:36 +04:00