Skip to content

feat(feedback): report bugs and feature requests from the conversation - #530

Merged
mrgoonie merged 18 commits into
mainfrom
feat/510-conversation-feedback-reporting
Oct 7, 2026
Merged

mrgoonie merged 18 commits into
mainfrom
feat/510-conversation-feedback-reporting

Conversation

@mrgoonie

@mrgoonie mrgoonie commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Refs #510. Related: #507, #402, #508, #495, #197, #129.

This delivers the phases of #510 that are not blocked: phases 0–4 and 7. People can report a bug or ask for a feature from the conversation and get back a truthful result. Handing an issue to Clark to fix stays unavailable until #402 and #508 land, and the product says so.

What changed

Phase 0: contracts and storage

  • packages/contracts/src/feedback.ts adds the following types:
    • FeedbackRequest, FeedbackDraft, FeedbackPublication and HandlingEligibility;
    • the rpt_ id;
    • the statuses (draft | publishing | unknown | published | failed);
    • the host-owned feedback-card block;
    • the hidden marker <!-- clark-report:rpt_... --> with a reader for it.
  • The repository is fixed to digitopvn/clarkcant by trusted config, and no request field can change it.
  • Migration 44 adds feedback_reports. Applied migrations are untouched. Conversation deletion removes a conversation's reports.

Phase 1: one host-owned service (apps/runtime/src/application/product-feedback.ts, feedback-compose.ts)

  • Safe diagnostics are on by default and the person can turn them off. They cover:
    • version, OS and architecture, runtime, locale and input mode;
    • subsystem, provider and model;
    • a redacted 300-character error excerpt with a 12-hex fingerprint;
    • the time it was captured.
  • No transcript, prompt, file, environment variable, raw log, home path or credential is collected.
  • All outbound text goes through the existing redactSecrets (no forked patterns), the home directory is replaced by ~ (case-insensitively on Windows), and @handles are neutralised so filing notifies nobody.
  • The issue only has sections someone actually spoke to. A reproduction nobody gave reads "Not known yet."
  • Philosophy fit (aligned, aligned-with-constraints, material-conflict) combines host rules with the model's reading, and the stricter one wins. A conflict is still filed as asked. The rules match whole words with Unicode boundaries, and the secret rule needs a hand-over verb, so "token usage" is not a conflict. Constraints and related-issue reasons on the card follow the person's language.
  • Before filing, it searches open issues and issues closed in the last 90 days. A fingerprint match or a near-identical issue counts as a duplicate.

Phase 2: GitHub publisher (feedback-github.ts)

  • Publishing is an external-write effect in the action ledger: prepared → submitted → confirmed, failed or unknown.
  • A report counts as published only after GitHub is read back holding its marker.
  • A write that gets no answer is unknown. Check again (intent: "check") only looks for the marker and never sends. The marker search window and the two-minute grace are anchored to the attempt's own time (effect.preparedAt), so a later check cannot restart the grace or hide the issue from the search. Once GitHub's own list shows the marker absent after the grace, the report is failed and retryable, and Send again files it for the first time. Nothing is sent while GitHub cannot be checked. The marker is looked for among the issues the token's owner opened (creator, from GET /user, asked once per check), at most 3 pages of 100.
  • When checking still cannot settle a report (that list runs past the scan, or the ledger no longer holds the attempt), it is unknown with inconclusive: { since, searchUrl, manualUrl }. The card says "Clark can't tell whether GitHub kept this report, and checking again won't change that." (EN/VI), drops Check again, links the issues the person opened since the attempt and the prefilled new-issue page with a duplicate warning, and offers "Send anyway — this may file it twice" (intent: "send-anyway", accepted only for such a report, otherwise 409 NOT_INCONCLUSIVE). That press is person-only (also refused at the route for MCP and the relay), policy-checked like a send, and recorded with approvedBy: "person"; a policy refusal leaves the report as it was. The node never sends a report again on its own.
  • When the node starts, every report left publishing or unknown is reconciled the same way, and a settled outcome is written into its conversation as a result card.
  • An open duplicate gets a comment instead of a new issue.
  • The token is the feat: add generic Signal → Intent → Effect reactive automation #197 GitHub credential (github_token), read through the secret broker as consumer feedback:github. Without it the status is needs-access, with GitHub's prefilled new-issue URL.
  • Tests use an in-process fake (test-support/fake-github.ts), also reachable from e2e with CC_GITHUB_FIXTURE=1.

