Skip to content

Promote dev → main (incl. /goal + /loop) - #258

Closed
mabry1985 wants to merge 25 commits into
mainfrom
dev
Closed

Promote dev → main (incl. /goal + /loop)#258
mabry1985 wants to merge 25 commits into
mainfrom
dev

Conversation

@mabry1985

Copy link
Copy Markdown
Member

Summary

Promotes everything on dev since the last release to main, including:

Merging this triggers auto-release.yml to compute the conventional-commits version bump, open a release PR, and publish.

Test plan

  • All checks green on feat(cli): /goal and /loop commands for long-horizon tasks #257 before squash-merge to dev (tests 20.x/22.x, lint, CodeQL, CodeRabbit)
  • Local smoke: both /goal and /loop are registered (confirmed via proto -p non-interactive path)
  • Manual smoke after release: type /goal and /loop in an interactive session
  • Manual smoke after release: confirm experimental.cron: true makes /loop 1m echo actually fire a tick

🤖 Generated with Claude Code

Automaker and others added 24 commits April 28, 2026 23:38
/recap (and any other caller without tools, e.g. /btw) was sending an
empty conversation to the model. The no-tools branch in pipeline
buildRequest dropped every assistant turn with tool_calls and every
tool-role message wholesale, so in tool-heavy sessions the recap saw
only bare user prompts and hallucinated context.

- generateRecap now passes tools: [] so the strip path doesn't fire,
  matching cc-2.18's awaySummary pattern.
- pipeline.ts no-tools branch now flattens instead of dropping: keeps
  assistant prose content and removes only the tool_calls field; tool
  results become [tool result] assistant notes truncated at 2000 chars.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
