Skip to content

FAQ harvesting: Teams -> Coda review -> FAQ-<Domain>.md - #100

Merged
vijay-tylertech merged 1 commit into
mainfrom
chore/faq-harvest-pipeline
Sep 9, 2026
Merged

vijay-tylertech merged 1 commit into
mainfrom
chore/faq-harvest-pipeline

Conversation

@vijay-tylertech

Copy link
Copy Markdown
Contributor

Builds the queued FAQ-harvesting loop: read the source Teams channels, extract FAQ candidates
not already in that domain's FAQ-*.md, post them to a Coda review table, and when a reviewer
ticks Ready for Processing, pull the row, index it into the FAQ, and delete it — so Coda
only ever holds outstanding items.

Why it is half agent, half script

Reading a Teams channel needs the Microsoft 365 MCP tool teams_list_channel_messages,
available to Claude in a session but not to a plain Python process (no Graph app credentials on
this machine). Extraction, dedupe and conflict classification are agent judgement; push,
pull and delete are deterministic — they are the steps that must not half-happen.

Status

The Aligned Releases queue is live — 21 candidates in Coda grid-4mdZMRDPAE, all awaiting
review. Nothing has been indexed and nothing has reached Foundry. Two candidates contradict
entries the agent answers from today (cohort unassignment; the feature-flag metadata field)
and are flagged, not applied.

Status Pages/SLAs is scoped but not built, and has nowhere to deploy yet —
Knowledge-StatusPageAndSLA/ is a scaffolded corpus with no agent and no collection.

Design notes worth reviewing

  • A checkbox is the only gate, and there is no Status column. Rows do not survive
    processing, so a status written on a row would never be read again. Decisions live in
    ledger-<domain>.json, which outlives the row.
  • Rejection = delete the row. push notices that a key it previously sent has gone and
    records it as rejected, so it is never re-proposed.
  • The ledger tracks table_id. Rebuilding the table is the normal way a column change
    happens, since the Coda API cannot rename or delete a column — without this, pointing at a
    fresh table would record every previously-pushed key as a rejection in one go.

Verified Coda behaviour, not assumed

Finding Consequence
The API cannot create a table or add/remove columns; a markdown table in canvasContent becomes static text Tables are made by CSV import, so the CSV filename must be the intended table name
Writes are async — a probe page took ~20s to disappear Every mutation polls /mutationStatus to completion
CSV import coerces types Source link → link (safe, full URL kept); the date column reads back as ...T00:00:00.000-05:00, so never string-compare it

Paths

Touches scripts/ and team-config/, both admin-only. No credentials committed —
CODA_API_TOKEN comes from the environment.

https://claude.ai/code/session_01KxA7f912exehyUjjgVBgf4

@vijay-tylertech
vijay-tylertech requested a review from a team as a code owner September 9, 2026 16:36
@vijay-tylertech
vijay-tylertech enabled auto-merge (squash) September 9, 2026 16:37
Recurring questions get answered in Teams by the people who own the answer, and then
the answer is lost. This adds the loop that catches them, with a human approval gate in
Coda so nothing unreviewed reaches Foundry.

Half agent, half script, because reading a Teams *channel* needs the Microsoft 365 MCP
tool teams_list_channel_messages, which is available to Claude in a session but not to a
plain Python process - there are no Graph app credentials on this machine. So extraction
and dedupe are agent work; push, pull and delete are deterministic.

  scripts/coda_faq_review.py         status / push / pull / delete
  scripts/faq-harvest/HARVEST.md     the loop, the sources, the rules extraction follows
  scripts/faq-harvest/TABLE-SPEC.md  column spec and what the CSV import actually produced
  team-config/faq-harvest/           the first batch, the import CSV, the ledger

The Aligned Releases queue is live: 21 candidates in Coda grid-4mdZMRDPAE, awaiting
review. Two of them contradict entries the agent is answering from today - cohort
unassignment and the feature-flag metadata field - and are flagged as such rather than
applied.

Three Coda behaviours the script exists to absorb, all verified rather than assumed:

- The REST API cannot create a table, and cannot add or remove a column. A markdown
  table in page canvasContent becomes static text, not a grid. Tables are made by CSV
  import, which is why the CSV filename has to be the intended table name.
- Writes are asynchronous. A probe page took ~20s to disappear. Every mutation polls
  /mutationStatus to completion, so "delete the processed row" cannot half-happen.
- CSV import coerces types: Source link became a link column (safe, full URL preserved)
  and the date column reads back as ...T00:00:00.000-05:00, so it must never be
  string-compared.

A checkbox is the only gate, and there is deliberately no Status column: rows do not
survive processing, so a status written on one would never be read again. Decisions live
in team-config/faq-harvest/ledger-<domain>.json instead, which outlives the row.
Rejection is expressed by deleting the row - push notices a key it previously sent has
gone and records it as rejected. The ledger tracks table_id for that reason too, since
rebuilding the table is the normal way a column change happens and would otherwise look
like the reviewer having deleted every row at once.

No credentials: CODA_API_TOKEN comes from the environment and the token is not in any
committed file.

Claude-Session: https://claude.ai/code/session_01KxA7f912exehyUjjgVBgf4
@vijay-tylertech
vijay-tylertech force-pushed the chore/faq-harvest-pipeline branch from bbeba84 to eee0511 Compare September 9, 2026 18:00
@vijay-tylertech
vijay-tylertech merged commit 22a7d8c into main Sep 9, 2026
1 check passed
@vijay-tylertech
vijay-tylertech deleted the chore/faq-harvest-pipeline branch September 9, 2026 20:58
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