Phase 3: conversation surfaces

  • Bug or feature reports can be started in these ways:
    • /report (found by autocomplete), /report bug … and /report feature … (also lỗi and tính năng), through the slash-command handler;
    • the model tool report_feedback for a sentence or for voice.
  • All of these only prepare. They show the issue exactly as it would be filed, with Create issue, and send nothing. The tool has no file action, and a call that still asks for one is prepared instead and told so.
  • A bare /report puts the host-owned Feedback Composer in the conversation. It has:
    • a Bug or Feature choice, the description, and a "share diagnostics" toggle;
    • a "What will be shared" disclosure;
    • Preview, which shows the issue exactly as it would be filed;
    • Create issue.
  • The result card states the truthful status:
    • created or commented, with the link;
    • unknown, with "Check again", which only checks; or, when checking cannot settle it, the two links, the duplicate warning and "Send anyway";
    • failed, with "Send again" only when GitHub was shown not to hold the report;
    • needs-access, with the manual link;
    • refused.
  • Only the person's press files a report. The press goes through the execution policy: a deny makes the report refused with nothing sent, and an ask is answered by the press itself, recorded in the ledger with approvedBy: "person" (recordEffectExecution gains an optional approvedBy, still "policy" by default). There is no approval-required state.
  • A card a later result answers (answers) renders as a record, after a reload too, so nothing offers to file the same report twice. A press that does not get through keeps its report id, so pressing again acts on the same report.
  • POST /feedback/reports/{id}/publish is person-only on MCP, the WebSocket relay and clarkcant api.

Phase 4: handling eligibility

Phase 7: issue templates

  • .github/ISSUE_TEMPLATE/bug.yml and feature.yml mirror the same information model. The invariant checker accepts them.

What stays the same

  • There is no reporter-specific process manager and no direct gh shell-out worker. Phases 5 and 6 are not started.
  • Voice adapter internals, timeline pagination, widget dev tooling and release tooling are untouched.
  • Every existing slash command and person-only route behaves as before.

Verification

  • Round 3 on dfcad96b: focused Vitest (conversation-client, contracts, the runtime feedback suites, core execution-policy, install-approval, open-interfaces, slash-commands) 157 files and 2069 tests passed; typecheck clean; pnpm invariants 13/13; ESLint on the touched files clean; the feedback e2e 3/3 passed. corepack pnpm verify: 7042 tests passed, with one file-level failure, session-preview-real.spec.ts, from a Windows EPERM while removing its temp profile dir; that file passes on its own (3/3).
  • Round 2 on 93bfa74d: focused Vitest (runtime feedback suites, core execution-policy.spec.ts, contracts) 51 files and 963 tests passed; typecheck clean; pnpm invariants 13/13; ESLint on the touched files clean; the feedback e2e 3/3 passed.
  • corepack pnpm verify on ac705e39: exit 0. Invariants, tsc (both configs) and ESLint pass; Vitest 7021 passed, 37 skipped, 1 todo across 526 files, 0 failed.
  • Focused Vitest suites:
    • product-feedback.spec.ts: 45, including the reported sequence (attempt at T0, offline check at +10 min, a press at +20 min finds the issue by its marker, with one GitHub write in total), policy deny and prohibition refused on the person's press, ask answered by the press, the restart sweep, and conversation delete;
    • feedback-compose.spec.ts (new): 25, covering philosophy cases EN/VI/NFD, titles, the Windows home scrub, mentions and surrogate-safe cutting;
    • feedback-surfaces.spec.ts, feedback-github.spec.ts and contracts feedback.spec.ts: 28;
    • conversation-client feedback-card.spec.ts (new): 8, plus the card-state matrix.
  • Playwright apps/web/e2e/feedback-report.spec.ts: 3 of 3 passed against the in-process GitHub fixture. The new case runs /report bug …, checks nothing is filed before the press, presses Create issue, and checks the prepared card stays a record after a reload.

Limitations

Notes for review

  • apps/runtime/src/host-text.ts gets one entry, the English tool label report_feedback. The host-text language test requires every defined tool to have one.
  • A bare / in the composer now shows all 7 commands and one skill within the 8-row cap. More skills appear as the person types. composer-references.spec.ts now states that rule instead of a list that only fit by coincidence.
  • Three migration-list assertions now include 44: audit.spec.ts, conversation-delete.spec.ts and packages/core/test/install-from-source.spec.ts. Applied migrations are unchanged.
  • This overlaps perf(conversation): read the timeline by sequence window and merge pages instead of replacing them #514 in routes/conversations.ts, services.ts, the contracts index, the client api.ts and the open-interfaces docs. Expect textual conflicts only, whichever lands second.

Remaining phases and blockers

Docs impact

  • In-repo: docs/open-interfaces.md and .vi.md gain a "Product reports" section (routes, intent/answers, statuses, Check again versus Send again, restart reconciliation, the policy on the person's press, the marker, eligibility, CC_GITHUB_FIXTURE) and add the publish route to the person-only list.
  • Official docs (clarkcant-web) are not edited in this PR. They are tracked in docs: report a bug or request a feature from the conversation (/report) clarkcant-web#118.

Clark, the report_feedback tool, voice and `/report bug ...` now only
prepare a report and show the exact issue with Create issue; the tool's
file action and the approval path behind it are gone. The person's press
goes through the execution policy: a deny is refused with nothing sent,
and an ask is answered by the press and recorded.

An unanswered write is reconciled against the attempt's own time, so a
later check can neither restart the grace period nor hide the issue from
the marker search, and the test GitHub honours that search window. Check
again only looks; Send again appears once GitHub shows the report absent.
Reports left publishing or unknown are reconciled when the node starts,
and a settled outcome is written into the conversation. A press that does
not get through keeps its report, so a second press cannot file twice.

Answered composers and prepared cards render as records after a reload.
The manual issue link no longer splits surrogate pairs, the home path is
scrubbed case-insensitively on Windows, @Handles are neutralised, titles
keep acronyms, philosophy rules match whole words and need a hand-over
verb for secrets, and constraints and related-issue reasons follow the
person's language.

Refs #510
The ledger now records the person, not the policy, as the one who let a
report be filed on their press: recordEffectExecution takes an optional
approvedBy, still "policy" by default.

A marker scan whose every page was full stops with "could not check"
instead of "absent", and a report whose attempt is missing from the
ledger stays unknown, so Send again is never offered on a report GitHub
may already hold.

The cross-platform philosophy rule needs an operating system named, so
"just for fun" no longer reads as a platform constraint, and the
machine-surface comment on the publish route says only the person files.

Refs #510
…n send it anyway

The marker scan now reads only the issues the token's owner opened
(creator, from GET /user, asked once per check), so other traffic in the
repository no longer runs the scan out.

When checking still cannot settle a report (the list runs past the scan,
or the ledger no longer holds the attempt), it is unknown and
inconclusive, said plainly: Clark can't tell whether GitHub kept it, and
checking again won't change that. The card drops Check again, links the
issues the person opened since the attempt and the prefilled new-issue
page with a duplicate warning, and offers Send anyway. That press is the
person's alone (refused on MCP and the relay at the route too), goes
through the execution policy like a send, and is recorded as the
person's decision; a refusal leaves the report as it was. The node never
sends a report again on its own.

Refs #510
@mrgoonie

mrgoonie commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at dfcad96be1d6bede5afc2a7ccc7a09fe424c31fa, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

@mrgoonie

mrgoonie commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at 67f2ecf400f41c099caa0aec6475f47cd2df17eb, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

…glish

Filing a report recorded its action-ledger description in the language
the node was set to at the press, so an entry written in Vietnamese kept
showing in Vietnamese on Settings > Control after the person chose
English. The ledger is written once and read later in any language, so
the description is now fixed English like every other entry's.

Refs #510
@mrgoonie

mrgoonie commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at 9ac14b092a51f1660b8759eaa2d22c5142f4a6e8, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

@mrgoonie

mrgoonie commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at 9c48492d3c8fe1f000b8abd5706910cb0f2fc438, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

@mrgoonie

mrgoonie commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at 2ebf4455ebebe2bb4cc6ecb6e3623d1c558fdc57, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

@mrgoonie

mrgoonie commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at 68d2f326d6201214eff95684889d5ced52dab707, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

@mrgoonie

mrgoonie commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at ec0be8fb4344b52439aea2d67379874ebde9df80, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

Keep main's external channels as storage migration 44 and move product reports to 45. Read the newest timeline page after a feedback publish, since the timeline query no longer takes afterSequence. /changelog and /report sit side by side in the slash commands, cards, tools and session search.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization has no extra usage available to pay for this review.

If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.

Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.

@mrgoonie

mrgoonie commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at c405fb472b7df6ff93917e3c84331e87dd4622c8, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

@mrgoonie

mrgoonie commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at d15b09c39e6bd54f6357e9e79cc65898a95543ca, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

@mrgoonie

mrgoonie commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at 2f282f5e7cbe980d875abe31f8cfc9b347052235, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

@mrgoonie

mrgoonie commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at 32e2fc7256788e8a8d752e8de2e0ff921b98eecb, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

# Conflicts:
#	packages/contracts/src/machine-surfaces.ts
@mrgoonie

mrgoonie commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Review attestation: ready to merge at 0e73dc148a6f4f6546576d6bd64bd8c868acf6d4, reviewed by agent:code-reviewer.

A push to this PR makes this attestation stale; the new head needs its own review.

@mrgoonie
mrgoonie merged commit d1dca30 into main Oct 7, 2026
40 of 41 checks passed
@mrgoonie
mrgoonie deleted the feat/510-conversation-feedback-reporting branch October 7, 2026 20:46
mrgoonie added a commit to digitopvn/clarkcant-web that referenced this pull request Oct 7, 2026
Describe /report and its Feedback Composer, that only the person's
Create issue press files a report, the result states, Check again and
Send again, what is and is never shared, and the person-only
/feedback/reports routes, in English and Vietnamese.

Refs #118
Refs digitopvn/clarkcant#510
Refs digitopvn/clarkcant#530
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