auto-release.yml opens version-bump PRs from `auto-release/v*` branches
into main, but release.yml's job gate only matched `head.ref == 'dev'`.
Result: every auto-release PR was merging cleanly but skipping publish
(v0.26.25 had to be dispatched manually). This adds the auto-release/*
prefix to the gate and refreshes the stale top-of-file comment.

Co-authored-by: Automaker <automaker@localhost>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…ary (Phase 1 of #162) (#165)

* feat(core): preserve task plan state in compaction summaries (#163)

* feat(core): preserve task plan state in compaction summaries

When context compaction fires, the agent loses awareness of its task plan
(completed, in-progress, pending work) and may re-plan already-done tasks.

Add extractTaskPlanSummary() that queries the TaskStore and produces a
structured <task-plan> XML section with status markers ([x], [~], [ ],
[-], [!]), priority labels, and parent-child indentation. Extend
compactMessages() to accept an optional taskStore and append the plan
to the compaction summary. Wire the TaskStore into agent-core at the
compaction call site.

Backward compatible: existing callers without taskStore remain unaffected.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix: add error handling and recursive nesting to compaction task plan

Address PR feedback from CodeRabbit:
- Wrap extractTaskPlanSummary call in try/catch so TaskStore
  failures don't break compaction
- Replace flat 2-level subtask rendering with recursive renderTask()
  that supports arbitrary nesting depth
- Add tests for multi-level nesting and error fallback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Automaker <automaker@localhost>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* feat(telemetry,ui): capture reasoning on Langfuse span and collapse thoughts post-stream

Phase 1 of the reasoning coordination tracked in #162. Captures
delta.reasoning_content / delta.reasoning across stream chunks and surfaces
it as gen_ai.response.thinking on the gen_ai chat span (gated on logPrompts,
matching the completion event policy). Always emits gen_ai.usage.thinking_tokens
when usage exposes it. Non-streaming responses get the same treatment by
inspecting {thought:true} parts on the response — and the completion event no
longer double-counts thoughts as content.

Renders gemini_thought items as a compact "▸ thinking (N chars)" summary once
the stream finalizes (live streaming render unchanged). Full text remains in
ChatRecord, ACP agent_thought_chunk notifications, and Langfuse for downstream
investigation. An in-TUI expand affordance is a follow-up.

Once homelab-iac#31 (EMIT_REASONING_CONTENT) flips on, this also covers
vLLM-served models that previously lost their <think> blocks at the gateway.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Automaker <automaker@localhost>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…ping (#167)

* chore(telemetry): rebrand qwen-code identifiers to proto-cli

Aligns telemetry / public-facing identifiers with the actual product
name. Verified against the Langfuse instance: new spans land with
service.name=proto-cli on scope=proto.openai-pipeline; existing
proto.* tracers (proto.llm, proto.turn, proto.tools, proto.harness,
etc.) were already correct.

Changes:
- SERVICE_NAME: qwen-code → proto-cli (resource attribute, the marquee
  label in Langfuse's service column)
- All EVENT_* constants: qwen-code.* → proto.* (matches the existing
  proto.harness.* convention already in this file)
- pipeline.ts tracer: qwen-code.openai-pipeline → proto.openai-pipeline
  (one straggler vs. the 9 other proto.* tracers in core/)
- types.ts event.name literals (PromptSuggestion, Speculation):
  qwen-code.* → proto.*
- acpAgent.ts agentInfo.name: qwen-code → proto-cli (visible to ACP
  clients like Zed when listing agents)
- marketplace.ts User-Agent: qwen-code → proto-cli (extension fetch
  identifier sent to api.github.com / raw.githubusercontent.com)

Out of scope (deliberately):
- packages/core/src/telemetry/qwen-logger/* — separate analytics ping
  to gb4w8c3ygj-default-sea.rum.aliyuncs.com (Alibaba RUM, the
  upstream Qwen team's endpoint). Should be disabled rather than
  rebranded; tracking separately.
- DEFAULT_SERVICE_NAME='qwen-code-oauth' in mcp/token-storage —
  renaming would orphan existing keychain entries.
- Misc qwen-code-* file paths, tmp dir names, sandbox image tag,
  test fixtures — not telemetry / not user-visible labels.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(telemetry): remove qwen-logger Alibaba RUM ping; keep useful events on Langfuse

The qwen-logger system shipped usage telemetry to a fixed Alibaba RUM
endpoint (gb4w8c3ygj-default-sea.rum.aliyuncs.com) — the upstream Qwen
Code team's analytics pipeline. We don't operate that endpoint, the
data isn't visible to us, and it labelled traffic as qwen-code-cli /
qwen-code@${version}. Confirmed unused on our deployment; nuking.

What's removed:
- packages/core/src/telemetry/qwen-logger/ (entire directory: logger,
  event-types, tests)
- packages/core/src/telemetry/integration.test.circular.ts (was a
  qwen-logger-specific circular-reference proxy-agent test, no longer
  applicable)
- ~30 QwenLogger.getInstance(config)?.logXxxEvent(event) callsites in
  loggers.ts
- QwenLogger exports from telemetry/index.ts and core/index.ts
- QwenLogger spies and assertions in config.test.ts and the
  describe('logHookCall', ...) block in loggers.test.ts that was
  exclusively QwenLogger-shaped

What's kept and rerouted to OTel/Langfuse:
- HookCallEvent type and the logHookCall function — hook execution
  data is genuinely useful telemetry (which hook fired, success,
  duration, exit code, captured stdout/stderr, error). Now emits a
  proto.hook_call OTel log record via logs.getLogger(SERVICE_NAME)
  instead of the Alibaba ping. Existing call site in
  hookEventHandler.ts:619 still fires per hook execution.
- LoopDetectionDisabledEvent likewise: was an empty no-op after the
  qwen-logger pull; rerouted to a proto.loop_detection_disabled OTel
  log record so the signal still reaches Langfuse.
- New tests in loggers.test.ts assert OTel emission shape for
  logHookCall (success, error, sdk-not-initialized branches).

Renamed (per "all not used" — no existing keychain entries to
invalidate):
- DEFAULT_SERVICE_NAME 'qwen-code-oauth' → 'proto-cli-oauth'
- FORCE_ENCRYPTED_FILE_ENV_VAR 'QWEN_CODE_…' → 'PROTO_CLI_…'
- file-token-storage encryption salt prefix and scrypt key seed
  switched to proto-cli; only invalidates non-existent tokens

Verified live: kimi-k2.6 turn through the rebuilt CLI lands a Langfuse
trace with service=proto-cli, scope=proto.openai-pipeline,
gen_ai.response.thinking present. No outbound traffic to aliyuncs.com.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Automaker <automaker@localhost>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(cli): add /goal and /loop commands for long-horizon tasks

/goal sets a verifiable completion condition; after each turn a small
evaluator call decides whether the condition holds and either marks the
goal achieved or injects the evaluator's reason as the next-turn
directive. Wires into client.ts at the same continuation site as the
existing Stop hook and CompletionChecker paths, so feedback drives a new
turn via the same sendMessageStream recursion the rest of the codebase
uses.

/loop schedules a recurring prompt via the existing CronScheduler so it
inherits jitter, expiry, and the idle-drain submit path already wired in
useGeminiStream. Supports both leading-token (5m check deploy) and
trailing "every N unit" parsing, a 10m default, list/clear/stop, and
single-job cancellation by 8-char id. Replaces the bundled loop skill
that used to model-route /loop input through cron_create / cron_list /
cron_delete tools; the tools stay for natural-language scheduling.

New modules in core: goal/ (manager, evaluator) and loop/
(intervalParser, intervalToCron). Docs added at docs/guides/goal.md and
the existing docs/guides/scheduled-tasks.md picks up the new management
syntax. 815 tests pass across the directories touched.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(goal,loop): address review feedback from PR #257

- /goal evaluator now re-runs after goal-driven continuations. Previously
  the unmet-goal continuation used SendMessageType.Hook, which the next
  pass's gate excluded -- so /goal would inject feedback once and then
  stop. Added SendMessageType.GoalContinuation, drop the Hook-only gate
  on the goal block, and extend the CompletionChecker gate to also skip
  goal-driven continuations so they don't interleave.

- Evaluator failures no longer abort a completed turn. evaluateGoal is a
  second model call after the user's turn already succeeded; if it
  throws we now log and skip recording, leaving the goal active and the
  user's turn output intact.

- extractFirstJsonObject tracks in-string state and JSON escape
  sequences, so payloads like {"reason": "see {artifact}"} no longer
  break brace matching.

- stripCodeFence replaces the lazy-quantifier regex (CodeQL polynomial
  regex finding) with a simple indexOf/lastIndexOf scan. Regression
  test verifies pathological whitespace input returns in under 100ms.

- GoalManager.setGoal and clearGoal now return defensive copies so
  callers can't mutate internal state through the return value.
  getActiveGoal/getLastAchievedGoal already did this.

- intervalToCron rounded check for near-24h inputs (e.g. 1439m) now
  compares back in minutes (days * 24 * 60 !== minutes) instead of
  hours / 24, so the rounding warning fires correctly.

- docs/guides/goal.md corrects the "small fast model" wording to
  reference Config.getModel() with a note about the future fast-model
  switch, and adds language tags to fenced code blocks for MD040.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Automaker <automaker@localhost>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@mabry1985, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 2 reviews/hour. Refill in 6 minutes and 4 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b506d336-7678-48d8-a1cc-afe2265c7b9b

📥 Commits

Reviewing files that changed from the base of the PR and between 180cf54 and 96cbfd1.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (60)
  • .github/workflows/release.yml
  • .github/workflows/sdk-release.yml
  • docs/guides/_meta.ts
  • docs/guides/goal.md
  • docs/guides/scheduled-tasks.md
  • docs/superpowers/plans/2026-04-30-p4-compaction-todo-preservation.md
  • package.json
  • packages/cli/package.json
  • packages/cli/src/acp-integration/acpAgent.ts
  • packages/cli/src/services/BuiltinCommandLoader.ts
  • packages/cli/src/ui/commands/goalCommand.test.ts
  • packages/cli/src/ui/commands/goalCommand.ts
  • packages/cli/src/ui/commands/loopCommand.test.ts
  • packages/cli/src/ui/commands/loopCommand.ts
  • packages/cli/src/ui/components/messages/ConversationMessages.test.tsx
  • packages/cli/src/ui/components/messages/ConversationMessages.tsx
  • packages/core/package.json
  • packages/core/src/agents/runtime/agent-core.ts
  • packages/core/src/agents/runtime/compaction.test.ts
  • packages/core/src/agents/runtime/compaction.ts
  • packages/core/src/config/config.test.ts
  • packages/core/src/config/config.ts
  • packages/core/src/core/client.test.ts
  • packages/core/src/core/client.ts
  • packages/core/src/core/openaiContentGenerator/pipeline.thinking.test.ts
  • packages/core/src/core/openaiContentGenerator/pipeline.ts
  • packages/core/src/extension/marketplace.ts
  • packages/core/src/goal/GoalManager.test.ts
  • packages/core/src/goal/GoalManager.ts
  • packages/core/src/goal/goalEvaluator.test.ts
  • packages/core/src/goal/goalEvaluator.ts
  • packages/core/src/goal/index.ts
  • packages/core/src/goal/types.ts
  • packages/core/src/hooks/hookEventHandler.ts
  • packages/core/src/index.ts
  • packages/core/src/loop/index.ts
  • packages/core/src/loop/intervalParser.test.ts
  • packages/core/src/loop/intervalParser.ts
  • packages/core/src/loop/intervalToCron.test.ts
  • packages/core/src/loop/intervalToCron.ts
  • packages/core/src/loop/types.ts
  • packages/core/src/mcp/token-storage/file-token-storage.ts
  • packages/core/src/mcp/token-storage/index.ts
  • packages/core/src/skills/bundled/loop/SKILL.md
  • packages/core/src/telemetry/constants.ts
  • packages/core/src/telemetry/index.ts
  • packages/core/src/telemetry/integration.test.circular.ts
  • packages/core/src/telemetry/loggers.test.ts
  • packages/core/src/telemetry/loggers.ts
  • packages/core/src/telemetry/qwen-logger/event-types.ts
  • packages/core/src/telemetry/qwen-logger/qwen-logger.test.ts
  • packages/core/src/telemetry/qwen-logger/qwen-logger.ts
  • packages/core/src/telemetry/types.ts
  • packages/sdk-typescript/package.json
  • packages/sdk-typescript/scripts/build.js
  • packages/sdk-typescript/src/anthropic-compat.d.ts.template
  • packages/sdk-typescript/src/anthropic-compat.ts
  • packages/test-utils/package.json
  • packages/web-templates/package.json
  • packages/webui/package.json
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Comment @coderabbitai help to get the list of available commands and usage tips.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@mabry1985

Copy link
Copy Markdown
Member Author

Closing in favour of a focused cherry-pick (#TBD). dev and main have diverged independently — dev is on 0.26.x (SDK release line), main is on 0.39.x with features dev doesn't have — so a bulk dev → main would downgrade main's version and pull in unrelated WIP. The new PR ports just the /goal + /loop commit cleanly onto main.

@mabry1985 mabry1985 closed this May 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant