From a43abaf5efb238f833c484cc57596c368eb0a996 Mon Sep 17 00:00:00 2001 From: "vanillagreen-fleet-lanes[bot]" <328550061+vanillagreen-fleet-lanes[bot]@users.noreply.github.com> Date: Sun, 18 Oct 2026 09:26:25 +0000 Subject: [PATCH] chore: refresh kendex renders --- .agents/skills/communication/SKILL.md | 37 + .../communication/references/messages.md | 80 +++ .../communication/references/questions.md | 43 ++ .../communication/references/reports.md | 58 ++ .../skills/communication/references/voice.md | 13 + .../skills/linear/scripts/lib/formatters.sh | 3 + .agents/skills/orch/README.md | 2 +- .agents/skills/orch/SKILL.md | 4 +- .../orch/references/communication-modes.md | 141 +--- .../skills/orch/references/oversee-events.md | 10 +- .agents/skills/orch/references/skill-rules.md | 6 +- .agents/skills/orch/schemas/lane-host.md | 6 +- .agents/skills/orch/scripts/lanes | 13 +- .../orch/scripts/lib/open-terminal-text.sh | 9 +- .../orch/scripts/lib/oversee-watch-text.sh | 9 +- .../orch/scripts/lib/overseer-launch.sh | 42 +- .../skills/orch/scripts/lib/pr-watch-pass.sh | 28 + .agents/skills/orch/scripts/open-terminal | 6 +- .agents/skills/orch/scripts/oversee-report | 2 +- .agents/skills/orch/scripts/oversee-succeed | 4 +- .agents/skills/orch/scripts/oversee-watch | 2 +- .../skills/orch/workflows/oversee-takeover.md | 4 +- .agents/skills/orch/workflows/oversee.md | 4 +- .../references/finding-disposition.md | 2 +- .../worktree/references/session-guard.md | 4 +- .agents/skills/worktree/scripts/lib/help.sh | 8 +- .agents/skills/worktree/scripts/worktree | 49 +- .../worktree/scripts/worktree-session-guard | 50 +- .claude/skills/communication | 1 + .kendex-generated.json | 6 + .kendex-lock.json | 639 +++++++++++------- 31 files changed, 842 insertions(+), 443 deletions(-) create mode 100644 .agents/skills/communication/SKILL.md create mode 100644 .agents/skills/communication/references/messages.md create mode 100644 .agents/skills/communication/references/questions.md create mode 100644 .agents/skills/communication/references/reports.md create mode 100644 .agents/skills/communication/references/voice.md create mode 120000 .claude/skills/communication diff --git a/.agents/skills/communication/SKILL.md b/.agents/skills/communication/SKILL.md new file mode 100644 index 00000000..deefd254 --- /dev/null +++ b/.agents/skills/communication/SKILL.md @@ -0,0 +1,37 @@ +--- +name: communication +description: "Load before writing a message to a person: a reply, report, briefing, decision request, or issue or comment addressed to the user." +summary: "Plain-language messages, reader modes, decision questions, reports, threads and spoken replies." +license: MIT +user-invocable: true +metadata: + author: vanillagreen + source: kendex + repository: "https://github.com/vanillagreencom/kendex" + bugs: "https://github.com/vanillagreencom/kendex/issues" +tags: [communication] +--- + +# Communication + +## Scope + +Use this package for messages to a person. Agent-to-agent messages, literal return formats, tool prompts, documentation and text sent as the user follow their own owners. The caller owns authority, delivery and report schedules. + +## Reading routes + +Read [messages](references/messages.md) before every message. Add only the reference the task needs: + +| Task | Read | +|---|---| +| Request a decision or action | [questions](references/questions.md) | +| Write a report or briefing | [reports](references/reports.md) | +| Answer a voice request | [voice](references/voice.md) | + +## User instruction + +The supported installed path is `.agents/skills/communication/SKILL.md`, relative to the consumer project or assistant home. Its user instruction file carries this writing reference: + +```text +Before writing a message to a person, read `.agents/skills/communication/SKILL.md`. +``` diff --git a/.agents/skills/communication/references/messages.md b/.agents/skills/communication/references/messages.md new file mode 100644 index 00000000..04e5597f --- /dev/null +++ b/.agents/skills/communication/references/messages.md @@ -0,0 +1,80 @@ +# Messages to a person + +Read before writing any message to a person. + +## Reader modes + +Use the reader mode the caller supplies. The default prose is for a CEO with moderate technical knowledge. + +| Mode | Prose | +|---|---| +| `ceo` | Say what the thing does and why it matters. Report the outcome and its cost. Name a tool, file, command or mechanism only when the person must act on it. Expand unfamiliar jargon. Keep common terms such as AI, CPU and API. | +| `engineer` | Use the session's technical vocabulary for the same outcomes and costs. | + +## Plain language + +- Write in ASD-STE100 Simplified Technical English. +- Start with the answer itself, stated as a fact. Give no summary, preamble, verdict or unrelated opening fact. +- Say what happened and what it means for the work. Name no generation, pane, token count, seat, mailbox id or internal rule unless the person must act on it. +- Stop after the last fact. Write no closing sentence. +- Put one idea in each short sentence. Use active voice. +- Cut generic sentences. Keep specific facts the reader needs: numbers, names and mechanisms. +- Never say that a fact is worth noticing. +- Do the work, then report it. Never narrate what you are about to do. +- Use no long dash, including after a bold label. Use a colon. +- Use short bullets as the default. +- Never mention these writing rules or say what you will not do. +- Never rate, rank, praise or sell, even when asked. This includes superlative framing. A heading names a topic, not a verdict. +- Name the real thing. Do not stack clauses or use insider shorthand. Replace abstract words such as signal, surface, shape, posture, residue, substrate and predicate with the real noun. +- Avoid: delve, landscape, testament, interplay, serves as, robust, seamless, and leverage as a verb. +- Give full detail on request. Never trade correctness for brevity. + +## Evidence and costs + +- Use a number only when you saw it in this session's output. Otherwise name the thing without the number. Never estimate or run an extra command only to fill that gap. +- Give every number its yardstick and verdict in the same bullet: the earlier value, target or normal range; good, bad or not known; and what is done about it. If the yardstick is unread, say so and name the reading that settles it. +- Give a measure that depends on load with that load: session length beside the work handled, or machine use beside what ran. Length or use alone never claims an improvement. +- Before posting, read each topic as the person and ask "so what for me?". Add that answer or cut the topic. +- State a cost as its figure and source. Compare added CI time against the plan's 50,000 private-repository minutes each month. + +The yardstick, load and so-what rules come from the owner's Slack messages 1792172820, 1792172887 and 1792172957, relayed in Jarvis note 1792173119. + +## Impact and odds + +When describing a mechanism, give its effect on the person and the likelihood of that effect. + +## Message purpose + +- Omit acknowledgements, unneeded mechanisms and history that do not affect the person's action. +- A critical notice states the failure, its effect and the action the person must take. +- When introducing a rule or setting, name the file or service that will hold it. + +## Medium and threads + +- Use the medium where the person started the conversation. Chat and voice connectors are the person's choice. Voice replies go to the call only. +- Keep one topic per post and per thread. Reply in the thread of the message answered, or its containing thread. Continue that topic there until the person changes topic. Keep thread replies in their threads. +- Answer each message in its own thread. If a fact answers two messages, give a short answer in each thread. +- A new topic, decision request, critical notice or progress report starts at the top level. +- Read only the thread of the message answered. Read its history when needed, not unrelated channel history. +- Follow the person's reporting cadence and quiet hours. The person defines which critical notices can interrupt them. + +## Times + +Write times in the person's time zone with am or pm. Do not use a `Z` stamp. + +## References and markup + +- Link each pull request, commit, issue and tracker item with its short name. Use `[REPO#N](https://github.com/OWNER/REPO/pull/N)`, `[SHORT_SHA](https://github.com/OWNER/REPO/commit/SHORT_SHA)` or `[KEY-N](TRACKER_ISSUE_URL)` as the form. Never put a tracker id in a code span. +- For standard Markdown, put blank lines between paragraphs, around lists and before labels. Use numbered lists for steps or options and bullets for parallel facts. +- Use headings and bold labels or decisions for structure. Never use bold for emphasis or on a whole sentence. Use sentence case. Use italics seldom. +- Use inline code for a command or path. Use a code block for output longer than one line. Keep paragraphs to a few sentences. +- Put text the person must send in a code block. Name the recipient above it. +- Beside a file, including a Slack file comment, use Slack mrkdwn: `*Label*` for bold, `` for a link and plain lines for a list. The other markup rules still hold. + +## Corrections + +Own a mistake in one line, with its repair. + +## Attachments + +Attach a screenshot or image when it explains the point better than words. diff --git a/.agents/skills/communication/references/questions.md b/.agents/skills/communication/references/questions.md new file mode 100644 index 00000000..fc13412d --- /dev/null +++ b/.agents/skills/communication/references/questions.md @@ -0,0 +1,43 @@ +# Questions + +Read when requesting a decision or action. The caller decides whether to ask and which options it can offer. + +## Decision requests + +Ask one question per message. Give the options and a recommendation. Each option states its gain, its cost and the likelihood of that cost. Use the reader mode from [messages](messages.md#reader-modes). + +## CEO questions + +```text +[WHAT THIS CHANGES FOR THE USER, ONE SENTENCE] + +**A. [OUTCOME OF THE FIRST PATH]** + +[ONE OR TWO PLAIN SENTENCES SAYING WHAT THE USER GETS, WHAT IT COSTS THEM AND HOW LIKELY THAT COST IS] + +**B. [OUTCOME OF THE SECOND PATH]** + +[ONE OR TWO PLAIN SENTENCES SAYING WHAT THE USER GETS, WHAT IT COSTS THEM AND HOW LIKELY THAT COST IS] + +**Recommended:** [A OR B], because [ONE SENTENCE IN OUTCOME TERMS]. +``` + +Use outcomes only. Name no mechanism the person does not act on and no option by its internal name. + +## Engineer questions + +```text +[QUESTION]: [OPTION_A] | [OPTION_B], with [RECOMMENDED_OPTION] recommended. +``` + +## Action requests + +Use plain words to say what the person does and what evidence closes the request. State what the deadline does. Omit the recommendation when the caller's ask form records none. + +## Opening question + +When the caller offers `idle` and `tracker` for an empty work queue, use: + +```text +What do you want to work on? Reply with issue ids or describe it, or answer tracker to take work from the tracker. With no answer by the deadline I wait for your reply. +``` diff --git a/.agents/skills/communication/references/reports.md b/.agents/skills/communication/references/reports.md new file mode 100644 index 00000000..108beb8b --- /dev/null +++ b/.agents/skills/communication/references/reports.md @@ -0,0 +1,58 @@ +# Reports and briefings + +Read when writing a report or briefing. Use the wording and markup in [messages](messages.md). + +## Reports + +Say the outcome for the person or fleet, not the issue title. Link each work item to its owning tracker issue: the Linear issue for a Linear item or the GitHub issue for an `issue-N` item. Do not use its pull request or commit as the work-item link. The tracker issue links to its pull request. + +Put detail in the report file. Send one post per report, not a thread of fragments. Give each blocked item its cause and next action. + +## Report opening + +Open with the repository's outcome readings, each with its date and source. Reuse existing evidence comments and rulings. Do not open with a Landed count. + +## Evidence + +List completed work only after its acceptance check passes. Put a merge under Landed only after reading it from the source service in this session. An agent's notice that it is merging, or an approval, is not a landing. + +## Waiting on you + +End with **Waiting on you**, with `Nothing` when empty. Read current open requests and the person's replies since the last report when writing it. Do not copy this section from a handoff. Keep a step here only when no available tool can do it. + +Name each open ask by its question, so the person can find its thread. Link each unanswered decision. State what its deadline does and when, using the [person's time zone](messages.md#times). This section is never empty while an ask is open. + +## Account headroom + +Report account headroom for every harness the fleet runs, including Claude, Codex and Copilot, side by side. + +## Summary shape + +- Put one item per line, at most 20 words. A line may carry two links. +- Put a blank line before each label. Each label stands alone: **Landed**, **Running**, **Blocked**, **Waiting on you**. +- Put each figure on its own line. Group account headroom after the opening outcome readings. +- Use at most `ORCH_REPORT_SUMMARY_LINES` item lines for an orch report, default 20. Blank lines, labels and the first opening line do not count. Leave excess items in the report file. Never pack a line to fit the cap. +- Use no table in an owner message. + +## Owner summary template + +Use this mrkdwn template for the report file's comment. For a post without a file, use standard Markdown under [References and markup](messages.md#references-and-markup). + +```text +[DATE]: [REPOSITORY OUTCOME READING] () +[DATE]: [REPOSITORY OUTCOME READING] () + +[ACCOUNT HEADROOM FIGURE] + +*Landed* +- [OUTCOME] () + +*Running* +- [OUTCOME IN PROGRESS] () + +*Blocked* +- Nothing + +*Waiting on you* +- Nothing +``` diff --git a/.agents/skills/communication/references/voice.md b/.agents/skills/communication/references/voice.md new file mode 100644 index 00000000..dfb889c9 --- /dev/null +++ b/.agents/skills/communication/references/voice.md @@ -0,0 +1,13 @@ +# Voice replies + +Read when answering a voice request. + +## Spoken reply + +- Answer a voice request before resuming other work. If the answer needs work, say what is needed in the spoken reply. +- Start with the answer in one or two spoken sentences. Use plain spoken words, no Markdown and no links. Say numbers as a person says them. Name an id only when the caller must act on it. +- Include the spoken answer only. End the spoken paragraph with one question or next step. + +## Action acknowledgement + +Before an approved action, say the exact action back in one sentence. The caller's authority and confirmation rules decide whether approval permits that action. diff --git a/.agents/skills/linear/scripts/lib/formatters.sh b/.agents/skills/linear/scripts/lib/formatters.sh index 879b1757..3a316a55 100755 --- a/.agents/skills/linear/scripts/lib/formatters.sh +++ b/.agents/skills/linear/scripts/lib/formatters.sh @@ -11,6 +11,7 @@ readonly ISSUE_BLOCKED_BY_FIELDS="inverseRelations { pageInfo { hasNextPage endC readonly ISSUE_RELATION_FIELDS="$ISSUE_BLOCKS_FIELDS $ISSUE_BLOCKED_BY_FIELDS" readonly ISSUE_RELATION_JQ=' def issue_is_open: (.state.type | IN("completed", "canceled") | not); +def issue_blocks_launch: issue_is_open and .state.name != "Verifying"; def issue_blocks_relations($relations): [($relations // [])[] | select(.type == "blocks")]; def issue_blocks_ids($relations): issue_blocks_relations($relations) | map(.relatedIssue.identifier); def issue_blocks_open_ids($relations): issue_blocks_relations($relations) | map(select(.relatedIssue | issue_is_open) | .relatedIssue.identifier); @@ -21,6 +22,7 @@ def issue_blocked_by_open_relations($relations): issue_blocked_by_relations($rel def issue_blocker_row: {id: .issue.identifier, title: .issue.title, state: .issue.state.name}; def issue_blocked_by_ids($relations): issue_blocked_by_relations($relations) | map(.issue.identifier); def issue_blocked_by_open_ids($relations): issue_blocked_by_open_relations($relations) | map(.issue.identifier); +def issue_blocked_by_launch_ids($relations): issue_blocked_by_relations($relations) | map(select(.issue | issue_blocks_launch) | .issue.identifier); def issue_blocked_by_rows($relations; $with_relation_id): issue_blocked_by_relations($relations) | map(issue_blocker_row + if $with_relation_id then {relation_id: .id} else {} end); def issue_blocked_by_open_rows($relations; $with_relation_id): issue_blocked_by_open_relations($relations) | map(issue_blocker_row + if $with_relation_id then {relation_id: .id} else {} end); # A related relation is one record Linear shows on both issues: the side that @@ -135,6 +137,7 @@ format_issue_single() { blocks: issue_blocks_ids(.issue.relations.nodes), blocked_by: issue_blocked_by_ids(.issue.inverseRelations.nodes), blocked_by_open: issue_blocked_by_open_ids(.issue.inverseRelations.nodes), + blocked_by_launch: issue_blocked_by_launch_ids(.issue.inverseRelations.nodes), related: issue_related_ids(.issue.relations.nodes; .issue.inverseRelations.nodes), url: (.issue.url // "") } + (if (.issue | has("syncedWith")) then { diff --git a/.agents/skills/orch/README.md b/.agents/skills/orch/README.md index 0439c0f2..cd594bca 100644 --- a/.agents/skills/orch/README.md +++ b/.agents/skills/orch/README.md @@ -50,7 +50,7 @@ Until KEN-2466 lands, the Claude Code agent renderer maps `haiku` to `sonnet` an | `REVIEW_MAX_CYCLES` | Re-review cycles per issue. `0`: one blockers-only fix round, accepted on its validation without re-review; `1`: one fix round and one re-review of its diff | `1` | | `REVIEW_MAX_EXTERNAL_ROUNDS` | External comment-triage passes and automatic review-wait restarts on one PR head | `4` | | `REVIEWER_SLOT_BUDGET` | Concurrent agent-session budget counting the primary; `0` is unlimited; reviews run in waves past it. On Codex, the cap `spawn-adapter slots` reports | `0` | -| `ORCH_USER_MODE` | `ceo` or `engineer`, and what each asks: [communication-modes.md](references/communication-modes.md) | `ceo` | +| `ORCH_USER_MODE` | `ceo` or `engineer`: [ask set and composition](references/communication-modes.md), [prose](../communication/references/messages.md#reader-modes) | `ceo` | | `ORCH_DECISION_MODE` | `ask` presents decision points; `auto-recommended` takes the recommended one | `auto-recommended` | | `ORCH_MERGE_AUTONOMY` | `auto` merges once every gate is green on authorization already given; `ask` requires it per merge | `auto` | | `PM_CREATE_AUTONOMY` | Audit creation and cancellation: [project-management settings](../project-management/README.md#setup) | `ask`; `auto` under `ceo` | diff --git a/.agents/skills/orch/SKILL.md b/.agents/skills/orch/SKILL.md index 85467d15..56f38ed6 100644 --- a/.agents/skills/orch/SKILL.md +++ b/.agents/skills/orch/SKILL.md @@ -5,7 +5,7 @@ summary: "Work-item orchestration for Linear or GitHub issues: prepare, delegate license: MIT user-invocable: true dependencies: - required: [mailbox, github, worktree, dev, project-management, decider, reviewer, review-gate] + required: [communication, mailbox, github, worktree, dev, project-management, decider, reviewer, review-gate] optional: [harness-ci, linear, second-opinion, commit-guards] metadata: author: vanillagreen @@ -53,7 +53,7 @@ Get the issue → dev implements → publication, review and fixes in the order - **Bounded loops.** A fix round addresses blockers only, and the same pass declines or tracks every `fix` suggestion ([workflows/review-pr.md](workflows/review-pr.md) § 4); re-review narrows to the fix diff, the domains it touched, and the class of every defect it fixed ([reviewer/SKILL.md](../reviewer/SKILL.md) § Re-Review Rounds); two consecutive rounds with no new blocker end the review; [workflows/review-pr.md § At The Cap](workflows/review-pr.md#at-the-cap) sets the cap, cap 0 and a fix round's own regression. - **Finding conduct.** Apply reviewer's [decision flow](../reviewer/references/finding-disposition.md#decision-flow), [recurrence rule](../reviewer/references/finding-disposition.md#recurrence) and [filing bar](../reviewer/references/finding-disposition.md#filing-bar). - **Scope cuts.** A reviewer or orchestrator can choose a cut round. A round whose only findings are scope or wording asks ends the review: reply, resolve, push nothing, merge through the gate. -- **Ask gates.** Which questions reach the user, and how each one is worded under the mode `ORCH_USER_MODE` names, is [references/communication-modes.md](references/communication-modes.md); nothing outside that file narrows or widens the set. That ask set holds whatever `ORCH_DECISION_MODE` says. Merge asks unless `ORCH_MERGE_AUTONOMY=auto`, which merges without asking only when every merge gate is green. In a lane every ask gate is `lane-mail`, never the harness question tool: [references/skill-rules.md](references/skill-rules.md) § Coordination. +- **Ask gates.** Which questions reach the user is [references/communication-modes.md](references/communication-modes.md); nothing outside that file narrows or widens the set. Use [communication](../communication/SKILL.md) for prose under the mode `ORCH_USER_MODE` names. That ask set holds whatever `ORCH_DECISION_MODE` says. Merge asks unless `ORCH_MERGE_AUTONOMY=auto`, which merges without asking only when every merge gate is green. In a lane every ask gate is `lane-mail`, never the harness question tool: [references/skill-rules.md](references/skill-rules.md) § Coordination. - **Post-PR autonomy.** After a PR exists, `ORCH_DECISION_MODE=auto-recommended` takes and logs the continuing option while a bounded wait, retry, or triage round remains. `ask` presents the listed choice. `workflow-state head-budget take` owns automatic retry spending, starting the count over on a changed head for review-wait only. At a cap, `workflow-state post-pr-stop record` atomically persists the named stop and renders its matching Markdown comment; the workflow posts that file to the PR and returns the stored stop. A nested caller uses `record-if-empty` so a precise upstream stop wins. Every continuing action clears the stop with `workflow-state update`. Initialize the resolved state key before these transitions. `ORCH_MERGE_AUTONOMY` controls merge consent only. - **The overseer reads results.** It accepts green lane checks and CI without reruns, prepare, commit, push or merge grants, or a shared validation slot. Only local [micro](workflows/micro.md) runs here; its commit chain validates it. Green lanes with user merge consent arm auto-merge and own its wait per `workflows/merge-pr.md`. Dev test-only validation-ceiling reports end validation. Lanes tick branch boxes with proving artifacts. It ticks post-merge boxes or parent outcomes only after reading proving artifacts at their revision and conditions: test output, screenshot, measured figure or deployed screen. Lane summaries are no proof. Containers close only after holders read their shared outcome at source, never on the last child. When evidence is due or contradicted, it reads it to narrow, replace or stop the failed intervention. A fix item is not the default. It gives no model or account instructions. Lanes keep launch models and launch no lanes. - **Item work stays in lanes.** A fleet is hosted when `lane-host resolve` prints anything except `local`. Overseers share its control VM for coordination. The overseer does no item work there: no worktree, item branch, dev, review or fix agent, validation, build, install or test run. Every item round goes to its branch's lane. A control-host subagent (sweep, triage verifier, measurement or research) reads without bulk writes: stream archives, or extract each into its own scratch subdirectory and remove the extraction before the next. Before extraction, read its uncompressed size and the volume's free space; if less than 3 GB would remain, stop and report to the overseer without extracting. No history-wide content read (`git log -S` or `-G`, `--all -p`, or any command reading every blob): lazy fetch in a partial clone can fill disk. Search via `gh search code`, the GitHub API, or a lane. No busy waits (`/dev/zero`, `/dev/urandom`, spin polls) on the shared host. Wait with one bounded background command and completion notice, `inotifywait` on a file, or watch events. Every control-host subagent brief includes this rule. Its scratch location is an empty subdirectory (`tmp///`) only that subagent removes, never one the overseer's background jobs read. Fleet guards read [command blocks](references/control-host-toolchain.conf). Refresh follows the [consumer's owner](references/oversee-events.md). No `--refresh-only` exception. diff --git a/.agents/skills/orch/references/communication-modes.md b/.agents/skills/orch/references/communication-modes.md index 03c645bb..98ecef33 100644 --- a/.agents/skills/orch/references/communication-modes.md +++ b/.agents/skills/orch/references/communication-modes.md @@ -1,6 +1,6 @@ # Communication modes -`ORCH_USER_MODE` names who an orch session is talking to. This file owns the ask set and the wording of the questions in it; nothing outside it narrows or widens that set, and a gate citing it states neither. +`ORCH_USER_MODE` names who an orch session is talking to. This file owns the ask set; nothing outside it narrows or widens that set, and a gate citing it states neither. For prose, read communication's [reader modes](../../communication/references/messages.md#reader-modes) and [questions](../../communication/references/questions.md). ```bash .agents/skills/orch/scripts/orch-env ORCH_USER_MODE ceo @@ -8,21 +8,19 @@ | Value | Meaning | |-------|---------| -| `ceo` | The session owns every technical decision. The user states intent and outcomes. Only a question in § Ask set reaches the user, worded as § The ceo question template requires | -| `engineer` | The package's original behaviour: the same ask set, worded as § The engineer question template requires | +| `ceo` | The session owns every technical decision. The user states intent and outcomes. Only a question in § Ask set reaches the user | +| `engineer` | The package's original behaviour, with the same ask set | ## Standing rulings | Ruling | What it means for a session | |--------|------------------------------| -| Technical decisions belong to the session | The user is told the outcome, never asked to pick a mechanism | -| The user is informed at a high level | A decision report names the outcome and its cost, not the parts that produced it | +| Technical decisions belong to the session | The session selects the mechanism | | A question is asked only where § Ask set puts it | Everything else is decided and recorded per § Recording | -| A question is framed as outcomes | Each path carries its gain, its cost and its odds, per path, in the template below | ## Ask set -These questions reach the user in both modes. Nothing else does. +These questions reach the user in both modes. Nothing else does. Use communication's [question wording](../../communication/references/questions.md) for the mode. A gate outside the set keeps its own option list under both modes and asks only where its autonomy key is set to `ask`. | Question | Reached by | |----------|-----------| @@ -46,33 +44,11 @@ Under `ceo` a composed key the settings ladder leaves unset takes the value belo Under `engineer` every key keeps its own default, listed in [README.md](../README.md) § Setup. -## The ceo question template - -```text -[WHAT THIS CHANGES FOR THE USER, ONE SENTENCE] - -**A. [OUTCOME OF THE FIRST PATH]** - -[ONE OR TWO PLAIN SENTENCES SAYING WHAT THE USER GETS, WHAT IT COSTS THEM AND HOW LIKELY THAT COST IS] - -**B. [OUTCOME OF THE SECOND PATH]** - -[ONE OR TWO PLAIN SENTENCES SAYING WHAT THE USER GETS, WHAT IT COSTS THEM AND HOW LIKELY THAT COST IS] - -**Recommended:** [A OR B], because [ONE SENTENCE IN OUTCOME TERMS]. -``` - -The template carries outcomes only. A question in the set names no mechanism the user does not act on, and no option by its internal name. A gate outside the set keeps its own option list under both modes and asks only where its autonomy key is set to `ask`. - -## The engineer question template - -```text -[QUESTION]: [OPTION_A] | [OPTION_B], with [RECOMMENDED_OPTION] recommended. -``` - ## Owner asks -An overseer's question to the owner is one owner ask: the template above for the mode, written to a file, sent with its form and its deadline as fields, never as prose. The template's recommendation is the option the ask records as `recommend`, the relay's Recommended line, and a question whose ask records none leaves it out. The chat shows one line naming the ask. `--wait` names one ask's minutes, and an ask without it takes `ORCH_ASK_WAIT_MINUTES`. Which forms record a recommendation, and what the deadline does for each, is the [lane-mail owner-channel contract](../../mailbox/scripts/lane-mail)'s. +An overseer's question to the owner is one owner ask: communication's [question template](../../communication/references/questions.md) for the mode, written to a file, sent with its form and its deadline as fields, never as prose. The template's recommendation is the option the ask records as `recommend` and the relay's Recommended line. The chat shows one line naming the ask. `--wait` names one ask's minutes, and an ask without it takes `ORCH_ASK_WAIT_MINUTES`. Which forms record a recommendation, and what the deadline does for each, is the [lane-mail owner-channel contract](../../mailbox/scripts/lane-mail)'s. + +An ask sent during the owner's night gets no reply before morning. An ask's recorded recommendation is the safe choice. Its deadline (`--wait`) falls after the owner's morning unless the ask can stand on that option. ```bash .agents/skills/mailbox/scripts/lane-mail ask --item overseer --to owner --options [OPTION_A],[OPTION_B] --recommend [RECOMMENDED_OPTION] --file [PATH] --issue [ITEM] --do [ACTION_AND_CLOSING_EVIDENCE] @@ -80,7 +56,7 @@ An overseer's question to the owner is one owner ask: the template above for the For an item ask, set `ORCH_OWNER_ASK_LABEL` and the owner email to enable the Linear route. `ORCH_OWNER_EMAIL` names the person and defaults to `KENDEX_USER_EMAIL`. The item supplies its own team. The overseer assigns that person, adds the label without replacing other labels, and posts the question as one plain comment. Its first line mentions that person by the Linear profile URL, built from the workspace key the tracker reports and the person's display name, so Linear notifies them. Then come the question text, its options, the recommendation or the reserved note with the deadline, the draft on a draft ask, the reply instruction, and a last line `Requested by` naming the asking overseer. The comment carries no ask header, ask id or Slack id: the posting record keeps the comment's id, and the watch finds replies after that comment. Linear sends the assignment notification. After the complete tracker question is confirmed, Slack posts one line: the owner mention, `Question from :`, the question's first line, the item link and its deadline, if any. A failed tracker write keeps the full chat question, options and deadline, and the pending ask names the failed operation as `tracker_cause`. It retains the item binding for cleanup and uses the chat deadline route. Unset settings report `lane-mail: tracker-unwritten issue= cause=settings-unset`. A failed settings read reports `cause=settings-unreadable`. An ask with no item stays on the chat route and creates no issue. -An item ask requires `--do TEXT`: plain words saying what the person does and what evidence closes it. A missing or empty action refuses as `owner-action-missing`, names `--do` as the fix and writes nothing. The label update also opens the description with `**, what you do:** `, a blank line, then the existing body. The first name comes from the Linear user the route assigns. A later ask replaces the opening line. The existing long watch pass restores a missing line from the ask's `do` field. +An item ask requires `--do TEXT`, worded as communication's [action requests](../../communication/references/questions.md#action-requests). A missing or empty action refuses as `owner-action-missing`, names `--do` as the fix and writes nothing. The label update also opens the description with `**, what you do:** `, a blank line, then the existing body. The first name comes from the Linear user the route assigns. A later ask replaces the opening line. The existing long watch pass restores a missing line from the ask's `do` field. The person answers with one comment on the issue and changes no state. `ok`, `yes` or `done`, alone and in any case, accepts the recommendation or approves the action a reserved ask proposes. Any other text is a change request. The overseer acts on that request and replies on the same issue. Each long watch pass reads new comments by that person's email after the ask's comment. Each comment ID is its delivery ID, so a repeated read delivers nothing new. A failed tracker read reports `KEN-3624-unread` and leaves the other checks running. @@ -101,7 +77,7 @@ An ask for the owner to approve a Slack message or an email sent as the owner is At `owner-ask-closed`, by any route including the watch's default close, the tracker route posts the ruling on the issue. Posting evidence retains the applied label, so close can clean up when settings are unset or unreadable. Each ask uses its recorded label. An older record without that label uses the configured label, never another ask’s recorded label. A legacy record cannot identify a label from earlier settings, so an unidentified historic label remains. If a closing or remaining legacy ask needs unavailable settings, close reports `tracker-unwritten` with the settings cause and leaves tracker ownership unchanged. The watch surfaces that diagnostic. Close removes its ask's label only when no remaining tracker-posted ask on that issue uses it. It keeps the labels of the remaining asks and unrelated item labels. While an ask remains, it keeps the assignee and shows the latest remaining ask's action. The watch finds owner replies through the remaining asks' recorded labels. After the last ask closes, close removes the assignee and opening action line. The overseer records the ruling per § Recording and sends `lane-mail notice --item overseer --to owner --ref [ASK_ID]` naming it, so a relay posts the ruling where the question was asked. -For a delivered owner request, `--ref` binds the reply to that request's delivery id through the [lane-mail owner-channel contract](../../mailbox/scripts/lane-mail). Answer it under the Reply row and Thread rule in [§ Owner messages](#owner-messages). +For a delivered owner request, `--ref` binds the reply to that request's delivery id through the [lane-mail owner-channel contract](../../mailbox/scripts/lane-mail). Answer it under the Reply row and Thread delivery in [§ Owner delivery](#owner-delivery). ## Opening question @@ -111,9 +87,7 @@ A session that starts with no item to work, no handoff file, no owner note and n .agents/skills/mailbox/scripts/lane-mail ask --item overseer --to owner --options idle,tracker --recommend idle --file [PATH] ``` -```text -What do you want to work on? Reply with issue ids or describe it, or answer tracker to take work from the tracker. With no answer by the deadline I wait for your reply. -``` +Use communication's [opening question](../../communication/references/questions.md#opening-question). `idle`, which stands at the deadline, launches nothing: the overseer keeps its watch running until the owner writes, and that empty queue is not [oversee.md § 5](../workflows/oversee.md#5-stop)'s Stop. `tracker` has it take work as [oversee.md § 2](../workflows/oversee.md#2-select-work) selects it. A reply naming issue ids or describing the work is an answer. The overseer closes with `resolve` when it has its ruling; a reply after the deadline arrives as an owner note. @@ -132,7 +106,7 @@ Next: [WHAT STARTS AFTER THAT] Waiting on you: [EACH OPEN QUESTION WITH WHAT ITS DEADLINE DOES AND WHEN, THEN EACH LANE BLOCKER, OR none] ``` -Under `engineer` a report is the same shape with the session's own vocabulary. The chat and the report file keep these rows. The owner's written summary takes [§ Owner messages](#owner-messages), not these rows. It opens with the repository's outcome readings, each with its date and source, reused from existing evidence comments and rulings. It opens with no Landed count. The Validation line per lane comes from that lane's workflow state `validate_rounds`, which `dev-artifact-check` and `worktree-push` write, so the owner sees what each round's and each restack's validation cost, and from its `restack_skips`, which [`merge-pr-restack.md`](../workflows/merge-pr-restack.md) step 2 writes, so the owner sees each restack that skipped its re-test, counted apart from the runs. The Rounds row uses the five counts defined in [oversee-events.md § lane-long](oversee-events.md#event-kinds). It reads `Rounds: none` with no running lane. The Escapes line is `oversee-report --help`'s count, so the owner sees whether one review cycle before the pull request lets more defects through. A bug issue counts only through its `Regressed-by: #N` line, which [issue-description-template.md](../../project-management/templates/issue-description-template.md) writes where the pull request that caused the defect is known; an issue that names a pull request only as its source is not an escape. The Use 1 line counts the fleet log's `use1` rows, which the overseer writes under [copilot-head-notices.md § Use 1 rows](copilot-head-notices.md#use-1-rows), one row per head approved through a Copilot head notice or the `awaiting-stale` fallback, so the owner sees each such head's route: approved by Copilot on re-request, overseer fallback, or declines on an unchanged head. Waiting on you is the unresolved owner asks `lane-mail pending --item overseer --to owner` lists, one record for the report, the relay and the chat. +The chat and the report file keep these rows. For the owner's written summary, read communication's [reports and template](../../communication/references/reports.md). `scripts/oversee-report write` prints findings about tracker links, Waiting on you, the word limit and the item-line cap, then sends on the writer's word; its `--help` defines the keyed output. The Validation line per lane comes from that lane's workflow state `validate_rounds`, which `dev-artifact-check` and `worktree-push` write, so the owner sees what each round's and each restack's validation cost, and from its `restack_skips`, which [`merge-pr-restack.md`](../workflows/merge-pr-restack.md) step 2 writes, so the owner sees each restack that skipped its re-test, counted apart from the runs. The Rounds row uses the five counts defined in [oversee-events.md § lane-long](oversee-events.md#event-kinds). It reads `Rounds: none` with no running lane. The Escapes line is `oversee-report --help`'s count, so the owner sees whether one review cycle before the pull request lets more defects through. A bug issue counts only through its `Regressed-by: #N` line, which [issue-description-template.md](../../project-management/templates/issue-description-template.md) writes where the pull request that caused the defect is known; an issue that names a pull request only as its source is not an escape. The Use 1 line counts the fleet log's `use1` rows, which the overseer writes under [copilot-head-notices.md § Use 1 rows](copilot-head-notices.md#use-1-rows), one row per head approved through a Copilot head notice or the `awaiting-stale` fallback, so the owner sees each such head's route: approved by Copilot on re-request, overseer fallback, or declines on an unchanged head. Waiting on you reads the unresolved owner asks from `lane-mail pending --item overseer --to owner`, one record for the report, the relay and the chat. Format it under communication's [Waiting on you](../../communication/references/reports.md#waiting-on-you). ## Owner-only verification @@ -146,97 +120,46 @@ Route each due or overdue post-merge box by who can read its evidence: A delegate notice creates no owner ask. Each overseer owns a verification ask through closure. -## Owner messages +## Owner delivery -This standard holds for the Jarvis session and every overseer: each post the relay makes for a `to=owner` envelope, each `slack post`, and each notice or ask for the owner. A message only a session reads, such as a `lane-mail send` to a lane, keeps its full detail. +Read [communication](../../communication/SKILL.md) before each post the relay makes for a `to=owner` envelope, each `slack post`, and each notice or ask for the owner. This route holds for the Jarvis session and every overseer. A message only a session reads, such as a `lane-mail send` to a lane, keeps its full detail. ### Routing -For the Jarvis session and every overseer, a conversation stays in the medium where it takes place. A voice call's replies go to the call only. Progress reports and scheduled messages go to every open text medium (Slack and terminal), never the phone. +Progress reports and scheduled messages go to every open text medium (Slack and terminal), never the phone. Replies follow communication's [medium and threads](../../communication/references/messages.md#medium-and-threads). | Message | Where | When | Mention | |---|---|---|---| -| Decision needed | Slack and chat | At the moment the question exists: one question per message, with the options, in the ceo template. A question only in the chat has not been asked. | Yes | +| Decision needed | Slack and chat | At the moment the question exists, through § Owner asks. A question only in the chat has not been asked. | Yes | | Critical notice | Slack and chat | A failure that stops work, loses data or money, or needs the owner within the hour. | Yes | -| Progress report | Slack and chat | The Jarvis session every hour, an overseer by `ORCH_REPORT_EVERY_MINUTES` ([Settings](../README.md#setup)), while the session runs, and before a succession. `oversee-report` still writes and prints during `ORCH_REPORT_QUIET_HOURS` (default midnight to 7 am in `ORCH_OWNER_TIME_ZONE`, default `America/Los_Angeles`), but sends no owner notice. Empty quiet hours turns suppression off. The first due report after the window sends the morning brief: **Landed**, **Running**, **Blocked** and **Waiting on you** cover the work since the last report sent to the owner, including overnight merges. Decisions needed and critical notices remain immediate. | No | -| Reply | Where the owner's message arrived | An answer to an owner message. A reply on Slack shows in the chat as at most one line naming the post. | No | +| Progress report | Slack and chat | The Jarvis session every hour, an overseer by `ORCH_REPORT_EVERY_MINUTES` ([Settings](../README.md#setup)), while the session runs, and before a succession. `oversee-report` still writes and prints during `ORCH_REPORT_QUIET_HOURS` (default midnight to 7 am in `ORCH_OWNER_TIME_ZONE`, default `America/Los_Angeles`), but sends no owner notice. Empty quiet hours turns suppression off. The first due report after the window sends the morning brief under communication's [summary shape](../../communication/references/reports.md#summary-shape), covering the work since the last report sent to the owner, including overnight merges. Decisions needed and critical notices remain immediate. | No | +| Reply | As communication's medium rule requires | A reply on Slack shows in the chat as at most one line naming the post. | No | -- Nothing else goes to Slack: no acknowledgement, no mechanism, no history. The same routing holds for every overseer. -- Threads: a reply goes in the thread of the owner message it answers, or of the thread that message sits in; later posts on the same topic stay in that thread until the owner moves to another topic. A new topic, a decision needed, a critical notice and the progress report start at the top level. One topic per post, so the owner can answer each in its own thread. Thread replies stay in their threads. -- An owner message that arrives with a thread pointer is read with that thread only; the Jarvis session reads the thread's history on demand, never the channel's. +- Only these message classes go to Slack. The same routing holds for every overseer. +- The `report-due` summary ([oversee-events.md § Event kinds](oversee-events.md#event-kinds)) reaches Slack as the report file's comment only. The chat and report file keep [§ Status report](#status-report) and carry no summary. +- The Slack relay links bare tracker ids as a backstop, including Linear ids. +- Deliver an image with `slack post --file`, adding `--thread TS` for a reply. -### Thread rule +### Thread delivery +- Give each answered owner message its own notice and `--ref`. Apply communication's [thread rule](../../communication/references/messages.md#medium-and-threads) to its text. - Answer a note typed in the pane in the pane only. Answer a Slack-delivered mailbox note with `lane-mail notice --item overseer --to owner --ref [DIRECTIVE_ID] --file [PATH]`; the pane shows at most one line naming the Slack post. A directive carrying `thread_ts` takes this notice, which keeps the reply in its thread. An owner's typed yes approves per [§ Voice requests](#voice-requests). A `slack post` text reply takes `--thread TS`. Answer a voice request per [§ Voice requests](#voice-requests). +- The Jarvis session reads a thread's history on demand through Slack's thread route. - The Slack relay delivers the whole owner/app thread up to the note in `parent.thread` on the first delivery to a reader generation. Later deliveries carry only messages since that generation's mark. Other users' messages and answers already delivered individually to that generation are excluded from every delivery. - Read the delivered `parent.thread` in full. Nothing is read twice within the same applicable revision. Make no further Slack read unless required history is missing; then use `slack thread TS [--limit N]`, where TS names the root or a reply. -### Words +### Owner setup -1. Write in ASD-STE100 Simplified Technical English. Put the answer first. -2. Say what happened and what it means for the work. Name no generation number, pane id, token count, seat name, mailbox id or internal rule name unless the owner must act on it. -3. Write a time in the owner's time zone with am or pm (`9:29 pm`), never as a `Z` stamp. -4. Write each pull request, commit, issue and tracker item as a Markdown link labelled with its short name: `[REPO#N](https://github.com/OWNER/REPO/pull/N)`, `[SHORT_SHA](https://github.com/OWNER/REPO/commit/SHORT_SHA)`, `[KEY-N](TRACKER_ISSUE_URL)`; beside a file, the mrkdwn form below. The Slack relay links bare tracker ids as a backstop, including Linear ids. Never put a tracker id in a code span: code stays literal and reaches the owner unlinked. -5. Every written owner message starts with what changed for the owner. Follow the [summary shape](#summary-shape) below. Each work item links to its owning tracker issue URL: a Linear issue URL for a Linear item, or the GitHub issue URL for an `issue-N` item. Never use a pull request or commit link. The tracker issue links to its pull request. Say the outcome for the owner or the fleet, not the issue title. End with **Waiting on you**, with `Nothing` when empty. Put detail in the report file. Send one post per report, never a thread of fragments. Answer each owner message in its own thread with its own `--ref`. Keep one topic per thread. If a fact answers two messages, give a short answer in each thread. The `report-due` summary ([oversee-events.md § Event kinds](oversee-events.md#event-kinds)) reaches Slack as the report file's comment only. The chat and the report file keep [§ Status report](#status-report) and carry no summary. The Routing table controls what also appears in the chat. -6. **Waiting on you** there names each ask `lane-mail pending --item overseer --to owner` shows by its question, so the owner finds its thread in the channel, and what its deadline does, at a time in the owner's time zone. It is never empty while an ask is open. -7. An ask sent during the owner's night gets no reply before morning. An ask's recorded recommendation is the safe choice. Its deadline (`--wait`) falls after the owner's morning unless the ask can stand on that option. -8. State a cost as its figure and its source, never as "a cost": "$0.106 per compute-hour, about $19 a month, Neon pricing page". Estimate added CI time against the 50,000 private-repository minutes a month the plan includes. -9. Create nothing half-finished. Give each app, bot, account, channel or key its avatar, its name under the naming convention and its description when it is created. -10. Report account headroom for every harness the fleet runs (Claude, Codex, Copilot), side by side. -11. Own a mistake in one line, with its repair. -12. Attach a screenshot or an image when it shows the point better than words: `slack post --file`, with `--thread TS` to place it under a message. -13. Give every number the owner reads its yardstick and its verdict in the same bullet: the earlier value, the target or the normal range; good, bad or not known; and what is done about it. When the yardstick is not read yet, say so and name the reading that settles it (the owner's Slack messages 1792172820, 1792172887 and 1792172957; Jarvis note 1792173119). -14. Report a measure that depends on load against that load: a lane's or session's length beside the work it handled, a machine's use beside what ran on it. Length or use alone never claims an improvement (the owner's Slack messages 1792172820, 1792172887 and 1792172957; Jarvis note 1792173119). -15. Before posting, read each topic once as the owner and ask "so what for me?". A topic whose text does not answer that gets the answer or is cut (the owner's Slack messages 1792172820, 1792172887 and 1792172957; Jarvis note 1792173119). - -Markup for a text posted alone, standard Markdown: - -- A blank line between paragraphs, before and after every list, and before every label. -- A numbered list for steps or options; bullets for parallel facts. -- Bold for a label or a decision; italics seldom. -- Inline code for a command or a path; a code block for output of more than one line. Tracker ids follow rule 4. -- No paragraph longer than a few sentences. - -A text sent beside a file, the comment of `slack post --file` or the `report-due` notice's summary, renders as Slack's mrkdwn markup, not standard Markdown. Write bold there as `*Label*`, a link as ``, and a list as plain lines; the other markup rules hold. - -### Summary shape - -- Put one item per line, at most 20 words. A line may carry two links. -- Put a blank line before each label. Each label stands alone: **Landed**, **Running**, **Blocked**, **Waiting on you**. -- Put each figure, such as account headroom or a count, on its own line. Put rule 10's headroom lines in their own group after the opening outcome readings. -- Use at most `ORCH_REPORT_SUMMARY_LINES` item lines, default 20. Blank lines, labels and the first opening line do not count. Leave excess items in the report file. Never pack a line to fit the cap. -- Use no table in an owner message. - -### Owner summary template - -Use this mrkdwn template for the report file's comment. For a post without a file, use the standard Markdown markup above. `scripts/oversee-report write` prints each finding about tracker links, the Waiting on you section, the word limit or the item-line cap and sends on the writer's word; its `--help` defines the keyed output. - -```text -[DATE]: [REPOSITORY OUTCOME READING] () -[DATE]: [REPOSITORY OUTCOME READING] () - -[ACCOUNT HEADROOM FIGURE] - -*Landed* -- [OUTCOME] () - -*Running* -- [OUTCOME IN PROGRESS] () - -*Blocked* -- Nothing - -*Waiting on you* -- Nothing -``` +Create nothing half-finished. Give each app, bot, account, channel or key its avatar, its name under the naming convention and its description when it is created. ### Voice requests +Read communication's [voice wording](../../communication/references/voice.md) before replying. + - While working a voice request, send one short progress notice per long step with `--progress --ref [REQUEST_ENVELOPE_ID]`. This is a report Jarvis may speak or hold. Send the final reply once without `--progress`. - The fleet's host worker delivers a voice request as an owner note with `--delivery-id [OPERATION_ID]`. Its envelope carries `delivery_id`. The directive's first line is `voice-request: caller=... operation=... conversation=... provenance=...`. The caller is its `caller=` value, never a name the transcription states. An employee caller cannot approve a step only the owner may approve. -- Start the reply with the answer in one or two spoken sentences. Use plain spoken words, no Markdown and no links. Say numbers as a person says them. Name an id only when the caller must act on it. End the spoken paragraph with one question or next step. -- The reply contains the spoken answer only. Reply with `lane-mail notice --item overseer --to owner --ref [REQUEST_ENVELOPE_ID] --file [PATH]`; the reference binds the reply to the request. An owner ask raised while answering the request sets `--ref [REQUEST_ENVELOPE_ID]` too, so the owner's answer binds to the call. The call's outcome appears in the next progress report. -- The owner's plain approval counts: a yes typed in Slack, or spoken on a call whose caller is the owner. A plain yes answers the ask it replies to (an ask bound with `--ref`, or a reserved or draft ask in [§ Owner asks](#owner-asks)) or approves a step no ask named. Whatever it answers, a step the next rule names waits for that rule's confirmation. A yes to a draft ask approves only the exact text whose `text_hash` that ask carries, so an edited text needs a new ask. Before acting, say the exact action back in one sentence, such as "Sending the welcome email now". No code, on-screen card or option word is needed. +- Reply with `lane-mail notice --item overseer --to owner --ref [REQUEST_ENVELOPE_ID] --file [PATH]`; the reference binds the reply to the request. An owner ask raised while answering the request sets `--ref [REQUEST_ENVELOPE_ID]` too, so the owner's answer binds to the call. The call's outcome appears in the next progress report. +- The owner's plain approval counts: a yes typed in Slack, or spoken on a call whose caller is the owner. A plain yes answers the ask it replies to (an ask bound with `--ref`, or a reserved or draft ask in [§ Owner asks](#owner-asks)) or approves a step no ask named. Whatever it answers, a step the next rule names waits for that rule's confirmation. A yes to a draft ask approves only the exact text whose `text_hash` that ask carries, so an edited text needs a new ask. Use communication's [action acknowledgement](../../communication/references/voice.md#action-acknowledgement) before acting. No code, on-screen card or option word is needed. - Explicit confirmation stays only for a destructive or irreversible step (a delete, a force-push, a revoke, an offboard) and for money (a payment, a purchase, new spending). On a call, the step waits for the caller's on-screen Approve, bound to the exact operation id and the caller. Act only on the host worker's approval record that names both and the on-screen provenance. For such a step the overseer reads `approved_by` and `approval` from the directive's first line. A directive missing either field, or whose `approval` is not `on-screen`, approves nothing. In Slack, the step waits for a typed yes to a message that names the step. A transcription alone and a yes to anything else confirm no such step. A correction voids an earlier confirmation; the corrected step needs a new one. ## Handoff @@ -273,7 +196,7 @@ Drop each closed tracker id from State. Keep its completion evidence on the item Standing procedures and traps go to the orch skill through a lane. Record rulings and filing history in the fleet log under [§ Recording](#recording). Verifying checks and readings stay on their tracker items; `oversee-watch` prints them. Owed items and acceptance lines stay in the tracker, with dispatch order in `launch_queue`. Item context, measured facts and failed approaches stay on the item they serve. Open exchanges stay in their mailboxes, read live. Before replacing a predecessor handoff, move records outside session state to these homes or confirm that their homes already retain them. A failed destination read or write leaves the handoff and progress log untouched. -[oversee.md](../workflows/oversee.md) § 5 uses this shape. This file's stance is not copied into a handoff. Its owner summary uses [§ Owner messages](#owner-messages). +[oversee.md](../workflows/oversee.md) § 5 uses this shape. This file's stance is not copied into a handoff. Its owner summary uses communication's [reports](../../communication/references/reports.md). ## Recording diff --git a/.agents/skills/orch/references/oversee-events.md b/.agents/skills/orch/references/oversee-events.md index 92fef554..5e6a74fa 100644 --- a/.agents/skills/orch/references/oversee-events.md +++ b/.agents/skills/orch/references/oversee-events.md @@ -22,7 +22,7 @@ The overseer owns fleet judgement, not just liveness; every `oversee.md` § 4 ev - **Fix the source.** The same finding class on a third PR is a mechanism gap: file it and route the smallest deterministic check (a guard lane, a preflight rule, a refusing script) or one sentence in the owning skill through a lane as its own item — the overseer still implements nothing. Deterministic beats prose where it stays simple; complex or brittle machinery is worse than either. A package or workflow gap is never a harness memory or a local note: a lane's is a proposal ([skill-rules.md § Coordination, Tracked issue creation](skill-rules.md#coordination)), and the overseer's own is filed as File one item alone below states. - **File one item alone.** Before filing, read [Design review](design-review.md). One item the overseer files itself, a class under Fix the source above or an issue an `owner-note` asks for, goes through [audit-issues](../../project-management/workflows/audit-issues.md) as `audit-issues --single [FILE_PATH]`, the file holding that one item per [audit-issues-input.md](../../project-management/schemas/audit-issues-input.md) with `source: "oversee"`, `parent_issue: null` and the fleet's `tracker`. After filing, append one fleet-log `ruling` whose text starts `filed ` and names the filed item, its Location file(s) and its defect-class rule, stated as the rule every site breaks. `--issues` is for a batch: its TPM run sweeps the whole backlog for cancellations. - **Rule once for the fleet.** A ruling that answers one lane's question is sent to every lane in the same situation and recorded in the fleet log. -- **Held merges.** Under `ORCH_MERGE_AUTONOMY=ask` (`oversee.md` § 3) the lane's merge question arrives as `lane-question`. Read the gate results without reproducing them, then relay the question to the user, worded as [communication-modes.md](communication-modes.md) requires. Send `MERGE` to the lane only after the user authorizes it, or send exactly one directive the user gave. A directive may carry the authorization ("with that landed, MERGE stands"), and the lane then merges once the change is in without a second answer. Under `ask` a `disarmed` pr-watch line on a `land=lane` record is not a wake; on a running `land=handoff` record it launches the landing lane (`pr-watch` below). +- **Held merges.** Under `ORCH_MERGE_AUTONOMY=ask` (`oversee.md` § 3) the lane's merge question arrives as `lane-question`. Read the gate results without reproducing them, then relay the question to the user, worded as communication's [questions](../../communication/references/questions.md) requires. Send `MERGE` to the lane only after the user authorizes it, or send exactly one directive the user gave. A directive may carry the authorization ("with that landed, MERGE stands"), and the lane then merges once the change is in without a second answer. Under `ask` a `disarmed` pr-watch line on a `land=lane` record is not a wake; on a running `land=handoff` record it launches the landing lane (`pr-watch` below). - **Lanes merge their own pull requests.** A lane whose gates read met merges its own head by [merge-pr.md](../workflows/merge-pr.md) § 5 step 1, where `pr-merge` picks the route. The overseer runs no normal merge for a lane. Its own GitHub App acts for the head approvals [copilot-head-notices.md](copilot-head-notices.md) sets, and for nothing else except an emergency merge in a consumer whose ruleset lists that app as a bypass actor, which that step's "Who acts" names. A merge group that cannot pass because a CI input read from the default branch broke takes the recovery route in [review-gate SKILL.md § 4. Operations](../../review-gate/SKILL.md#4-operations). - **Hand off a lane before it runs out.** The `lane-mail-check` turn-end hook reads the lane's context through its harness adapter, from the transcript, or on Copilot CLI from the reading its kendex Copilot extension recorded from Copilot's `session.usage_info`, against the limit Copilot compacts at, and where none stands from Copilot's statusLine session record ([copilot-runtime.md](copilot-runtime.md#measurement)), and its account headroom on its own credential, and refuses the turn end at either mark until the record below stands, so a lane hands itself off with no directive. Copilot honours a turn-end block 8 times in a row and then ends the turn unheld; the refusal returns at the session's next turn end. What follows is the BACKSTOP for a lane whose hook refused nothing, such as one past its account mark with no turn end since. On the `oversee.md` § 1 tmux surface, at every `oversee.md` § 4 event, read each live lane's context use: @@ -75,7 +75,7 @@ A lane's successful direct-push completion takes [§ Direct-push cycle records]( To wake a lane below is to send it the directive and wake it per `oversee-lanes.md` § Talking to a lane, which wakes only a Claude Code or Codex lane whose send receipt reads `monitor=none`. -- `merged` → the PR is in; the owning lane finishes `merge-pr.md` § 5 on its own and a GitHub merge alone is not lane completion. A parked or stopped item that the close command judges terminal gets its cycle record from the watch before terminal close. A parked record whose pull request is open or queued stays parked, whatever the tracker state. A resumed record whose retained PR is OPEN also stays in the fleet, including after failed create leaves it stopped; [workflow-state.md](../schemas/workflow-state.md#oversee-state) owns the retained identity. A parked Done item with an unchecked Done-when box takes the parked-merged rule after its recorded pull request merges. A stopped Done item with an unchecked box also stays open for Recovery relaunch, including after a parked resume starts the sandbox but fails to create the harness. The watch reports a recorder refusal through `lane-close-failed item=[ITEM] step=cycle exit=[N]` and continues close. It uses the recorded launch tier and does not invent a missing tier. Read its cycle output under the verdict rules below. The class target forgives one clean final-head CI run and the merge group. `oversee-cycle --help` owns the class bases. The cycle row keeps lane-controlled time as `lane=` and end-to-end open-to-merge time as `open=`. The rollup and progress report show both medians and the miss share on lane-controlled time. The cycle row is the report for a Done item with no open box; no lane completion check or relaunch is required. A parked item with work left takes the `parked-merged` rule, which records the cycle once relaunch brings its sandbox up. For a running item, first, before any step below and while the lane's own workflow state still stands, record the lane's cycle from the overseer's base checkout, or from a checkout of the lane's repository where its `mail_root` is another repository's worktree, as `oversee.md` § 3 runs `lane-mail` for it: `.agents/skills/orch/scripts/oversee-cycle --state-dir [OVERSEE_STATE_DIR] record --pr [PR_NUMBER] --tier [TIER] [ITEM_KEY]`, `[TIER]` being what `oversee.md` § Item Tier gives the item, and `--repo [OWNER/REPO]` added for a lane whose record names none in another repository. It logs its own row. A `verdict=miss` line needs nothing more; a `repeat-miss` line is three lanes missing on one phase, and files one CI or process issue in that repository naming the phase, the lanes and the `causes` the line gives each, per [skill-rules.md § Coordination](skill-rules.md#coordination). A refusal is reported and never blocks the rest of this rule. A hosted item stays in the watch until its `lane-closed` or `lane-close-refused` event, per § Event kinds. Wake it only if it is not still inside that run, and read a reported failure there rather than advancing the item. For a parked or stopped item this rule ends here. Items the close command judges terminal close in the watch. A parked item with work left gets `parked-merged` and its resumed lane runs `merge-pr.md` § 5 steps 2-6. For an item that is not parked, follow the repository's declared refresh owner in its consumer instructions. On a hosted fleet, run `.agents/skills/orch/scripts/sync-base` in the control checkout. The first sync can receive the item merge before the owner's refresh commit exists; it is not refresh completion. Keep refresh and verification with the declared owner outside the control host, and run `sync-base` again after its reviewed outputs merge. Report a failed owner workflow. Consumer refresh stays in each consumer's own Actions through the [refresh workflow](../../review-gate/references/adoption.md). On a local fleet, run `.agents/skills/orch/scripts/post-merge --command-only` in the overseer's base checkout when a declared workflow owns refresh. When the local fleet is the refresh owner, run `.agents/skills/orch/scripts/post-merge` without a mode flag. After either local mode succeeds, run the repo's lifecycle check. All post-merge modes retain checkout changes; report those diffs to their declared owner. A later sync can refuse pending changes; report that refusal and preserve the changes. Stop on a failed step and report its status. When the fleet's LAST item completes, run the `heartbeat` triage pass before closing out, whatever the tracker; items living in Linear also get `.agents/skills/orch/scripts/reconcile-work-items` (a GitHub-item fleet skips that with a note). Report both with the close-out. +- `merged` → every PR the watch reported `refresh-ready` gets `EVENT merged kendex/refresh ` at its merge, once across restarts. This line triggers the base-move check for open lane PRs whose files the refresh changed. Approval while open and an unmerged close print no merged line. A refresh has no owning lane; handle its base-move check and follow the repository's declared refresh owner. For an item PR, the PR is in; the owning lane finishes `merge-pr.md` § 5 on its own and a GitHub merge alone is not lane completion. A parked or stopped item that the close command judges terminal gets its cycle record from the watch before terminal close. A parked record whose pull request is open or queued stays parked, whatever the tracker state. A resumed record whose retained PR is OPEN also stays in the fleet, including after failed create leaves it stopped; [workflow-state.md](../schemas/workflow-state.md#oversee-state) owns the retained identity. A parked Done item with an unchecked Done-when box takes the parked-merged rule after its recorded pull request merges. A stopped Done item with an unchecked box also stays open for Recovery relaunch, including after a parked resume starts the sandbox but fails to create the harness. The watch reports a recorder refusal through `lane-close-failed item=[ITEM] step=cycle exit=[N]` and continues close. It uses the recorded launch tier and does not invent a missing tier. Read its cycle output under the verdict rules below. The class target forgives one clean final-head CI run and the merge group. `oversee-cycle --help` owns the class bases. The cycle row keeps lane-controlled time as `lane=` and end-to-end open-to-merge time as `open=`. The rollup and progress report show both medians and the miss share on lane-controlled time. The cycle row is the report for a Done item with no open box; no lane completion check or relaunch is required. A parked item with work left takes the `parked-merged` rule, which records the cycle once relaunch brings its sandbox up. For a running item, first, before any step below and while the lane's own workflow state still stands, record the lane's cycle from the overseer's base checkout, or from a checkout of the lane's repository where its `mail_root` is another repository's worktree, as `oversee.md` § 3 runs `lane-mail` for it: `.agents/skills/orch/scripts/oversee-cycle --state-dir [OVERSEE_STATE_DIR] record --pr [PR_NUMBER] --tier [TIER] [ITEM_KEY]`, `[TIER]` being what `oversee.md` § Item Tier gives the item, and `--repo [OWNER/REPO]` added for a lane whose record names none in another repository. It logs its own row. A `verdict=miss` line needs nothing more; a `repeat-miss` line is three lanes missing on one phase, and files one CI or process issue in that repository naming the phase, the lanes and the `causes` the line gives each, per [skill-rules.md § Coordination](skill-rules.md#coordination). A refusal is reported and never blocks the rest of this rule. A hosted item stays in the watch until its `lane-closed` or `lane-close-refused` event, per § Event kinds. Wake it only if it is not still inside that run, and read a reported failure there rather than advancing the item. For a parked or stopped item this rule ends here. Items the close command judges terminal close in the watch. A parked item with work left gets `parked-merged` and its resumed lane runs `merge-pr.md` § 5 steps 2-6. For an item that is not parked, follow the repository's declared refresh owner in its consumer instructions. On a hosted fleet, run `.agents/skills/orch/scripts/sync-base` in the control checkout. The first sync can receive the item merge before the owner's refresh commit exists; it is not refresh completion. Keep refresh and verification with the declared owner outside the control host, and run `sync-base` again after its reviewed outputs merge. Report a failed owner workflow. Consumer refresh stays in each consumer's own Actions through the [refresh workflow](../../review-gate/references/adoption.md). On a local fleet, run `.agents/skills/orch/scripts/post-merge --command-only` in the overseer's base checkout when a declared workflow owns refresh. When the local fleet is the refresh owner, run `.agents/skills/orch/scripts/post-merge` without a mode flag. After either local mode succeeds, run the repo's lifecycle check. All post-merge modes retain checkout changes; report those diffs to their declared owner. A later sync can refuse pending changes; report that refusal and preserve the changes. Stop on a failed step and report its status. When the fleet's LAST item completes, run the `heartbeat` triage pass before closing out, whatever the tracker; items living in Linear also get `.agents/skills/orch/scripts/reconcile-work-items` (a GitHub-item fleet skips that with a note). Report both with the close-out. - `parked-merged [ITEM] pr=[N] repo=[OWNER/REPO]` → the wait PR merged and the item has work left. A dependency park selects `parked.until_pr`, even with no own `parked.pr`. Its own PR merge cannot clear that wait. A queue park selects `parked.pr`. Relaunch through [lane-directive.md § Recovery relaunch](lane-directive.md#recovery-relaunch). The launcher starts the sandbox before resume. It reports `host-start-failed` and keeps the record parked if the provider does not confirm the start. A lane that resumes without a transcript is a blocker to report. For a dependency park, the lane rebases and continues the held step. Record no cycle for the dependency's merge. For a queue park, record the item's cycle under `merged` once the sandbox is up. The lane finishes `merge-pr.md` § 5 steps 2-6 and § 6. The watch repeats this hand before each heartbeat while the record still reads parked. Recovery relaunch rewrites the record before harness creation, so replay cannot start a second harness. Report a capacity refusal and handle the next repeat. - `parked-closed [ITEM] pr=[N] repo=[OWNER/REPO]` → the dependency PR closed without merging. The watch reports it once. Resolve the hold or resume the lane through the same Recovery relaunch route. - `lane-exited` → the window is alive but the harness under it is gone (the lane's closing lines follow the event and say why; `payload-noise-only lines=N` in their place means the lane deleted its own worktree and the shell has drawn nothing since). A lane stopped by a harness session limit ("You've hit your session limit · resets 9:50am") is not dead: resume it under another auth lane (`lanes pick --harness [HARNESS] --model [MODEL]` for the model the replacement will run, then [lane-directive.md § Recovery relaunch](lane-directive.md#recovery-relaunch)), or wait for the shown reset and use Recovery relaunch on the original account. The relaunch carries its own continuation line, except on a hosted codex lane, which resumes without one and takes it by Pane paste ([lane-directive.md § Recovery relaunch](lane-directive.md#recovery-relaunch)). A lane that reported `handoff` on an earlier run is relaunched per that event, not resumed or nudged. Any other exit is the `window-gone` rule below. @@ -109,17 +109,17 @@ To wake a lane below is to send it the directive and wake it per `oversee-lanes. - `cloud-stall-closed [ITEM] directive_age=[SECONDS]` → a stalled cloud lane left its recorded directive unanswered for `ORCH_CLOUD_STALL_MINUTES`, nothing pushed since, and the watch closed it through `lane-close`, whose `lane-closed` lines come before this one and whose fleet-log `close` row names the send's result, the CLI's words and the credit reading. Archive nothing yourself: report the session id to the owner, who archives it. Relaunch the item as a hosted lane on its branch: choose the host under [oversee.md § 3 Placement](../workflows/oversee.md#3-launch), never `claude-cloud`, and use [lane-directive.md § Recovery relaunch](lane-directive.md#recovery-relaunch) with `--host [HOST]`. With no session on that host to resume, the relaunch renders the `start` template and runs the standard cycle on the branch the cloud lane left. Name the fleet-log cause in the relaunch's own `ruling` row. - `lane-long [ITEM] age=[SECONDS] review_rounds=[COUNT] fix_receipts=[COUNT] validation_runs=[COUNT] restacks=[COUNT] repeated_class_rounds=[COUNT] stage=[STEP]` → a `running` or `parked` lane is `ORCH_WATCH_LANE_AGE_SECS` past its record's `launched_at` (default 12600 seconds, 3.5 hours), which `--relaunch` and handoffs keep and a fresh launch after `lane-close` renews; `stage=` is the `Step` line of its status file, `parked`, `unread` or `none`. The repeat schedule is `oversee-watch --help` § `EVENT lane-long`. `review_rounds=` adds the first internal review panel, re-review cycles and comment-review iterations from workflow state. `fix_receipts=` counts `stages` entries whose `kind` is `fix`, not `cycles`, which can count fixed items. `validation_runs=` counts each `dev-validate-run` start in the lane worktree, including finished, bounded and running runs before round acceptance. Restack validation runs count too. The runner publishes its start inventory at `tmp/validation-runs`; its help defines the file. A missing, unreadable or invalid inventory reads `unread`. `restacks=` reads workflow state `restacks`, one per completed restack whatever validation route followed it ([workflow-state.md](../schemas/workflow-state.md)). `repeated_class_rounds=` counts later distinct patch commits that repeat an equal cause or a shared location/owner key in `pr_comment_review.patched_causes`, once per commit, across internal and comment reviews. The optional `owner` comes from the item's `Owner:` line. Key equality is the [dev-round schema](../schemas/dev-round.md)'s contract. This count covers recorded patches only; it cannot show a review that recorded no class. With no patch entry, `repeated_class_rounds` reads `unread`. With no `stages` list, `fix_receipts` reads `unread`. An absent `restacks` field counts as zero. All five counts read `unread` when state is absent or unread, the lane writes no files, or it is parked. The watch reads no parked lane file. For any `stage=` but `parked`, read the lane record: its status file per `oversee.md` § Bounded lane reads, its workflow state, and its pull request's `github.sh pr-timeline`. A `parked` lane's disk is stopped, so read none of its files: read the overseer's own lane record, its `parked` `{pr, head, repo, at}` and `pauses`, and that pull request's `github.sh pr-timeline`; a park happens only in [merge-pr.md](../workflows/merge-pr.md) § 5 step 1's queue wait, so the cause is the merge queue or the time before the park. Before naming the cause, apply [Design review](design-review.md) when its trigger holds, including its wider read for missing counts. Name the cause: long tests, a stuck state or wait, a review loop, scope growth, or the merge queue. If no design review starts, record the cause in the fleet log as a `ruling` whose text starts `long-reason`. Where the cause is in the system, not in this one item, file its source fix under Fix the source in § Judgement rules. - `window-gone`, or any lane whose session ended with no merged PR → inspect its worktree and PR state, then re-launch once with the same brief through [lane-directive.md § Recovery relaunch](lane-directive.md#recovery-relaunch). Without `--relaunch`, the existing worktree reads as another session's claim and the item is skipped. The launcher starts from the normal brief only when no matching transcript exists. A second death is surfaced to the user, not retried. After the relaunched lane finishes, close it through `lane-close`; do not reconstruct the pane, host, and state steps by hand. -- `lane-question` → the lane's own question, and the only shape one arrives in. Answer it when available evidence already decides it, apply the ruling, record it in the fleet log, and send the answer back per `oversee-lanes.md` § Talking to a lane. Repo state, the issue body, a stated convention, scope-narrowing calls subject to [requirement-change review](design-review.md#inputs-and-actions), and a lane's own well-argued recommendation are available evidence. A pure cut back to main's behaviour, or a cut of surface the Done-when does not need, takes no table. Relay any other question to the user only where [communication-modes.md](communication-modes.md) § Ask set puts it, worded as that file requires. A merge question under `ORCH_MERGE_AUTONOMY=ask` follows Held merges above and always goes to the user. Every emitted question is answered: the lane is blocked in `lane-mail wait` on this line. An overseer resuming a fleet reads what it still owes with `lane-mail pending --item [ISSUE_ID]`, adding `--root [MAIL_ROOT] --host` for a lane whose record puts it on another host. +- `lane-question` → the lane's own question, and the only shape one arrives in. Answer it when available evidence already decides it, apply the ruling, record it in the fleet log, and send the answer back per `oversee-lanes.md` § Talking to a lane. Repo state, the issue body, a stated convention, scope-narrowing calls subject to [requirement-change review](design-review.md#inputs-and-actions), and a lane's own well-argued recommendation are available evidence. A pure cut back to main's behaviour, or a cut of surface the Done-when does not need, takes no table. Relay any other question to the user only where [communication-modes.md](communication-modes.md) § Ask set puts it, using the question format that section links. A merge question under `ORCH_MERGE_AUTONOMY=ask` follows Held merges above and always goes to the user. Every emitted question is answered: the lane is blocked in `lane-mail wait` on this line. An overseer resuming a fleet reads what it still owes with `lane-mail pending --item [ISSUE_ID]`, adding `--root [MAIL_ROOT] --host` for a lane whose record puts it on another host. - `lane-notice` → the lane reported something it is not waiting on. Act on it where it needs acting on; it needs no reply. A `copilot-*` notice takes [copilot-head-notices.md](copilot-head-notices.md). - `directive-read [ITEM] [ID]` → the lane's mailbox cursor passed the directive: the lane has it. Nothing is owed; a sent directive is confirmed by this line alone. - `directive-unread [ITEM] [ID] age=[SECONDS]` → the directive has waited past `ORCH_DIRECTIVE_UNREAD_SECS` with the lane's cursor short of it. Reach the lane by its state: wake an idle one per `oversee-lanes.md` § Talking to a lane, and any other by its row in [lane-reach.md § Wake refusals](lane-reach.md#wake-refusals). `directive-read` follows once it reads it. -- `owner-note` → a note to the overseer mailbox, which carries owner and delegate notes; its text follows. `from=owner` is routing, not authorship; a record names the stated speaker per [communication-modes.md § Recording](communication-modes.md#recording). Every text and `options:` line under `lane-question`, `lane-notice`, `peer-note`, `owner-note` and `owner-ask-resolved` is indented two spaces, so only a watch record begins with `EVENT`. Act on it, or record it in the fleet log as a ruling. Where a reply is owed, send it as `lane-mail notice --item overseer --to owner --ref [ID]`, the event's id as `--ref`, so the owner reads it on the channel the note came from ([overseer takeover § 1](../workflows/oversee-takeover.md#1-read-the-mailbox-and-handoff)); a question back is an owner ask. Follow [communication-modes.md § Owner messages](communication-modes.md#owner-messages) for reply routing; an identical send within the minute appends nothing and refuses `duplicate id=[FIRST_ID]`, and a notice text the owner received within 24 hours refuses `owner-notice-repeated` naming that notice's id, so a second reply takes its own words. The watch reports each `lane-question`, `lane-notice`, `directive-unread`, `owner-note`, `owner-ask-resolved` and `peer-note`, and each `directive-read` for a directive read after its lane is first watched, at least once, and a stop between its print and the commit of its row or cursor reports it again: an id already seen is a repeat. +- `owner-note` → a note to the overseer mailbox, which carries owner and delegate notes; its text follows. `from=owner` is routing, not authorship; a record names the stated speaker per [communication-modes.md § Recording](communication-modes.md#recording). Every text and `options:` line under `lane-question`, `lane-notice`, `peer-note`, `owner-note` and `owner-ask-resolved` is indented two spaces, so only a watch record begins with `EVENT`. Act on it, or record it in the fleet log as a ruling. Where a reply is owed, send it as `lane-mail notice --item overseer --to owner --ref [ID]`, the event's id as `--ref`, so the owner reads it on the channel the note came from ([overseer takeover § 1](../workflows/oversee-takeover.md#1-read-the-mailbox-and-handoff)); a question back is an owner ask. Follow [communication-modes.md § Owner delivery](communication-modes.md#owner-delivery) for reply routing; an identical send within the minute appends nothing and refuses `duplicate id=[FIRST_ID]`, and a notice text the owner received within 24 hours refuses `owner-notice-repeated` naming that notice's id, so a second reply takes its own words. The watch reports each `lane-question`, `lane-notice`, `directive-unread`, `owner-note`, `owner-ask-resolved` and `peer-note`, and each `directive-read` for a directive read after its lane is first watched, at least once, and a stop between its print and the commit of its row or cursor reports it again: an id already seen is a repeat. - `owner-ask-resolved [ASK_ID] by=[text|default] id=[ANSWER_ID]` → an answer to an owner ask; its text follows. The owner can answer more than once, each with its own answer id. Record the ruling per [communication-modes.md § Recording](communication-modes.md#recording). When the overseer has its ruling, close with `lane-mail resolve --item overseer --id [ASK_ID]` and send a notice with `--ref [ASK_ID]` naming what stood. `by=default` supplies the recommendation only for an unanswered deadline. Later replies after closure arrive as `owner-note` directives. - `owner-ask-closed [ASK_ID] by=[explicit|text|default]` → the separate close record. An answered deadline closes without a default answer; the owner's words stand. - `peer-note [REPOSITORY] [ID] kind=[KIND]` → a peer repository's overseer wrote to this one; its text follows. Answer `kind=ask` alone, per [peer-mail.md](peer-mail.md); `kind=answer` carries `re=[ASK_ID]` and is recorded against that ask of this overseer's, and `kind=directive` needs no reply. Record the exchange in the fleet log. - `lane-asking` → a harness dialog, never a question for the overseer: a permission prompt, a trust prompt, a model picker. Answer it in the lane's own dialog per [lane-reach.md § Per harness](lane-reach.md#per-harness). A line that carries `stop-cause=allow-all-blocked-by-policy` is a Copilot lane launched with allow-all whose policy blocks it: follow [copilot-runtime.md § Allow-all blocked by policy](copilot-runtime.md#allow-all-blocked-by-policy) and do not answer the prompt. A Copilot lane launched without allow-all carries no cause, and its prompt is answered as above. That section also names each `session-record=` reason a Copilot lane's line can carry. -- `report-due` → the status report is due. Run `oversee-report render` with the watch's `--state` and `--repo` values, which reads the `ORCH_CONNECTED_REPOS` repositories after them as the watch does, write the work's outcomes with the template in [communication-modes.md § Owner messages](communication-modes.md#owner-messages), never rating them, then run `oversee-report write --summary-file [PATH]` with the same values. Paste what `write` prints into the chat unchanged: it is the file's content, so chat and file carry one report. The summary is in neither: it is the text of the report notice `write` sends the owner, posted as the file's Slack comment. `write` sends that notice and is the only send of a report and its summary: never send the summary as a separate notice, before or after `write`. During `ORCH_REPORT_QUIET_HOURS` (default midnight to 7 am in `ORCH_OWNER_TIME_ZONE`, default `America/Los_Angeles`), `write` sends no owner notice. Empty quiet hours turns suppression off. The first due report after the window sends the morning brief. Its Landed, Running, Blocked and Waiting on you summary covers the work since the last report sent to the owner, including overnight merges. Decisions needed and critical notices remain immediate at any hour. The written file ends the cadence event without advancing the last-sent baseline when no notice was sent. A `write` refused as `notice=[FILE]` wrote and printed the report, which ends the event; nothing re-sends the notice, and a second `write` in the same minute is refused `report-exists`. Fix what the lines under it name, then send the notice by hand: `lane-mail notice --item overseer --to owner --attach [FILE] --file [SUMMARY_PATH]`. A hand send refused `owner-notice-repeated` means the first send landed: the owner holds that text, and the id it names is the receipt. Any other refused `render` or `write` names its cause on its first stderr line: fix it, and where it stands, tell the user the report is blocked and why, because the event repeats on every long pass until a report is written. +- `report-due` → the status report is due. Run `oversee-report render` with the watch's `--state` and `--repo` values, which reads the `ORCH_CONNECTED_REPOS` repositories after them as the watch does, write the work's outcomes with the template in communication's [reports](../../communication/references/reports.md), then run `oversee-report write --summary-file [PATH]` with the same values. Paste what `write` prints into the chat unchanged: it is the file's content, so chat and file carry one report. The summary is in neither: it is the text of the report notice `write` sends the owner, posted as the file's Slack comment. `write` sends that notice and is the only send of a report and its summary: never send the summary as a separate notice, before or after `write`. During `ORCH_REPORT_QUIET_HOURS` (default midnight to 7 am in `ORCH_OWNER_TIME_ZONE`, default `America/Los_Angeles`), `write` sends no owner notice. Empty quiet hours turns suppression off. The first due report after the window sends the morning brief. Its Landed, Running, Blocked and Waiting on you summary covers the work since the last report sent to the owner, including overnight merges. Decisions needed and critical notices remain immediate at any hour. The written file ends the cadence event without advancing the last-sent baseline when no notice was sent. A `write` refused as `notice=[FILE]` wrote and printed the report, which ends the event; nothing re-sends the notice, and a second `write` in the same minute is refused `report-exists`. Fix what the lines under it name, then send the notice by hand: `lane-mail notice --item overseer --to owner --attach [FILE] --file [SUMMARY_PATH]`. A hand send refused `owner-notice-repeated` means the first send landed: the owner holds that text, and the id it names is the receipt. Any other refused `render` or `write` names its cause on its first stderr line: fix it, and where it stands, tell the user the report is blocked and why, because the event repeats on every long pass until a report is written. - `triage` → team-wide: run `oversee.md` § Bounded issue reads and set `[ISSUES]` to the emitted identifiers. Take out of `[ISSUES]` each Linear mirror `oversee.md` § Outside contributions judges on GitHub, recorded as it says. Cross-check `gh issue list --repo [REPO] --state open` for the first repository: an open GitHub issue whose Linear mirror, the item whose `github_sync` names it, is Done is residue, so close it on GitHub naming the pull request that fixed it; one with no mirror and no `outside-contribution` event means the GitHub-to-Linear sync broke, so send one owner notice naming the issue. Read each issue team's complete live project inventory and reuse it for project selection and validation. Stop without writing `triaged` if a project read fails or is incomplete. Launch one fresh canonical `maintainer` verifier with the source repository and the lowest-cost model the surface exposes. The launch call is Claude's generated-agent tool, Codex `spawn_agent` after `scripts/spawn-adapter spawn maintainer` followed by `send_input`, OpenCode `functions.task`, or Pi `subagent`, as [SKILL.md § Runtime Notes](../SKILL.md#runtime-notes) specifies. On the terminal surface, call it from the overseer session. On the managed-session surface, use that surface's native call. In sequential mode, make the same call and wait for it before resuming. Send it the team project inventories and this task: `Verify only these Linear issues: [ISSUES]. For each issue, read its full body and source and apply the filing bar regardless of lane authorship. Follow the Verifier returns contract in .agents/skills/orch/references/skill-rules.md under Coordination for evidence, project and agent selection, and the final return.` The [Verifier returns contract](skill-rules.md#coordination) governs both the task and acceptance. Capture only the single final return defined by [skill-rules.md § Single Return Message](skill-rules.md#single-return-message). Once that return is captured, or on any launch, capture, parse, or validation failure after the launch, retire the verifier through the surface's own shut-down call before any further launch: a finished subagent can keep holding a runtime thread slot ([DEVELOPMENT.md § Reviewer slot budget](https://github.com/vanillagreencom/kendex/blob/main/skills/orch/DEVELOPMENT.md#reviewer-slot-budget)). Validate the final return against that contract. Stop without writing `triaged` on a launch, capture, parse, or validation failure. For each valid kept item, read its project and labels live with `linear.sh issues get [ID]`. If the team inventory is nonempty and the project is missing, or a required agent label is missing, set only the missing fields in one `linear.sh issues update [ID]`: pass `--project` only when the team inventory is nonempty and no project exists; pass `--labels` only when `LINEAR_AGENT_LABELS` is nonempty and no agent label exists, merging the selected agent label with all current labels under the linear skill's `--labels` rule. Leave existing projects and agent labels unchanged. With an empty `LINEAR_AGENT_LABELS`, preserve all current labels and skip agent-label assignment. Stop without writing that item's `triaged` record if its read or update fails. Route each valid kept item or cancel it, then record the terminal verdict in the fleet state's `triaged` list; every pass emits the item again until that record exists. `triaged` is the verdict log the watch rebuilds its triage keys from, per `oversee-watch --help`. - `outside-contribution` → [oversee.md § Outside contributions](../workflows/oversee.md#outside-contributions). - `refresh-failing` → send one owner notice for every `report=initial`, naming the repository, the failed-run count and the cause, even when the cause matches an earlier incident. For `report=repeat`, notify only when the cause changes. A consumer fleet's overseer applies this rule to its own repository too. `oversee-watch --help` defines the event fields. diff --git a/.agents/skills/orch/references/skill-rules.md b/.agents/skills/orch/references/skill-rules.md index a9be27d5..54297704 100644 --- a/.agents/skills/orch/references/skill-rules.md +++ b/.agents/skills/orch/references/skill-rules.md @@ -85,13 +85,13 @@ A lane never steers a running dev or fix round by message alone. The harness's s **Private settings.** A brief or workflow names the setting and the reader `orch-env NAME DEFAULT` ([scripts/orch-env](../scripts/orch-env)), never the private env file. An agent never opens, prints, greps or sources the private env file: `.env.local`, or the file `KENDEX_ENV_FILE` names. The only exception is a setup workflow that writes one named secret into it. -**Voice requests.** Follow [communication-modes.md § Voice requests](communication-modes.md#voice-requests) for the owner's plain-yes approval, the explicit confirmation of destructive and money steps, and the spoken reply. +**Voice requests.** Follow [communication-modes.md § Voice requests](communication-modes.md#voice-requests) for the owner's plain-yes approval and the explicit confirmation of destructive and money steps. Read communication's [voice wording](../../communication/references/voice.md) before the spoken reply. **Containers.** An issue with children or an `agent:multi` label and no `(one PR)` title marker is a CONTAINER. A container is never orchestrated and never gets a PR. Each child is the PR unit. Selection operates on unblocked children. Container closure follows [merge-pr.md § 5 step 2](../workflows/merge-pr.md#5-execute-the-merge) and its Verification continuation in [oversee-events.md § Event kinds](oversee-events.md#event-kinds). -**Ancestor gate.** Read current Linear facts before each launch or implementation delegation. Every selected issue walks its full `parent_id` chain. An enclosing `(one PR)` bundle REPLACES the selection. Apply the gate to the final selection. Dispatch requires the item's own `state_type` non-terminal and the union of its `blocked_by_open` with every container ancestor's `blocked_by_open` empty. +**Ancestor gate.** Read current Linear facts with `issues get --format=safe` before each launch or implementation delegation. Every selected issue walks its full `parent_id` chain. An enclosing `(one PR)` bundle REPLACES the selection. Apply the gate to the final selection. Dispatch requires the item's own `state_type` non-terminal and the union of its `blocked_by_launch` with every container ancestor's `blocked_by_launch` empty. This launch-only field excludes completed, canceled and post-merge Verifying blockers. In Progress and Backlog blockers still hold dispatch. Other readers keep `blocked_by_open`. A dependent that needs a blocker's proven outcome instead of its merged code states that need in its body. The overseer's queue order holds that dependent through verification. -For a `(one PR)` bundle or `Audit Bundle: yes`, also read the complete descendant tree through [project-management § Reading a Full Subtree](../../project-management/references/dependencies.md#reading-a-full-subtree). Include the external `blocked_by_open` of every non-terminal descendant whose work the session will implement. Exclude blockers that belong to the same bundle from this descendant check; the delegated session orders that work. Any remaining open blocker stops dispatch. A missing or incomplete parent, descendant, or blocker read stops dispatch. `blocked_by` remains relation history and does not decide dispatch. +For a `(one PR)` bundle or `Audit Bundle: yes`, also read the complete descendant tree through [project-management § Reading a Full Subtree](../../project-management/references/dependencies.md#reading-a-full-subtree). Read each non-terminal descendant whose work the session will implement with `issues get --format=safe`. Include its external `blocked_by_launch`. Exclude blockers that belong to the same bundle from this descendant check; the delegated session orders that work. Any remaining launch blocker stops dispatch. A missing or incomplete parent, descendant, or blocker read stops dispatch. `blocked_by` remains relation history and does not decide dispatch. **Sequencing.** Order by data flow (Creates ↔ Consumes), never by agent ordering; existing blocking relations outrank inference. Record relations under linear SKILL.md § Blocked Label vs Issue Relations. Only an explicit `(one PR)` bundle leaves intra-bundle ordering to the delegated session. diff --git a/.agents/skills/orch/schemas/lane-host.md b/.agents/skills/orch/schemas/lane-host.md index 8000ec6c..f2b43041 100644 --- a/.agents/skills/orch/schemas/lane-host.md +++ b/.agents/skills/orch/schemas/lane-host.md @@ -11,7 +11,7 @@ Every place a lane runs is a host kind. `lane-host capabilities` prints the kind | Key | Values | Caller that matches on it | |---|---|---| | `kind` | `local`, `ssh`, `claude-cloud`, `codex-cloud` | `open-terminal` writes it into the lane record | -| `launch` | `window`, `ssh`, `cloud-session`, `cloud-task` | `open-terminal`; `lanes pick`, for repository access | +| `launch` | `window`, `ssh`, `cloud-session`, `cloud-task` | `open-terminal`; `lanes pick`, for repository access; the local overseer's account reader | | `channel` | `mailbox`, `session`, `task` | `lane-mail send`, the `oversee-watch` mail pass | | `files` | `local`, `verb`, `none` | `lane-mail send` hosted mailbox requirement; `oversee-watch` status-file, workflow-state and mailbox reads; `lib/lane-gitfile.sh` `lane_item_state`, which reads no state for `none`, for `oversee-cycle record` and `oversee-report` | | `status` | `pane`, `verb`, `task`, `none` | `oversee-watch` lane judgement | @@ -20,7 +20,7 @@ Every place a lane runs is a host kind. `lane-host capabilities` prints the kind | `relaunch` | `resume`, `fresh` | read by no caller in this build | | `park` | `verb`, `none` | read by no caller until the Daytona provider declares its line; `lane-close --park` keeps its `stop-sandbox --check` read | | `accounts` | `verb`, `none` | read by no caller until then; `lanes` keeps its exit-2 read of `accounts` | -| `pool` | `plan`, `cloud-credit` | `lanes pick`, the tier of its expires-first rule | +| `pool` | `plan`, `cloud-credit` | `lanes pick`, the tier of its expires-first rule; the local overseer's account reader | | `land` | `lane`, `handoff` | the overseer's `pr-watch` `disarmed` rule in [oversee-events.md](../references/oversee-events.md). Landing placement follows [oversee.md § 3 Placement](../workflows/oversee.md#3-launch). | | Kind | `launch` | `channel` | `files` | `status` | `stop` | `relaunch` | `park` | `accounts` | `pool` | `land` | @@ -31,6 +31,8 @@ Every place a lane runs is a host kind. `lane-host capabilities` prints the kind | `claude-cloud` | `cloud-session` | `session` | `none` | `none` | `none` | `fresh` | `none` | `none` | `cloud-credit` | `handoff` | | `codex-cloud` | `cloud-task` | `task` | `none` | `task` | `none` | `fresh` | `none` | `none` | `plan` | `handoff` | +The local overseer's Claude account reader uses the configured provider only for `launch=ssh` with `pool=plan`. It keeps the optional `accounts` probe for older SSH providers. Other host capabilities use the local account reader, so a cloud worker's spending pool and repository access rules cannot refuse a local overseer seat. + Local launches keep their existing state environment. SSH providers, static and Daytona, must carry the default `ORCH_STATE_DIR` in the harness session through `remote-prefix`, as `workflow-state --help` specifies. A fresh successor to a standing handoff uses the remote directory selected by its handoff judge, so it can continue an older configured-directory record. The Claude cloud session interface accepts a description and cannot set the remote harness environment. `codex-cloud` is declared and not built: `open-terminal` refuses `launch=cloud-task` as `kind-unbuilt`. Daytona's line is its provider's to declare; until it does, the dispatcher answers it the static `ssh` line, whose `park` and `accounts` no caller reads. A `claude-cloud` lane's record names `host` and `kind` `claude-cloud`, its account, its cloud `session_id`, and the item's window, whose pane runs the session's local client, or shows the session URL the CLI printed before it exited (`open-terminal --help`, `--host`). `status=none` keeps that window out of `oversee-watch`'s pane passes: such a lane is judged by `lane-stalled`, `start-stalled` and `lane-long` alone, and `lane-close` closes its window by the record. For the session the operator archives, read the account from its fleet-log `close` row, which carries `session=` and `account=`. Claude Code 2.1.295 offers no supported cloud-session archive route. A documented archive verb requires a new item to call it in the `stop=none` arm before writing the row. diff --git a/.agents/skills/orch/scripts/lanes b/.agents/skills/orch/scripts/lanes index 248f2a2d..82b20b3b 100755 --- a/.agents/skills/orch/scripts/lanes +++ b/.agents/skills/orch/scripts/lanes @@ -250,10 +250,9 @@ # the provider reports with a reading is judged even where discovery # does not reach it. The overseer's own picks (oversee launch, the # succession walk and capacity count, oversee-succeed's headroom -# mark) run under ORCH_LANE_HOST=local, since its session runs on -# this machine's copy. So a folder whose local login a provider-side -# retire removed reads `no_credentials` there and cannot seat an -# overseer. +# mark) use the configured provider for Claude accounts too: its +# stored token can back a local session with no local credentials file. +# Other overseer accounts use this machine's reading. # # With --lane it judges that ONE account instead of # choosing among the fleet, measuring only that directory. A launcher @@ -3282,7 +3281,7 @@ host_accounts_answer() { # HOST [RECORD] — rows or their cache record, status rows="$record" fi printf '%s\n' "$rows" -} +} 2>&"$HOST_ACCOUNTS_ERR_FD" # The recorded reading of the session one `lanes context` row names, the # lane_context_collect fetch contract: the record on stdout and exit 0, exit 1 @@ -3917,6 +3916,9 @@ parse_argv() { PROJECTED=false LOCAL_ONLY=false CACHE_ONLY=false + # ol_lanes supplies descriptor 3 to keep provider notices separate from + # pick/check refusal details. Ordinary invocations retain stderr. + HOST_ACCOUNTS_ERR_FD=2 SUB="${1:-}" # A bare invocation names the commands and does nothing else, so it is one @@ -3939,6 +3941,7 @@ parse_argv() { --model=*) MODEL="${1#--model=}"; need_val --model "$MODEL"; shift ;; --binding-floor) BINDING_FLOOR=true; shift ;; --for-overseer) FOR_OVERSEER=true; shift ;; + --provider-notices-fd3) HOST_ACCOUNTS_ERR_FD=3; shift ;; --projected) PROJECTED=true; shift ;; --local) LOCAL_ONLY=true; shift ;; --cache-only) [[ "$SUB" == list ]] || die unknown-option "$@"; CACHE_ONLY=true; LOCAL_ONLY=true; shift ;; diff --git a/.agents/skills/orch/scripts/lib/open-terminal-text.sh b/.agents/skills/orch/scripts/lib/open-terminal-text.sh index 11eee0c7..0a17ca0a 100644 --- a/.agents/skills/orch/scripts/lib/open-terminal-text.sh +++ b/.agents/skills/orch/scripts/lib/open-terminal-text.sh @@ -15,7 +15,7 @@ ot_message() { # REASON FIELD=VALUE... case "$reason" in missing-value) text='The option requires a value.' ;; helper-missing) text='The required helper is not executable.' ;; - launch-blocked) text='An item or its ancestor has an open blocker. Complete the named blockers before launching this item.' ;; + launch-blocked) text='An item or its ancestor has a blocker that still holds launch. Merge or complete the named blockers before launching this item.' ;; launch-blocked-unread) text='The live blocker read failed. Restore the tracker read before launching this item.' ;; entry-permission-untransferable) text='The caller permissions cannot transfer to this harness. The preference walk skips this entry.' ;; items-missing) text='Specify a work item.' ;; @@ -808,6 +808,13 @@ launched, skipped, and failed counts. Preparing counts both background jobs and saved foreground busy continuations, as schemas/lane-host.md § Provider protocol defines. +A new Linear fleet launch refuses as launch-blocked when the item or a +container ancestor has a blocker in blocked_by_launch from issues get +--format=safe. Completed, canceled and post-merge Verifying blockers satisfy +this launch check. In Progress and Backlog blockers still hold launch. +launch-blocked-unread means the live read could not be completed. A relaunch +or wake of a recorded lane passes this check. + Every launch that stands under --state-dir is recorded in the oversee workflow state that flag names (`workflow-state get oversee .lanes`, created when absent); a launch with no --state-dir names no fleet and writes no diff --git a/.agents/skills/orch/scripts/lib/oversee-watch-text.sh b/.agents/skills/orch/scripts/lib/oversee-watch-text.sh index 5282ce95..b65d9c82 100644 --- a/.agents/skills/orch/scripts/lib/oversee-watch-text.sh +++ b/.agents/skills/orch/scripts/lib/oversee-watch-text.sh @@ -216,6 +216,13 @@ The long pass's events, checked and reported in this order: refresh-ready wakes on the opening pass and once per new head, including without a lane EVENT merged + every refresh-ready PR gets this line at its + merge, with branch kendex/refresh. It triggers + the base-move check for open lane PRs whose files + the refresh changed. When a saved ready key + clears, one REST read distinguishes a merge from + approval while open or an unmerged close. The + merged row prevents repeats across restarts; an --item PR merged at or after --since, in any --repo, being the item's own, its key lower-cased. The PR is the item's by @@ -847,7 +854,7 @@ Options: value names the state file, so a run given a different one starts from no sightings and parks every walled lane afresh; LINEAR_TEAM below arms the triage check - --item ISSUE_ID live item; repeatable. No values skips merged and + --item ISSUE_ID live item; repeatable. No values skips item merges and handoff with a note --repo OWNER/REPO repository; repeatable and case-normalized. The first repository and ORCH_CONNECTED_REPOS feed pr-watch. diff --git a/.agents/skills/orch/scripts/lib/overseer-launch.sh b/.agents/skills/orch/scripts/lib/overseer-launch.sh index 683194f2..dec79f4e 100644 --- a/.agents/skills/orch/scripts/lib/overseer-launch.sh +++ b/.agents/skills/orch/scripts/lib/overseer-launch.sh @@ -21,7 +21,7 @@ # ol_pi_model a pi session's model, out of the sources naming it # ol_entry_model one entry's harness, model, class and effort, a # class resolved to its model -# ol_lanes `lanes` on this machine's copy of each account +# ol_lanes `lanes` through the overseer's account reader # ol_pick_record one `lanes pick --json` record, for a caller's # own counts # ol_pick_lane one `lanes pick` for one entry, with the counts a @@ -71,8 +71,8 @@ # kendex's model-resolution warning (ol_model_line), because # the caller owns its own refusal prefix and words: ol_checkout_notice and # ol_fleet_log_notice print theirs through the caller's `message`. Every -# dependency writes its stderr to DEP_ERR, which the caller relays under its -# keyed line. +# failed dependency leaves its stderr in DEP_ERR for the caller's keyed +# refusal. Account reads relay notices before record parsing replaces DEP_ERR. # # Requires, of a caller that runs its functions: SCRIPT_DIR (the orch scripts # directory), DEP_ERR (a file), lib/lane-launch.sh sourced by the caller, @@ -445,14 +445,28 @@ ol_class_unread() { # ENTRY printf '%s\n' "$OL_CLASS_ERR" >"$DEP_ERR" } -# ol_lanes ARGS... — `lanes` as every overseer read of an account asks it, -# under ORCH_LANE_HOST=local: an overseer opens through overseer-host on this -# machine, under this machine's copy of the account, so a provider's reading -# of that account is not the one its session spends. The successor walk and -# the caller's own headroom mark both read through here, so the two never -# judge one account on two copies. -ol_lanes() { # ARGS... - ORCH_LANE_HOST=local "$SCRIPT_DIR/lanes" "$@" +# SSH providers can measure Claude tokens without a local credentials file. +# Their plan pool also applies to the local overseer. Cloud-session policy +# instead governs remote launches, so it cannot judge this local seat. +ol_lanes() { # ACCOUNT_HARNESS ARGS... + local harness="$1" host=local launch pool rc=0 + shift + if [[ "$harness" == claude ]]; then + # shellcheck source=lane-capabilities.sh + source "$SCRIPT_DIR/lib/lane-capabilities.sh" || return 1 + lane_capabilities_read "$SCRIPT_DIR/lane-host" "${ORCH_LANE_HOST:-local}" || return 1 + lane_capability launch launch + lane_capability pool pool + [[ "$launch:$pool" != ssh:plan ]] || host="${ORCH_LANE_HOST:-local}" + fi + # The child owns descriptor 3 for this invocation. Provider notices go to + # the caller before record parsing can replace DEP_ERR; ordinary refusal + # details stay there for the caller's keyed refusal. + ORCH_LANE_HOST="$host" "$SCRIPT_DIR/lanes" "$@" --provider-notices-fd3 3>&2 2>"$DEP_ERR" || rc=$? + if [[ "$rc" -eq 0 ]]; then + [[ ! -s "$DEP_ERR" ]] || cat -- "$DEP_ERR" >&2; : > "$DEP_ERR" + fi + return "$rc" } # ol_pick_record HARNESS MODEL TRIGGER [EXCLUDE_DIR] [LANE]: the one `lanes pick @@ -476,8 +490,8 @@ ol_pick_record() { # HARNESS MODEL TRIGGER [EXCLUDE_DIR] [LANE] [[ -n "$(lane_context_mark_model "$harness" "$model")" ]] || floor=(--binding-floor) [[ -z "${4:-}" ]] || exclude=(--exclude-lane "$4") [[ -z "${5:-}" ]] || scope=(--lane "$5") - OL_PICK_RECORD="$(ol_lanes pick --harness "$harness" --min-headroom-pct "$3" "${scope[@]}" \ - ${floor[@]+"${floor[@]}"} ${exclude[@]+"${exclude[@]}"} ${model:+--model "$model"} --json 2>"$DEP_ERR")" || rc=$? + OL_PICK_RECORD="$(ol_lanes "$harness" pick --harness "$harness" --min-headroom-pct "$3" "${scope[@]}" \ + ${floor[@]+"${floor[@]}"} ${exclude[@]+"${exclude[@]}"} ${model:+--model "$model"} --json)" || rc=$? return "$rc" } @@ -653,7 +667,7 @@ ol_walk() { # TRIGGER EXCLUDE_DIR ENTRY... # must still be unmeasured, and a retired account's unmeasured record # is not admission: the account policy owns that separate question. rc=0 - ol_lanes check "$OL_WALK_CALLER_LANE" >/dev/null 2>"$DEP_ERR" || rc=$? + ol_lanes "$OL_ACCOUNT_HARNESS" check "$OL_WALK_CALLER_LANE" >/dev/null || rc=$? case "$rc" in 0) ;; 4) continue ;; diff --git a/.agents/skills/orch/scripts/lib/pr-watch-pass.sh b/.agents/skills/orch/scripts/lib/pr-watch-pass.sh index d4a94c99..153a1799 100644 --- a/.agents/skills/orch/scripts/lib/pr-watch-pass.sh +++ b/.agents/skills/orch/scripts/lib/pr-watch-pass.sh @@ -192,6 +192,34 @@ check_pr_watch() { [[ -z "$event_out" ]] || printf '%s' "$event_out" [[ -z "$PW_ERR" ]] || printf '%s\n' "$PW_ERR" fi + # A rolling refresh has no item. Approval clears its reducer line while + # the merge queue can keep it open, so retain its identity until it closes. + local pr kind state prior merge_key + for i in "${PW_REPO_INDICES[@]}"; do + repo="${REPOS[$i]}" + while IFS=$'\t' read -r pr kind; do + [[ "$pr" =~ ^[0-9]+$ && "$kind" == refresh-ready:* ]] || continue + # A currently ready head replaces the old head's identity. + grep -q -- "^$pr"$'\t''refresh-ready:' <<<"${pass_keys[$i]}" && continue + state="$(gh api "repos/$repo/pulls/$pr" --jq '[.merged, .state] | @tsv' 2>"$errf")" \ + || die pr-list-failed "$(cat "$errf")" "repo=$repo" "pr=$pr" + case "$state" in + false$'\t'open) + pass_keys[$i]+="${pass_keys[$i]:+$'\n'}$pr"$'\t'"$kind" + continue ;; + false$'\t'closed) continue ;; + true$'\t'closed) ;; + *) die pr-list-invalid "" "repo=$repo" "pr=$pr" ;; + esac + prior="$(lane_row_get merged "${pass_keys[$i]}" kendex/refresh)" \ + || die state-read-failed "" "repo=$repo" "row=merged" + merge_key="$repo#$pr" + grep -qxF -- "$merge_key" <<<"${prior// /$'\n'}" && continue + echo "EVENT merged $pr kendex/refresh $repo" + event=1 + pass_keys[$i]="$(lane_row_set merged "${pass_keys[$i]}" kendex/refresh "${prior:+$prior }$merge_key")" + done <<<"${PW_SEEN[$i]}" + done for i in "${PW_REPO_INDICES[@]}"; do pw_stage_state "$(pw_state_file "${REPOS[$i]}")" "${pass_keys[$i]}" done diff --git a/.agents/skills/orch/scripts/open-terminal b/.agents/skills/orch/scripts/open-terminal index 09a042de..5fe6fbf9 100755 --- a/.agents/skills/orch/scripts/open-terminal +++ b/.agents/skills/orch/scripts/open-terminal @@ -3827,19 +3827,19 @@ launch_blockers_gate() { # ITEM || ! row="$("$linear" issues get "$next" --format=safe)" \ || ! jq -e --arg id "$next" ' .id == $id and (.parent_id | type == "string") - and (.blocked_by_open | type == "array" and all(.[]; type == "string" and length > 0)) + and (.blocked_by_launch | type == "array" and all(.[]; type == "string" and length > 0)) ' <<<"$row" >/dev/null; then ot_message launch-blocked-unread "item=$selected" "read=$next" >&2 return 1 fi seen+="$next " - blockers="$(jq -cn --argjson known "$blockers" --argjson row "$row" '$known + $row.blocked_by_open | unique')" || return 1 + blockers="$(jq -cn --argjson known "$blockers" --argjson row "$row" '$known + $row.blocked_by_launch | unique')" || return 1 parent="$(jq -r '.parent_id' <<<"$row")" || return 1 next="$parent" done blockers="$(jq -r 'join(",")' <<<"$blockers")" || return 1 [[ -n "$blockers" ]] || return 0 - ot_message launch-blocked "item=$selected" "blockers=$blockers" "fix=complete blockers $blockers before launch" >&2 + ot_message launch-blocked "item=$selected" "blockers=$blockers" "fix=merge or complete blockers $blockers before launch" >&2 return 1 } diff --git a/.agents/skills/orch/scripts/oversee-report b/.agents/skills/orch/scripts/oversee-report index aec96c21..395edfba 100755 --- a/.agents/skills/orch/scripts/oversee-report +++ b/.agents/skills/orch/scripts/oversee-report @@ -147,7 +147,7 @@ write prints the rows and writes the same bytes to the path These findings are advisory: write sends on the writer's word. Argument, setting and notice failures still refuse. Owner wording and the template live in - references/communication-modes.md § Owner messages. + ../communication/references/reports.md § Owner summary template. Rows: Landed each fleet item, a lanes[] record of any status, with a diff --git a/.agents/skills/orch/scripts/oversee-succeed b/.agents/skills/orch/scripts/oversee-succeed index 711ee24b..7aae1e2f 100755 --- a/.agents/skills/orch/scripts/oversee-succeed +++ b/.agents/skills/orch/scripts/oversee-succeed @@ -1272,9 +1272,9 @@ if (( JUDGES )); then caller_rc=4 caller_record="" caller_wall_at="" if ol_account_measured "$CALLER_ACCOUNT_HARNESS"; then caller_rc=0 - caller_record="$(ol_lanes pick --lane "$CALLER_CFG" --harness "$CALLER_ACCOUNT_HARNESS" --for-overseer \ + caller_record="$(ol_lanes "$CALLER_ACCOUNT_HARNESS" pick --lane "$CALLER_CFG" --harness "$CALLER_ACCOUNT_HARNESS" --for-overseer \ --min-headroom-pct "$HEADROOM_TRIGGER" ${CALLER_ACCOUNT_MODEL:+--model "$CALLER_ACCOUNT_MODEL"} \ - --json 2>"$DEP_ERR")" || caller_rc=$? + --json)" || caller_rc=$? fi memo_fields="" if [[ "$caller_rc" == 0 || "$caller_rc" == 3 ]]; then diff --git a/.agents/skills/orch/scripts/oversee-watch b/.agents/skills/orch/scripts/oversee-watch index c32f8586..851dbdc3 100755 --- a/.agents/skills/orch/scripts/oversee-watch +++ b/.agents/skills/orch/scripts/oversee-watch @@ -1893,7 +1893,7 @@ check_merged() { fi parked_merged_line "$item" "$PARKED_KEY" done - state="$(lane_row_prune merged "$state" "${MERGED_ITEMS[@]}")" + state="$(lane_row_prune merged "$state" "${MERGED_ITEMS[@]}" kendex/refresh)" state="$(lane_row_prune parked-until "$state" ${PARKED_ITEMS[@]+"${PARKED_ITEMS[@]}"})" lane_row_commit "$state" } diff --git a/.agents/skills/orch/workflows/oversee-takeover.md b/.agents/skills/orch/workflows/oversee-takeover.md index ecb7ca24..6e1edfcb 100644 --- a/.agents/skills/orch/workflows/oversee-takeover.md +++ b/.agents/skills/orch/workflows/oversee-takeover.md @@ -6,9 +6,9 @@ Read this route at succession, takeover and after compaction. Load `mailbox` bef Read linked communication and peer-mail sections when a note, reply or ask needs them. Before the first decision from the handoff, read only the opening hold-check paragraph of [communication-modes.md § Handoff](../references/communication-modes.md#handoff). Read its remaining snapshot and writer rules before replacing the handoff. -The overseer mailbox carries owner and delegate notes; `from=owner` is routing, not authorship, and a record names the stated speaker per [communication-modes.md § Recording](../references/communication-modes.md#recording). Send these notes with `.agents/skills/mailbox/scripts/lane-mail send --item overseer --directive --file [PATH]` from any project checkout (`lane-mail --help`). The [watch](oversee.md#4-watch-and-advance) reports them at least once as `owner-note`. Reply to mailbox notes with `lane-mail notice --item overseer --to owner --ref [NOTE_ID] --file [PATH]`. Answer each owner message in its own thread with its own `--ref`. Keep one topic per thread. If a fact answers two messages, give a short answer in each thread. Owner questions use [communication-modes.md § Owner asks](../references/communication-modes.md#owner-asks), never a question dialog. Peer overseers write the same mailbox, reported as `peer-note` ([peer-mail.md](../references/peer-mail.md)). The repeat watch reports both. With single passes, lane-mail hooks hand them over as `lane-mail-check: unread=` at turn end and after tool calls; the watch reports neither ([peer-mail.md § Who reads a note](../references/peer-mail.md#who-reads-a-note)). +The overseer mailbox carries owner and delegate notes; `from=owner` is routing, not authorship, and a record names the stated speaker per [communication-modes.md § Recording](../references/communication-modes.md#recording). Send these notes with `.agents/skills/mailbox/scripts/lane-mail send --item overseer --directive --file [PATH]` from any project checkout (`lane-mail --help`). The [watch](oversee.md#4-watch-and-advance) reports them at least once as `owner-note`. Reply to mailbox notes with `lane-mail notice --item overseer --to owner --ref [NOTE_ID] --file [PATH]`. Follow [Thread delivery](../references/communication-modes.md#thread-delivery). Owner questions use [communication-modes.md § Owner asks](../references/communication-modes.md#owner-asks), never a question dialog. Peer overseers write the same mailbox, reported as `peer-note` ([peer-mail.md](../references/peer-mail.md)). The repeat watch reports both. With single passes, lane-mail hooks hand them over as `lane-mail-check: unread=` at turn end and after tool calls; the watch reports neither ([peer-mail.md § Who reads a note](../references/peer-mail.md#who-reads-a-note)). -Answer owner notes under [communication-modes.md § Owner messages](../references/communication-modes.md#owner-messages), its Reply row and Thread rule. +Use communication's [message wording](../../communication/references/messages.md) for owner notes and orch's [Owner delivery](../references/communication-modes.md#owner-delivery) for its Reply row and Thread delivery. First in every session, before the handoff file, read that mailbox: `.agents/skills/mailbox/scripts/lane-mail inbox --item overseer` prints every note no reader has taken yet and moves the mailbox's own cursor past them. Act on each or record it in the fleet log. The [watch](oversee.md#4-watch-and-advance) reads through the same cursor, so it does not report them again, save a note it had read before this and not yet acknowledged; a repeated note id is one already seen. What is still owed either way is `lane-mail pending --item overseer` (`lane-mail --help`). diff --git a/.agents/skills/orch/workflows/oversee.md b/.agents/skills/orch/workflows/oversee.md index 2d6bc7ec..177f8742 100644 --- a/.agents/skills/orch/workflows/oversee.md +++ b/.agents/skills/orch/workflows/oversee.md @@ -20,7 +20,7 @@ Read the mailbox and handoff through [overseer takeover § 1](oversee-takeover.m ## 2. Select Work -`open-terminal --state-dir` refuses a new Linear lane as `launch-blocked` when the item or a container ancestor has an open blocker. It refuses an incomplete tracker read as `launch-blocked-unread`. A relaunch or wake of an already recorded lane passes this check. When code shows a dependency that holds an item, record its blocking relation first under linear SKILL.md § Blocked Label vs Issue Relations. Then hold the item until the blocker clears. +`open-terminal --state-dir` enforces the Ancestor gate in [references/skill-rules.md § Coordination](../references/skill-rules.md#coordination). It refuses a held launch as `launch-blocked` and an incomplete tracker read as `launch-blocked-unread`. A relaunch or wake of an already recorded lane passes this check. When code shows a dependency that holds an item, record its blocking relation first under linear SKILL.md § Blocked Label vs Issue Relations. Then apply the Ancestor gate. Unblocked, non-terminal development items from the tracker. Exclude Verifying items: their post-merge readings belong to the overseer. Apply the Ancestor gate ([references/skill-rules.md § Coordination](../references/skill-rules.md#coordination)) to each final development item before launch. Follow `start.md` for container selection. The fleet state's `launch_queue` holds the order; its membership is the tracker's, never handoff memory: every heartbeat names each owed tracker item the queue lacks as an `owed` line under [oversee-events.md § Event kinds](../references/oversee-events.md#event-kinds) `heartbeat`, which routes each verdict. A GitHub item labeled `blocked` is not a candidate. An item whose `worktree create` exits 75 belongs to another session: skip it; its siblings still launch. On the tmux surface that claim IS `open-terminal`'s own worktree create, never pre-create the worktree. A surface that creates its own worktree environment (Codex app threads) records the claim in workflow-state before launch. Oversee runs as at most one session per repo. `open-terminal --state-dir` enforces the two caps in [lane-directive.md § Caps](../references/lane-directive.md#caps). Select items only where their cap has room; on other surfaces keep those same limits yourself: @@ -162,7 +162,7 @@ rm -f tmp/oversee-triage-source.json ### Judgement at every event -Write owner summaries with [communication-modes.md § Owner messages](../references/communication-modes.md#owner-messages) and its template. For an owner note marked as a voice request, apply [§ Voice requests](../references/communication-modes.md#voice-requests) before acting or replying. +Write owner summaries with communication's [reports and template](../../communication/references/reports.md). For an owner note marked as a voice request, apply orch's [approval and delivery](../references/communication-modes.md#voice-requests) before acting and communication's [voice wording](../../communication/references/voice.md) before replying. - Judgement rules for every event: [oversee-events.md § Judgement rules](../references/oversee-events.md#judgement-rules). - Handling per event kind: [oversee-events.md § Event kinds](../references/oversee-events.md#event-kinds). diff --git a/.agents/skills/reviewer/references/finding-disposition.md b/.agents/skills/reviewer/references/finding-disposition.md index d66a524c..fc1ca030 100644 --- a/.agents/skills/reviewer/references/finding-disposition.md +++ b/.agents/skills/reviewer/references/finding-disposition.md @@ -69,7 +69,7 @@ An `issue` signal is necessary but not sufficient. Every candidate carries its s A review-born finding clears the bar only where what reaches it is a user or a shipped run, and files at priority 2 carrying the symptom that showed it (project-management SKILL.md § Disposition, which every filing goes through). Below that, a pre-existing defect this diff neither introduces nor arms is declined with its reason; a review-born P3 does not file. Step 1 keeps its exception for a defect that blocks this change from working. -Never for a finding that asks for a product decision the issue does not carry — a new command, a parity feature, a behavior nobody specified: that is declined. A product question that does reach the user is one [communication-modes.md](../../orch/references/communication-modes.md) § Ask set names, asked in that file's wording and nowhere else. Every candidate runs through Step 0 before the bar judges it, whichever door it arrived by — a `category: "issue"` suggestion, an item escalated at a cap, a Discovered Work or deliberately-left-out bullet from a dev return — and one Step 0 excludes is declined there. Step 0 is the only place the classes are written. +Never for a finding that asks for a product decision the issue does not carry — a new command, a parity feature, a behavior nobody specified: that is declined. A product question that does reach the user is one [communication-modes.md](../../orch/references/communication-modes.md) § Ask set names, asked through that section's wording route and nowhere else. Every candidate runs through Step 0 before the bar judges it, whichever door it arrived by — a `category: "issue"` suggestion, an item escalated at a cap, a Discovered Work or deliberately-left-out bullet from a dev return — and one Step 0 excludes is declined there. Step 0 is the only place the classes are written. A finding that does reach a fix round names, per delegated item, the shipped producer, user action, or fixture that reaches it — the `reach` field of [`../schemas/dev-round.md`](../../orch/schemas/dev-round.md). Step 0 runs first, and a reach never overrides it; a class Step 0 excludes is declined whether or not the finding can name one. diff --git a/.agents/skills/worktree/references/session-guard.md b/.agents/skills/worktree/references/session-guard.md index 87750537..b0e29d02 100644 --- a/.agents/skills/worktree/references/session-guard.md +++ b/.agents/skills/worktree/references/session-guard.md @@ -6,10 +6,10 @@ The `worktree-prompt-claim` companion uses the session hook's claim decision bef Claiming is the caller's job: `create` never claims, the orchestrating workflow claims once the worktree is the session's, and `remove` releases at teardown. The catalog's `worktree-session-claim` hook claims at session start under the env ladder below, so a session opened by hand holds a lease too. It claims only a worktree whose private git dir holds the `kendex-issue` record, which every tree `create` returns carries, one adopted through `--reuse` or `--restack` included, and runs no worktree command to learn that. By default, a start meeting a lock another owner name or tool holds, an issue lease with no association to this session included, leaves that lock as it stands and says nothing. The hook's catalog declaration defines which harnesses refuse or only advise in its optional required-claim mode. The workflow's `claim --owner --adopt` takes over a lease the caller's env identity holds, so its claim follows the hook's. Without `--adopt` a claim under any other owner refuses that lease, which is what keeps cleanup's own `--owner` claim off a tree a session claimed after cleanup probed it; `refresh` takes over nothing. Probe with `status`, which is read-only, never with `claim`: `claim` takes or rewrites the lease. -The lease is scoped to the OWNER string, which the calling workflow sets to the issue ID: two sessions on the same issue share one lease and either may release it. Bare `create ` exits 75 on existing ownership; `create --reuse|--restack` skips that refusal, so **nothing prevents a second implementer there**. The per-issue claim lock is a repository-local flock held only inside one `create` invocation and is not that gate either. +The lease is scoped to the OWNER string, which the calling workflow sets to the issue ID: two sessions on the same issue share one lease and either may release it at close-out. The recorded PID belongs to the short-lived guard writer, which exits after claim or refresh. Automatic release by `remove` requires that recorded PID to be absent on this host. A live recorded PID protects only the guard write window; it does not establish whether the harness is still working. A remote host or an unknown process state also keeps the lease. Bare `create ` exits 75 on existing ownership; `create --reuse|--restack` skips that refusal, so **nothing prevents a second implementer there**. The per-issue claim lock is a repository-local flock held only inside one `create` invocation and is not that gate either. Staleness is heartbeat age with **no liveness check**. The heartbeat moves only when a caller re-enters or re-claims the tree, and nothing does so on a timer, so an unattended lease's age is the age of its claim and not of the session's last work in it: a session working steadily past its TTL is stale by this measure and will be unlocked by `release --stale` or `sweep`. `worktree-session-guard refresh --owner ` is what holds a live lease open. Nothing runs `sweep` automatically; confirm the owner is really gone before releasing. A Git worktree lock does not block writes, commits, or rebases inside the worktree, and `git worktree remove -f -f` or a plain `rm -rf` still destroy a claimed tree; use `status` and `list` to attribute such a removal afterwards. -`remove ` and `create --reuse` probe with the issue ID they were addressed with first. The env ladder (`$KENDEX_SESSION_OWNER`, else `$HT_SESSION_OWNER`, else `$USER`) is probed as the second identity and is the only identity for path-addressed calls. Two sessions on one machine share the `$USER` fallback identity, and either can remove a tree the other claimed under it or adopt it under an issue ID. Naming an issue in `remove ` releases that issue's lease whoever claimed it. `cleanup` never releases on an owner match — it skips every lease regardless of owner. The one lease that admits anything is the owner's own under `cleanup --targets-only --worktree PATH --owner ID`, which prunes that worktree's Cargo build output and leaves the lease held. +`remove ` and `create --reuse` use the issue ID they were addressed with first. A path-addressed `remove` reads the issue from the private Git directory's `kendex-issue` record. Issue identity uses the same case normalization as worktree creation. The env ladder (`$KENDEX_SESSION_OWNER`, else `$HT_SESSION_OWNER`, else `$USER`) supplies a fallback identity. Two sessions on one machine share the `$USER` fallback identity, and either can adopt a lease held under it under an issue ID. `cleanup` never releases on an owner match: it skips every lease regardless of owner. The one lease that admits anything is the owner's own under `cleanup --targets-only --worktree PATH --owner ID`, which prunes that worktree's Cargo build output and leaves the lease held. diff --git a/.agents/skills/worktree/scripts/lib/help.sh b/.agents/skills/worktree/scripts/lib/help.sh index 6694a5af..8c7a3863 100755 --- a/.agents/skills/worktree/scripts/lib/help.sh +++ b/.agents/skills/worktree/scripts/lib/help.sh @@ -420,7 +420,13 @@ Failure semantics: manual 'git branch -D' recovery command. Session leases: - remove releases its own lease before removing. A foreign lease is left + Sessions on the same item share one lease; either may release it at close-out. + remove releases it only when its recorded guard writer PID is absent on this + host. A live recorded PID, remote host or unknown process state refuses. + The guard writer exits after claim/refresh. This check covers its write window + and does not establish whether the harness is still working. + ID calls use the item ID; path calls use the private Git issue record. + The session environment is a fallback identity. A foreign lease is left alone and refuses the removal, naming the owner. Lane mailboxes: diff --git a/.agents/skills/worktree/scripts/worktree b/.agents/skills/worktree/scripts/worktree index 13624823..b2f9f461 100755 --- a/.agents/skills/worktree/scripts/worktree +++ b/.agents/skills/worktree/scripts/worktree @@ -2235,40 +2235,32 @@ probe_session_lease() { return "$rc" } -# Release this session's OWN lease on a worktree it is about to remove. Without +# Release the caller's item or environment lease before removal. Without # this a session that claimed its worktree cannot tear it down — the lease is a # native git lock, so `refuse_locked_worktree` and git itself both refuse. It # must therefore run BEFORE that precheck, and after the ownership guard so a # foreign repository's lease is never touched. # -# Ownership is proved by probe, once per identity the caller can claim: the -# issue ID the command was addressed with first (the identity the orchestrating -# workflow claims with), then the session env ladder. Only an owner-matching -# guard lease is released. A foreign lease, a lock taken outside the guard, -# and an unreadable state are all left exactly as they are and fall through to -# the precheck, which names the owner and the way out. +# The issue record uses the branch's lower-case spelling; the lease keeps the +# workflow's spelling. Compare through the existing issue normalizer, then +# release the exact recorded owner. The guard checks its writer PID under its +# mutex; that PID does not establish harness liveness. release_own_session_lease() { - local wt="$1" issue_owner="${2:-}" env_owner owner="" candidate rc + local wt="$1" issue_owner="${2:-}" env_owner owner="" status_rc=0 session_guard_available || return 0 env_owner="$(session_guard_owner)" - if [[ "$env_owner" == "$issue_owner" ]]; then - env_owner="" + owner="$("$SESSION_GUARD" status "$wt" --owner-only --repo "$PROJECT_ROOT" 2>/dev/null)" || status_rc=$? + # status emits the recorded owner before an inherited owner mismatch. + # Adoption changes the item owner while the session environment stays put. + case "$status_rc" in + 0 | 75) ;; + *) return 0 ;; + esac + if [[ "$owner" != "$env_owner" ]]; then + [[ -n "$issue_owner" && "$(issue_branch_name "$owner")" == "$(issue_branch_name "$issue_owner")" ]] || return 0 fi - for candidate in "$issue_owner" "$env_owner"; do - [[ -n "$candidate" ]] || continue - rc=0 - probe_session_lease "$wt" "$candidate" || rc=$? - # 0 alone means "a guard lease exists AND this identity owns it"; 75 is an - # identity mismatch the next candidate may still resolve. Anything else - # (no lease, foreign lock, unreadable) holds for every identity alike. - case "$rc" in - 0) owner="$candidate"; break ;; - 75) continue ;; - *) return 0 ;; - esac - done [[ -n "$owner" ]] || return 0 - if ! "$SESSION_GUARD" release "$wt" --owner "$owner" --repo "$PROJECT_ROOT" >/dev/null; then + if ! "$SESSION_GUARD" release "$wt" --owner "$owner" --inactive --repo "$PROJECT_ROOT" >/dev/null; then worktree_message lease-release-failed "$wt" "Error: could not release this session's guard lease on $wt; refusing to remove it." >&2 echo " Release it, then retry: $SESSION_GUARD release \"$wt\" --owner \"$owner\"" >&2 return 1 @@ -3517,9 +3509,8 @@ case "${1:-}" in worktree_message remove-target-required "target" "Error: remove requires an issue ID or path" >&2 exit 1 fi - # Accept either issue ID or direct path. An issue-addressed removal also - # carries the issue ID as an owner identity for the lease release; - # a path-addressed one has only the session env ladder. + # A path-addressed close-out gets its issue from the private Git record, + # so a relaunched session does not need its predecessor's environment. REMOVE_ISSUE_OWNER="" if [[ "$ARG" == */* ]]; then WT_PATH="$ARG" @@ -3556,6 +3547,10 @@ case "${1:-}" in BRANCH="" # Git keeps HEAD in the registration after the worktree directory is gone. if [[ -n "$REMOVE_GIT_DIR" ]]; then + if [[ -z "$REMOVE_ISSUE_OWNER" && -f "$REMOVE_GIT_DIR/$WORKTREE_ISSUE_RECORD" ]]; then + REMOVE_ISSUE="$(cat -- "$REMOVE_GIT_DIR/$WORKTREE_ISSUE_RECORD")" || exit 1 + REMOVE_ISSUE_OWNER="$(issue_session_owner "$REMOVE_ISSUE")" + fi REMOVE_HEAD="$(cat -- "$REMOVE_GIT_DIR/HEAD")" || exit 1 case "$REMOVE_HEAD" in "ref: refs/heads/"*) BRANCH="${REMOVE_HEAD#ref: refs/heads/}" ;; diff --git a/.agents/skills/worktree/scripts/worktree-session-guard b/.agents/skills/worktree/scripts/worktree-session-guard index ba3c5d6c..d23ff31d 100755 --- a/.agents/skills/worktree/scripts/worktree-session-guard +++ b/.agents/skills/worktree/scripts/worktree-session-guard @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Native Git worktree locks carrying an owner and a TTL heartbeat. # stdout protocol: claim/refresh return the owner; status/list emit complete -# JSON records consumed by worktree's lease probe. Other notices use stable +# JSON records by default. status --owner-only feeds worktree remove. Notices use stable # worktree-: lines; English explanation is not a parsed protocol. set -euo pipefail MESSAGE_DIR=${BASH_SOURCE[0]%/*} @@ -47,6 +47,10 @@ Options (a flag a command does not take is a usage failure): --owner NAME claim, refresh, release, status. Lease owner; defaults to KENDEX_SESSION_OWNER, HT_SESSION_OWNER, then USER for mutating owner commands. + --owner-only status. Print the recorded owner as one line instead of + JSON, or an empty line without a managed lease. Output + precedes the same status exit code, including 75. + worktree remove uses this readback for lease close-out. --adopt claim. Has effect only with --owner: take over a lease held under the environment owner above, as a session-start claim leaves it; without it that lease @@ -58,6 +62,11 @@ Options (a flag a command does not take is a usage failure): --ttl-minutes N release, sweep. Heartbeat TTL in minutes (default 720). --stale release. Release a lease only when it is past the TTL. --force release. Release a foreign lease regardless of age. + --inactive release. With --owner, release only when the recorded + guard writer PID is absent on this host. A live recorded + PID or unknown process state refuses. The writer exits + after claim/refresh; this does not prove harness inactivity. + Cannot combine with --stale or --force. --dry-run sweep. Report results without releasing leases. --repo DIR release, status, list, sweep. Repository checkout. @@ -67,7 +76,8 @@ mutex otherwise; either refuses after waiting 60 seconds for it. Exit codes: 0 success, 1 usage/Git failure or a lock wait that ran out, 3 no lock, 4 non-guard lock, 5 enumeration failure or a lease sweep could -not evaluate, 75 foreign owner/lock or a lease not yet stale. +not evaluate, 75 foreign owner/lock, a lease not yet stale, or an inactive +release whose recorded writer PID is present or cannot be checked. EOF } @@ -299,7 +309,7 @@ lease_age() { printf '%s\n' "$(( $(date -u +%s) - heartbeat ))" } -status_json() { +status_output() { local locked=false managed=false owner='' pid='' host='' claimed='' heartbeat='' age=-1 reason='' if read_lease; then locked=true @@ -314,6 +324,10 @@ status_json() { age="$(lease_age "$LEASE_TEXT" 2>/dev/null || printf '%s' -1)" fi fi + if [[ "$owner_only" == true ]]; then + printf '%s\n' "$owner" + return 0 + fi printf '{"path":"%s","directory_present":%s,"locked":%s,"managed":%s,"owner":"%s","pid":"%s","host":"%s","claimed_at":"%s","heartbeat_at":"%s","heartbeat_age_seconds":%s,"lock_reason":"%s"}\n' \ "$(json_escape "$REQUESTED_PATH")" "$DIRECTORY_PRESENT" "$locked" "$managed" \ "$(json_escape "$owner")" "$(json_escape "$pid")" "$(json_escape "$host")" \ @@ -339,6 +353,25 @@ release_current() { claimed_by "${recorded:-unknown}" return "$EXIT_OWNED" fi + if [[ "$inactive" == true ]]; then + # The lease records the short-lived guard writer, not the harness. + # This protects the writer window only, not a working harness session. + local pid='' host='' process='' process_rc=2 + if pid="$(lease_field "$LEASE_TEXT" pid 2>/dev/null)" && + host="$(lease_field "$LEASE_TEXT" host 2>/dev/null)" && + [[ "$host" == "$(sanitize_host)" && "$pid" =~ ^[1-9][0-9]*$ ]]; then + process_rc=0 + process="$(ps -p "$pid" -o pid= 2>&1)" || process_rc=$? + fi + if [[ "$process_rc" == 0 ]]; then + worktree_message guard-process-live "path=$REQUESTED_PATH pid=$pid" >&2 + return "$EXIT_OWNED" + fi + if [[ "$process_rc" != 1 || -n "$process" ]]; then + worktree_message guard-process-unverified "path=$REQUESTED_PATH pid=$pid host=$host" >&2 + return "$EXIT_OWNED" + fi + fi rm -f -- "$LOCK_FILE" } @@ -369,20 +402,24 @@ require_flag_applies() { OWNER='' owner_set=false +owner_only=false repo="$PWD" repo_set=false ttl="$DEFAULT_TTL_MINUTES" stale=false force=false +inactive=false dry_run=false adopt=false session=false while [[ $# -gt 0 ]]; do case "$1" in --owner) require_flag_applies --owner 'claim refresh release status'; [[ $# -ge 2 ]] || fail guard-option-value --owner "This option requires a value."; OWNER="$(sanitize_owner "$2")"; owner_set=true; shift 2 ;; + --owner-only) require_flag_applies --owner-only 'status'; owner_only=true; shift ;; --ttl-minutes) require_flag_applies --ttl-minutes 'release sweep'; [[ $# -ge 2 && "$2" =~ ^[0-9]{1,10}$ ]] || fail guard-ttl-invalid "${2:-}" "TTL must be a non-negative integer."; ttl="$2"; shift 2 ;; --stale) require_flag_applies --stale 'release'; stale=true; shift ;; --force) require_flag_applies --force 'release'; force=true; shift ;; + --inactive) require_flag_applies --inactive 'release'; inactive=true; shift ;; --dry-run) require_flag_applies --dry-run 'sweep'; dry_run=true; shift ;; --adopt) require_flag_applies --adopt 'claim'; adopt=true; shift ;; --session) require_flag_applies --session 'claim'; session=true; shift ;; @@ -391,6 +428,9 @@ while [[ $# -gt 0 ]]; do *) fail guard-option-unknown "$1" "Unknown session-guard option." ;; esac done +if [[ "$inactive" == true && ( "$owner_set" != true || "$stale" == true || "$force" == true ) ]]; then + fail guard-option-combination --inactive "This option requires --owner and cannot combine with --stale or --force." +fi [[ "$repo_set" == true || -z "$path" || ! -d "$path" ]] || repo="$path" env_owner="${KENDEX_SESSION_OWNER:-${HT_SESSION_OWNER:-${USER:-}}}" if [[ "$owner_set" != true ]]; then @@ -441,7 +481,7 @@ case "$command" in ;; status) resolve_registration "$path" "$repo" || fail guard-worktree-invalid "$path" "Path is not a linked worktree of $repo." - status_json + status_output read_lease || exit "$EXIT_NO_LEASE" lease_is_managed "$LEASE_TEXT" || exit "$EXIT_UNMANAGED" if [[ -n "$OWNER" && "$(lease_field "$LEASE_TEXT" owner 2>/dev/null || true)" != "$OWNER" ]]; then @@ -470,7 +510,7 @@ case "$command" in DIRECTORY_PRESENT=false [[ -d "$REQUESTED_PATH" ]] && DIRECTORY_PRESENT=true if [[ "$command" == list ]]; then - status_json + status_output continue fi read_lease || continue diff --git a/.claude/skills/communication b/.claude/skills/communication new file mode 120000 index 00000000..0b4cbbe0 --- /dev/null +++ b/.claude/skills/communication @@ -0,0 +1 @@ +../../.agents/skills/communication \ No newline at end of file diff --git a/.kendex-generated.json b/.kendex-generated.json index d9f8ff45..c96f3019 100644 --- a/.kendex-generated.json +++ b/.kendex-generated.json @@ -89,6 +89,11 @@ ".agents/skills/commit-guards/scripts/secrets", ".agents/skills/commit-guards/scripts/suppression-ban", ".agents/skills/commit-guards/scripts/todo-ban", + ".agents/skills/communication/SKILL.md", + ".agents/skills/communication/references/messages.md", + ".agents/skills/communication/references/questions.md", + ".agents/skills/communication/references/reports.md", + ".agents/skills/communication/references/voice.md", ".agents/skills/decider/README.md", ".agents/skills/decider/SKILL.md", ".agents/skills/decider/kendex.settings.toml.example", @@ -526,6 +531,7 @@ ".claude/skills/bot-instructions", ".claude/skills/code-quality", ".claude/skills/commit-guards", + ".claude/skills/communication", ".claude/skills/decider", ".claude/skills/deep-research", ".claude/skills/dep-radar", diff --git a/.kendex-lock.json b/.kendex-lock.json index ed055fe7..01d77e6d 100644 --- a/.kendex-lock.json +++ b/.kendex-lock.json @@ -8,7 +8,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f61907f3d571a02cf2a775ebb0034f787a1d5ffe2d68e52585124f28badd368", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -43,7 +43,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f61907f3d571a02cf2a775ebb0034f787a1d5ffe2d68e52585124f28badd368", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -78,7 +78,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f61907f3d571a02cf2a775ebb0034f787a1d5ffe2d68e52585124f28badd368", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -113,7 +113,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f61907f3d571a02cf2a775ebb0034f787a1d5ffe2d68e52585124f28badd368", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -148,7 +148,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "5d2ba692c5b40abe71c7af38392e2ee2aecc2a3b07d256d9b44a4cb4d6c06090", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -185,7 +185,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "5d2ba692c5b40abe71c7af38392e2ee2aecc2a3b07d256d9b44a4cb4d6c06090", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -222,7 +222,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "5d2ba692c5b40abe71c7af38392e2ee2aecc2a3b07d256d9b44a4cb4d6c06090", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -259,7 +259,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "5d2ba692c5b40abe71c7af38392e2ee2aecc2a3b07d256d9b44a4cb4d6c06090", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -296,7 +296,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4a25e8a4c3e339bdf1890993e437e938feed7baa0a565bbe09e873ec62a75c64", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -327,7 +327,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4a25e8a4c3e339bdf1890993e437e938feed7baa0a565bbe09e873ec62a75c64", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -358,7 +358,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4a25e8a4c3e339bdf1890993e437e938feed7baa0a565bbe09e873ec62a75c64", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -389,7 +389,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4a25e8a4c3e339bdf1890993e437e938feed7baa0a565bbe09e873ec62a75c64", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -420,7 +420,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "a1802df17bd986fd550df5df1d70792098e98f5b2e518364a51337835cab6bb7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -453,7 +453,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "a1802df17bd986fd550df5df1d70792098e98f5b2e518364a51337835cab6bb7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -486,7 +486,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "a1802df17bd986fd550df5df1d70792098e98f5b2e518364a51337835cab6bb7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -519,7 +519,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "a1802df17bd986fd550df5df1d70792098e98f5b2e518364a51337835cab6bb7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -552,7 +552,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3002276f894146f3c381e406e2c14d3ef3f75e64e0d7a51c1a8be30486bfa79e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -582,7 +582,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3002276f894146f3c381e406e2c14d3ef3f75e64e0d7a51c1a8be30486bfa79e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -612,7 +612,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3002276f894146f3c381e406e2c14d3ef3f75e64e0d7a51c1a8be30486bfa79e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -642,7 +642,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3002276f894146f3c381e406e2c14d3ef3f75e64e0d7a51c1a8be30486bfa79e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -672,7 +672,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "64f1a2e0e2bb4c4bac776f8c489c4fbaa17f149f955092737e47c72cc31bb7b2", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -702,7 +702,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "64f1a2e0e2bb4c4bac776f8c489c4fbaa17f149f955092737e47c72cc31bb7b2", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -732,7 +732,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "64f1a2e0e2bb4c4bac776f8c489c4fbaa17f149f955092737e47c72cc31bb7b2", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -762,7 +762,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "64f1a2e0e2bb4c4bac776f8c489c4fbaa17f149f955092737e47c72cc31bb7b2", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -792,7 +792,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c29a9dd689ce336a07824eb0fb8d518191124b6be0c5ca037a65ca618cd07106", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -822,7 +822,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c29a9dd689ce336a07824eb0fb8d518191124b6be0c5ca037a65ca618cd07106", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -852,7 +852,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c29a9dd689ce336a07824eb0fb8d518191124b6be0c5ca037a65ca618cd07106", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -882,7 +882,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c29a9dd689ce336a07824eb0fb8d518191124b6be0c5ca037a65ca618cd07106", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -912,7 +912,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e0a3a3a908ecfb00b4e9ae083e0ce2a2db55183f0ab878a38d8092eaaee6d8ad", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -942,7 +942,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e0a3a3a908ecfb00b4e9ae083e0ce2a2db55183f0ab878a38d8092eaaee6d8ad", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -972,7 +972,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e0a3a3a908ecfb00b4e9ae083e0ce2a2db55183f0ab878a38d8092eaaee6d8ad", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1002,7 +1002,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e0a3a3a908ecfb00b4e9ae083e0ce2a2db55183f0ab878a38d8092eaaee6d8ad", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1032,7 +1032,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "954fde6a7332eac489845daa35b7413e7a216823cba8bcf73aaeecf180d73f3d", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1062,7 +1062,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "954fde6a7332eac489845daa35b7413e7a216823cba8bcf73aaeecf180d73f3d", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1092,7 +1092,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "954fde6a7332eac489845daa35b7413e7a216823cba8bcf73aaeecf180d73f3d", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1122,7 +1122,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "954fde6a7332eac489845daa35b7413e7a216823cba8bcf73aaeecf180d73f3d", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1152,7 +1152,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ac74145015e2575770fdaa3f2730ef7672b1cc72c0159a5a4f390e1b1f474f2f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1182,7 +1182,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ac74145015e2575770fdaa3f2730ef7672b1cc72c0159a5a4f390e1b1f474f2f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1212,7 +1212,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ac74145015e2575770fdaa3f2730ef7672b1cc72c0159a5a4f390e1b1f474f2f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1242,7 +1242,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ac74145015e2575770fdaa3f2730ef7672b1cc72c0159a5a4f390e1b1f474f2f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1272,7 +1272,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5bba5231d21a1ecf327af004dbcc34c36fe074fa2ce01fc855848017d7ccd8a", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1302,7 +1302,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5bba5231d21a1ecf327af004dbcc34c36fe074fa2ce01fc855848017d7ccd8a", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1332,7 +1332,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5bba5231d21a1ecf327af004dbcc34c36fe074fa2ce01fc855848017d7ccd8a", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1362,7 +1362,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5bba5231d21a1ecf327af004dbcc34c36fe074fa2ce01fc855848017d7ccd8a", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1392,7 +1392,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5c7aad291389053ed6aae2b30ced684b9818e83d3faf332c316bc80d8b126f6", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1422,7 +1422,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5c7aad291389053ed6aae2b30ced684b9818e83d3faf332c316bc80d8b126f6", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1452,7 +1452,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5c7aad291389053ed6aae2b30ced684b9818e83d3faf332c316bc80d8b126f6", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1482,7 +1482,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5c7aad291389053ed6aae2b30ced684b9818e83d3faf332c316bc80d8b126f6", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1512,7 +1512,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e9b4d7ef81ad5f5439354dee4ce7f41a9a5b02e4e2c196a202b649bfbb489342", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1542,7 +1542,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e9b4d7ef81ad5f5439354dee4ce7f41a9a5b02e4e2c196a202b649bfbb489342", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1572,7 +1572,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e9b4d7ef81ad5f5439354dee4ce7f41a9a5b02e4e2c196a202b649bfbb489342", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1602,7 +1602,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e9b4d7ef81ad5f5439354dee4ce7f41a9a5b02e4e2c196a202b649bfbb489342", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1632,7 +1632,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "23ac64c27be9ea4619067d5facaa78f01edf2d37e986ec0a6f023eb51c61dc01", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1667,7 +1667,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "23ac64c27be9ea4619067d5facaa78f01edf2d37e986ec0a6f023eb51c61dc01", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1702,7 +1702,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "23ac64c27be9ea4619067d5facaa78f01edf2d37e986ec0a6f023eb51c61dc01", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1737,7 +1737,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "23ac64c27be9ea4619067d5facaa78f01edf2d37e986ec0a6f023eb51c61dc01", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1772,7 +1772,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b264e304113e038b3eb1fd220e50a7122ac11b270fbd4e6bc145e95f4bc9bd65", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1807,7 +1807,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b264e304113e038b3eb1fd220e50a7122ac11b270fbd4e6bc145e95f4bc9bd65", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1842,7 +1842,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b264e304113e038b3eb1fd220e50a7122ac11b270fbd4e6bc145e95f4bc9bd65", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1877,7 +1877,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b264e304113e038b3eb1fd220e50a7122ac11b270fbd4e6bc145e95f4bc9bd65", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1912,7 +1912,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1510d851b6a09b92fc0c50f142733a8273e0fdc85e87a0bbde43dd9fbee280f9", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1943,7 +1943,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1510d851b6a09b92fc0c50f142733a8273e0fdc85e87a0bbde43dd9fbee280f9", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -1974,7 +1974,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1510d851b6a09b92fc0c50f142733a8273e0fdc85e87a0bbde43dd9fbee280f9", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2005,7 +2005,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1510d851b6a09b92fc0c50f142733a8273e0fdc85e87a0bbde43dd9fbee280f9", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2036,7 +2036,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f04b302951c4fe6adc0e0dc7124417a847b00ea2902666c8f8a869bc79895d88", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2070,7 +2070,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f04b302951c4fe6adc0e0dc7124417a847b00ea2902666c8f8a869bc79895d88", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2104,7 +2104,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f04b302951c4fe6adc0e0dc7124417a847b00ea2902666c8f8a869bc79895d88", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2138,7 +2138,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f04b302951c4fe6adc0e0dc7124417a847b00ea2902666c8f8a869bc79895d88", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2172,7 +2172,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d2dac90f8f53f19ae855924d27b53c54d2b28871a4f84b068d6a2bad0c4f6c36", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2199,7 +2199,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d2dac90f8f53f19ae855924d27b53c54d2b28871a4f84b068d6a2bad0c4f6c36", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2226,7 +2226,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d2dac90f8f53f19ae855924d27b53c54d2b28871a4f84b068d6a2bad0c4f6c36", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2253,7 +2253,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b733e4ad323748222e30134660417d1de58727dbdaee690b9b9f27f5d23f12a7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2285,7 +2285,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b733e4ad323748222e30134660417d1de58727dbdaee690b9b9f27f5d23f12a7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2317,7 +2317,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b733e4ad323748222e30134660417d1de58727dbdaee690b9b9f27f5d23f12a7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2349,7 +2349,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b733e4ad323748222e30134660417d1de58727dbdaee690b9b9f27f5d23f12a7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2381,7 +2381,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "47bf5378331d6d82cf860c3c38150cb95b21f6b7d12841f7ee056c55622799e8", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2413,7 +2413,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "47bf5378331d6d82cf860c3c38150cb95b21f6b7d12841f7ee056c55622799e8", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2445,7 +2445,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "056014489bdf17897fb9de308ecc1ea22c3ffdf83c3894382b08f0e94b2dbcdb", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2477,7 +2477,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "056014489bdf17897fb9de308ecc1ea22c3ffdf83c3894382b08f0e94b2dbcdb", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2509,7 +2509,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "056014489bdf17897fb9de308ecc1ea22c3ffdf83c3894382b08f0e94b2dbcdb", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2541,7 +2541,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "056014489bdf17897fb9de308ecc1ea22c3ffdf83c3894382b08f0e94b2dbcdb", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2573,7 +2573,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "8d06d8ae1faf86625add070a7a6dca48c5be41a600e7cecfbd71e6e151f5e769", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2605,7 +2605,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "8d06d8ae1faf86625add070a7a6dca48c5be41a600e7cecfbd71e6e151f5e769", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2637,7 +2637,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "8d06d8ae1faf86625add070a7a6dca48c5be41a600e7cecfbd71e6e151f5e769", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2669,7 +2669,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "8d06d8ae1faf86625add070a7a6dca48c5be41a600e7cecfbd71e6e151f5e769", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2701,7 +2701,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ec0e477e5664f963929581df503d093d4ae21da6b76d6f3d542f7980c3a9a08a", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2733,7 +2733,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ec0e477e5664f963929581df503d093d4ae21da6b76d6f3d542f7980c3a9a08a", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2765,7 +2765,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ec0e477e5664f963929581df503d093d4ae21da6b76d6f3d542f7980c3a9a08a", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2797,7 +2797,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ec0e477e5664f963929581df503d093d4ae21da6b76d6f3d542f7980c3a9a08a", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2829,7 +2829,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4cca63d27e717911ce6dff804126511f8611fea1dd170d913defcfea15bdf2c7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2870,7 +2870,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4cca63d27e717911ce6dff804126511f8611fea1dd170d913defcfea15bdf2c7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2911,7 +2911,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4cca63d27e717911ce6dff804126511f8611fea1dd170d913defcfea15bdf2c7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2952,7 +2952,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4cca63d27e717911ce6dff804126511f8611fea1dd170d913defcfea15bdf2c7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -2993,7 +2993,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "9246462997cb2e9e8166226f651f7598ea6c81bd0e025f9861e7366ffca2d699", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3031,7 +3031,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "158045e0bc3594e6b18d6cb77032b9ef98aad34cee1b35a0f556684c76a09fc9", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3063,7 +3063,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "158045e0bc3594e6b18d6cb77032b9ef98aad34cee1b35a0f556684c76a09fc9", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3095,7 +3095,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "aa8ec9e210f6385308d6a824177a1cc7e5e88460918a904a5519836428824444", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3190,7 +3190,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "aa8ec9e210f6385308d6a824177a1cc7e5e88460918a904a5519836428824444", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3258,7 +3258,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "aa8ec9e210f6385308d6a824177a1cc7e5e88460918a904a5519836428824444", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3353,7 +3353,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "aa8ec9e210f6385308d6a824177a1cc7e5e88460918a904a5519836428824444", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3430,7 +3430,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1bfbcb2c43e6fab13888956bdc98691ec72d4eadf293187f4867af817d60bdbe", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3462,7 +3462,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7a99ebbd12769b351b8656699134c0f93d7ab06af43b4cb4ea8ac410fcaf64aa", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3503,7 +3503,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7a99ebbd12769b351b8656699134c0f93d7ab06af43b4cb4ea8ac410fcaf64aa", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3544,7 +3544,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7a99ebbd12769b351b8656699134c0f93d7ab06af43b4cb4ea8ac410fcaf64aa", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3585,7 +3585,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7a99ebbd12769b351b8656699134c0f93d7ab06af43b4cb4ea8ac410fcaf64aa", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3626,7 +3626,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4fa45a9fc7c4f7a5bb5ff5bb66e392460442ac8ed4ef14832d17832a2a4515eb", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3667,7 +3667,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4fa45a9fc7c4f7a5bb5ff5bb66e392460442ac8ed4ef14832d17832a2a4515eb", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3708,7 +3708,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4fa45a9fc7c4f7a5bb5ff5bb66e392460442ac8ed4ef14832d17832a2a4515eb", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3749,7 +3749,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4fa45a9fc7c4f7a5bb5ff5bb66e392460442ac8ed4ef14832d17832a2a4515eb", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3790,7 +3790,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "eef427b33e0fbbfbb8b807dd0986ffa66ce350033aac9bb23255988b03925024", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3828,7 +3828,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b128f266b3d67697e7ac128f8aabc97b472a03cc7fe6f05e4fc9b145cc315442", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3860,7 +3860,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c7905659a294ec88a2b38b9bfbf071d0160a45689ece954a0f9564e3c5791ba2", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3901,7 +3901,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d8a11a3b614b97c3b0c304cae7494a16510c998f1f325f0ad10874957c43b917", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3933,7 +3933,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d8a11a3b614b97c3b0c304cae7494a16510c998f1f325f0ad10874957c43b917", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3965,7 +3965,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d8a11a3b614b97c3b0c304cae7494a16510c998f1f325f0ad10874957c43b917", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -3997,7 +3997,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d8a11a3b614b97c3b0c304cae7494a16510c998f1f325f0ad10874957c43b917", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4029,7 +4029,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "87dd5148fca28408dab96f6a6819bb3d43cf6da54ad02c4cf60fc953e50bbc43", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4061,7 +4061,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "87dd5148fca28408dab96f6a6819bb3d43cf6da54ad02c4cf60fc953e50bbc43", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4093,7 +4093,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "26090ae471accc49d86a2b1c10fd364b72df1ce4f6a767fd10e82318770d3105", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4125,7 +4125,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "26090ae471accc49d86a2b1c10fd364b72df1ce4f6a767fd10e82318770d3105", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4157,7 +4157,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "26090ae471accc49d86a2b1c10fd364b72df1ce4f6a767fd10e82318770d3105", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4189,7 +4189,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d7dad268fbd914b6517b1afe088558166c009cd0ac221ce83fed82de7e8488e3", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4221,7 +4221,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d7dad268fbd914b6517b1afe088558166c009cd0ac221ce83fed82de7e8488e3", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4253,7 +4253,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d7dad268fbd914b6517b1afe088558166c009cd0ac221ce83fed82de7e8488e3", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4285,7 +4285,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f8fa08d86e3482b5f30034dd7522ce3236f6e6a5000b8f64d6009093dccc5577", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4326,7 +4326,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f8fa08d86e3482b5f30034dd7522ce3236f6e6a5000b8f64d6009093dccc5577", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4367,7 +4367,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f8fa08d86e3482b5f30034dd7522ce3236f6e6a5000b8f64d6009093dccc5577", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4408,7 +4408,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f8fa08d86e3482b5f30034dd7522ce3236f6e6a5000b8f64d6009093dccc5577", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4449,7 +4449,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fb43be6b7dee642b200268fbe71e14cc96282ea06a1554012ab80ce52a92ba79", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4490,7 +4490,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fb43be6b7dee642b200268fbe71e14cc96282ea06a1554012ab80ce52a92ba79", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4531,7 +4531,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fb43be6b7dee642b200268fbe71e14cc96282ea06a1554012ab80ce52a92ba79", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4572,7 +4572,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fb43be6b7dee642b200268fbe71e14cc96282ea06a1554012ab80ce52a92ba79", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4613,7 +4613,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "101caf97829906294354478ca77d288f5311a70a3c6ba90ae2babf9e3bf34624", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4654,7 +4654,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "101caf97829906294354478ca77d288f5311a70a3c6ba90ae2babf9e3bf34624", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4695,7 +4695,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "a334bd710c5b926e24b2dd2a066d3b4dcd6747030a111bf7cabcc545ea242ad7", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4727,7 +4727,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "9425ae12b1eb7229702d033513e1758ae9a092db8f561b912e74c6740bbfa2ef", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4768,7 +4768,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3e981ce407351f70b1e2dbc8e46840b64be2ecd8b17fe16ccdff0960edf2f7ad", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4809,7 +4809,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3e981ce407351f70b1e2dbc8e46840b64be2ecd8b17fe16ccdff0960edf2f7ad", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4841,7 +4841,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3e981ce407351f70b1e2dbc8e46840b64be2ecd8b17fe16ccdff0960edf2f7ad", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4873,7 +4873,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3e981ce407351f70b1e2dbc8e46840b64be2ecd8b17fe16ccdff0960edf2f7ad", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4905,7 +4905,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "17acbaa3d814c683f04c45b904c6aeba02c20bcc0fe529e2333031077abdac6f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4942,7 +4942,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "17acbaa3d814c683f04c45b904c6aeba02c20bcc0fe529e2333031077abdac6f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -4978,7 +4978,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "17acbaa3d814c683f04c45b904c6aeba02c20bcc0fe529e2333031077abdac6f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5014,7 +5014,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "17acbaa3d814c683f04c45b904c6aeba02c20bcc0fe529e2333031077abdac6f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5050,7 +5050,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "bed7626f1d7e1f047a4f3f49ff2d2b83167d03ea2610d85e0c4cddd892353157", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5105,7 +5105,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "bed7626f1d7e1f047a4f3f49ff2d2b83167d03ea2610d85e0c4cddd892353157", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5159,7 +5159,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "bed7626f1d7e1f047a4f3f49ff2d2b83167d03ea2610d85e0c4cddd892353157", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5213,7 +5213,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "bed7626f1d7e1f047a4f3f49ff2d2b83167d03ea2610d85e0c4cddd892353157", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5267,7 +5267,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "98fc478b875c8c5b7d831bce38f1eb2665925e6c5c76eeba6184e80d1b5554ac", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5322,7 +5322,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "98fc478b875c8c5b7d831bce38f1eb2665925e6c5c76eeba6184e80d1b5554ac", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5376,7 +5376,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "98fc478b875c8c5b7d831bce38f1eb2665925e6c5c76eeba6184e80d1b5554ac", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5430,7 +5430,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "98fc478b875c8c5b7d831bce38f1eb2665925e6c5c76eeba6184e80d1b5554ac", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5477,6 +5477,139 @@ } ] }, + "skill:communication:claude": { + "name": "communication", + "kind": "skill", + "harness": "claude", + "source": "kendex", + "sourceRepo": "vanillagreencom/kendex", + "sourceHash": "02cfb4aeb93eee375890032cc3eaaf0d896ced7d85619dfd636eb37c08611aae", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "selector": { + "sourceRev": null, + "rev": null + }, + "renderedHash": "ae5b6c36a5920f095847eea18d59c11350a268a4f335dcef1e2fa65e00251e2f", + "enabled": true, + "emitted": { + "kind": "skill", + "name": "communication", + "paths": [ + ".agents/skills/communication", + ".claude/skills/communication" + ] + }, + "reasons": [ + { + "reason": "required-by", + "by": { + "source": "kendex", + "kind": "skill", + "name": "orch", + "harness": "claude" + } + } + ] + }, + "skill:communication:codex": { + "name": "communication", + "kind": "skill", + "harness": "codex", + "source": "kendex", + "sourceRepo": "vanillagreencom/kendex", + "sourceHash": "02cfb4aeb93eee375890032cc3eaaf0d896ced7d85619dfd636eb37c08611aae", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "selector": { + "sourceRev": null, + "rev": null + }, + "renderedHash": "ae5b6c36a5920f095847eea18d59c11350a268a4f335dcef1e2fa65e00251e2f", + "enabled": true, + "emitted": { + "kind": "skill", + "name": "communication", + "paths": [ + ".agents/skills/communication" + ] + }, + "reasons": [ + { + "reason": "required-by", + "by": { + "source": "kendex", + "kind": "skill", + "name": "orch", + "harness": "codex" + } + } + ] + }, + "skill:communication:copilot": { + "name": "communication", + "kind": "skill", + "harness": "copilot", + "source": "kendex", + "sourceRepo": "vanillagreencom/kendex", + "sourceHash": "02cfb4aeb93eee375890032cc3eaaf0d896ced7d85619dfd636eb37c08611aae", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "selector": { + "sourceRev": null, + "rev": null + }, + "renderedHash": "ae5b6c36a5920f095847eea18d59c11350a268a4f335dcef1e2fa65e00251e2f", + "enabled": true, + "emitted": { + "kind": "skill", + "name": "communication", + "paths": [ + ".agents/skills/communication" + ] + }, + "reasons": [ + { + "reason": "required-by", + "by": { + "source": "kendex", + "kind": "skill", + "name": "orch", + "harness": "copilot" + } + } + ] + }, + "skill:communication:pi": { + "name": "communication", + "kind": "skill", + "harness": "pi", + "source": "kendex", + "sourceRepo": "vanillagreencom/kendex", + "sourceHash": "02cfb4aeb93eee375890032cc3eaaf0d896ced7d85619dfd636eb37c08611aae", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "selector": { + "sourceRev": null, + "rev": null + }, + "renderedHash": "ae5b6c36a5920f095847eea18d59c11350a268a4f335dcef1e2fa65e00251e2f", + "enabled": true, + "emitted": { + "kind": "skill", + "name": "communication", + "paths": [ + ".agents/skills/communication" + ] + }, + "reasons": [ + { + "reason": "required-by", + "by": { + "source": "kendex", + "kind": "skill", + "name": "orch", + "harness": "pi" + } + } + ] + }, "skill:decider:claude": { "name": "decider", "kind": "skill", @@ -5484,7 +5617,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b4a75dca09bb20bb042bde9f3998d836b981a5b8030ec9690ca01e6836a2f752", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5539,7 +5672,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b4a75dca09bb20bb042bde9f3998d836b981a5b8030ec9690ca01e6836a2f752", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5593,7 +5726,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b4a75dca09bb20bb042bde9f3998d836b981a5b8030ec9690ca01e6836a2f752", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5647,7 +5780,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b4a75dca09bb20bb042bde9f3998d836b981a5b8030ec9690ca01e6836a2f752", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5701,7 +5834,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f07de0df87cd6a53de4d68f1098c408db4e8d73fa88822426de3cad6875f04e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5729,7 +5862,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f07de0df87cd6a53de4d68f1098c408db4e8d73fa88822426de3cad6875f04e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5756,7 +5889,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f07de0df87cd6a53de4d68f1098c408db4e8d73fa88822426de3cad6875f04e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5783,7 +5916,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f07de0df87cd6a53de4d68f1098c408db4e8d73fa88822426de3cad6875f04e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5810,7 +5943,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f2bca9bc82c0e18f23e61cc013e521dd5b6867f5038845a1163ee1effa83abed", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5838,7 +5971,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f2bca9bc82c0e18f23e61cc013e521dd5b6867f5038845a1163ee1effa83abed", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5865,7 +5998,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f2bca9bc82c0e18f23e61cc013e521dd5b6867f5038845a1163ee1effa83abed", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5892,7 +6025,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f2bca9bc82c0e18f23e61cc013e521dd5b6867f5038845a1163ee1effa83abed", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5919,7 +6052,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "2b4fb8a2e6cee53ac5340737a5b71cd26ff88276766ac78fcc45c7f28769822c", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5956,7 +6089,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "2b4fb8a2e6cee53ac5340737a5b71cd26ff88276766ac78fcc45c7f28769822c", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -5992,7 +6125,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "2b4fb8a2e6cee53ac5340737a5b71cd26ff88276766ac78fcc45c7f28769822c", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6028,7 +6161,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "2b4fb8a2e6cee53ac5340737a5b71cd26ff88276766ac78fcc45c7f28769822c", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6064,7 +6197,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fd88aed4b9211e14a8250139ebedd785f139c9e508101465548c06a6571fec46", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6092,7 +6225,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fd88aed4b9211e14a8250139ebedd785f139c9e508101465548c06a6571fec46", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6119,7 +6252,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fd88aed4b9211e14a8250139ebedd785f139c9e508101465548c06a6571fec46", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6146,7 +6279,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fd88aed4b9211e14a8250139ebedd785f139c9e508101465548c06a6571fec46", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6173,7 +6306,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "0a859081ace51943009f81b7748b1f08a236bb886fe50495e2d26518524ec195", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6219,7 +6352,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "0a859081ace51943009f81b7748b1f08a236bb886fe50495e2d26518524ec195", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6264,7 +6397,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "0a859081ace51943009f81b7748b1f08a236bb886fe50495e2d26518524ec195", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6309,7 +6442,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "0a859081ace51943009f81b7748b1f08a236bb886fe50495e2d26518524ec195", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6354,7 +6487,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "831b57913311d8fd3bcdd376b7da7ef3344ab22702865bcb731393dc7580662b", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6436,7 +6569,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "831b57913311d8fd3bcdd376b7da7ef3344ab22702865bcb731393dc7580662b", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6517,7 +6650,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "831b57913311d8fd3bcdd376b7da7ef3344ab22702865bcb731393dc7580662b", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6598,7 +6731,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "831b57913311d8fd3bcdd376b7da7ef3344ab22702865bcb731393dc7580662b", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6679,7 +6812,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3168f92b017a42bfd272b4be616ab39c22c1b3f5640f8087e1740b3f8be99666", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6725,7 +6858,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3168f92b017a42bfd272b4be616ab39c22c1b3f5640f8087e1740b3f8be99666", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6770,7 +6903,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3168f92b017a42bfd272b4be616ab39c22c1b3f5640f8087e1740b3f8be99666", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6815,7 +6948,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3168f92b017a42bfd272b4be616ab39c22c1b3f5640f8087e1740b3f8be99666", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -6859,13 +6992,13 @@ "harness": "claude", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "c96c42363dac3c7b8232bb83423595a22845c88397a0ac274a8c40572266d9df", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "3ba41c08e765a62757dfa60e6c5c182e18491c2f94223824957cc50187ffc823", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "14768e2e2c2db99224d39f192ac75a2f095dac390e40796d4473d8fe527fe360", + "renderedHash": "702a10c23daa5e3ede1297689361914d0ba4e4010535a945dcf0fa559056c48b", "enabled": true, "emitted": { "kind": "skill", @@ -6896,13 +7029,13 @@ "harness": "codex", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "c96c42363dac3c7b8232bb83423595a22845c88397a0ac274a8c40572266d9df", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "3ba41c08e765a62757dfa60e6c5c182e18491c2f94223824957cc50187ffc823", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "14768e2e2c2db99224d39f192ac75a2f095dac390e40796d4473d8fe527fe360", + "renderedHash": "702a10c23daa5e3ede1297689361914d0ba4e4010535a945dcf0fa559056c48b", "enabled": true, "emitted": { "kind": "skill", @@ -6932,13 +7065,13 @@ "harness": "copilot", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "c96c42363dac3c7b8232bb83423595a22845c88397a0ac274a8c40572266d9df", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "3ba41c08e765a62757dfa60e6c5c182e18491c2f94223824957cc50187ffc823", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "14768e2e2c2db99224d39f192ac75a2f095dac390e40796d4473d8fe527fe360", + "renderedHash": "702a10c23daa5e3ede1297689361914d0ba4e4010535a945dcf0fa559056c48b", "enabled": true, "emitted": { "kind": "skill", @@ -6968,13 +7101,13 @@ "harness": "pi", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "c96c42363dac3c7b8232bb83423595a22845c88397a0ac274a8c40572266d9df", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "3ba41c08e765a62757dfa60e6c5c182e18491c2f94223824957cc50187ffc823", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "14768e2e2c2db99224d39f192ac75a2f095dac390e40796d4473d8fe527fe360", + "renderedHash": "702a10c23daa5e3ede1297689361914d0ba4e4010535a945dcf0fa559056c48b", "enabled": true, "emitted": { "kind": "skill", @@ -7005,7 +7138,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "65b880f56f31d134b2e2cb53b693f434825143b9c5b7022a89b11fa733f4ee2e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7048,7 +7181,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "65b880f56f31d134b2e2cb53b693f434825143b9c5b7022a89b11fa733f4ee2e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7090,7 +7223,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "65b880f56f31d134b2e2cb53b693f434825143b9c5b7022a89b11fa733f4ee2e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7132,7 +7265,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "65b880f56f31d134b2e2cb53b693f434825143b9c5b7022a89b11fa733f4ee2e", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7173,13 +7306,13 @@ "harness": "claude", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "9fe5b741f613c0df2b3e65b02a5f5b58c52ffc65c2d2e15edaf3d6e52296a205", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "555518b41740a2d1e50708d8c0f586633773bdb15794bce752c8cfd2fafa2daa", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "7a7bb4c4d944320939ddfe7a22bd636f0314c66ed723848ff1be1d08bdbb3933", + "renderedHash": "f06541ec1f671c27d52b6d75fb3f7926f0c7545256e60ff2b6f49d9be32b8109", "enabled": true, "emitted": { "kind": "skill", @@ -7255,13 +7388,13 @@ "harness": "codex", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "9fe5b741f613c0df2b3e65b02a5f5b58c52ffc65c2d2e15edaf3d6e52296a205", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "555518b41740a2d1e50708d8c0f586633773bdb15794bce752c8cfd2fafa2daa", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "7a7bb4c4d944320939ddfe7a22bd636f0314c66ed723848ff1be1d08bdbb3933", + "renderedHash": "f06541ec1f671c27d52b6d75fb3f7926f0c7545256e60ff2b6f49d9be32b8109", "enabled": true, "emitted": { "kind": "skill", @@ -7336,13 +7469,13 @@ "harness": "copilot", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "9fe5b741f613c0df2b3e65b02a5f5b58c52ffc65c2d2e15edaf3d6e52296a205", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "555518b41740a2d1e50708d8c0f586633773bdb15794bce752c8cfd2fafa2daa", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "7a7bb4c4d944320939ddfe7a22bd636f0314c66ed723848ff1be1d08bdbb3933", + "renderedHash": "f06541ec1f671c27d52b6d75fb3f7926f0c7545256e60ff2b6f49d9be32b8109", "enabled": true, "emitted": { "kind": "skill", @@ -7408,13 +7541,13 @@ "harness": "pi", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "9fe5b741f613c0df2b3e65b02a5f5b58c52ffc65c2d2e15edaf3d6e52296a205", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "555518b41740a2d1e50708d8c0f586633773bdb15794bce752c8cfd2fafa2daa", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "7a7bb4c4d944320939ddfe7a22bd636f0314c66ed723848ff1be1d08bdbb3933", + "renderedHash": "f06541ec1f671c27d52b6d75fb3f7926f0c7545256e60ff2b6f49d9be32b8109", "enabled": true, "emitted": { "kind": "skill", @@ -7481,7 +7614,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e967f26a25614f2028d62a3d0a9a4ae1a45d5e15d438f27f32006afa4de3dc7f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7509,7 +7642,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e967f26a25614f2028d62a3d0a9a4ae1a45d5e15d438f27f32006afa4de3dc7f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7536,7 +7669,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e967f26a25614f2028d62a3d0a9a4ae1a45d5e15d438f27f32006afa4de3dc7f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7563,7 +7696,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e967f26a25614f2028d62a3d0a9a4ae1a45d5e15d438f27f32006afa4de3dc7f", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7590,7 +7723,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "457ba4b0812f431f86d0b5c4ed21e8f9b2f39ecbf49cfcf1f2e0172797e7d1fe", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7636,7 +7769,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "457ba4b0812f431f86d0b5c4ed21e8f9b2f39ecbf49cfcf1f2e0172797e7d1fe", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7681,7 +7814,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "457ba4b0812f431f86d0b5c4ed21e8f9b2f39ecbf49cfcf1f2e0172797e7d1fe", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7726,7 +7859,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "457ba4b0812f431f86d0b5c4ed21e8f9b2f39ecbf49cfcf1f2e0172797e7d1fe", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7771,7 +7904,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1bbf866e0a8475b09892ab440195b61e3c1ea252497ff568de02bfa921c203f8", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7817,7 +7950,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1bbf866e0a8475b09892ab440195b61e3c1ea252497ff568de02bfa921c203f8", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7862,7 +7995,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1bbf866e0a8475b09892ab440195b61e3c1ea252497ff568de02bfa921c203f8", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7907,7 +8040,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1bbf866e0a8475b09892ab440195b61e3c1ea252497ff568de02bfa921c203f8", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -7951,13 +8084,13 @@ "harness": "claude", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "1e44b9baf9b34c01696c287282cf9a303ff42167896209d30f24abcdd28a100d", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "88fff5eb5e09dd6ed63d56799b56af08853870b9215d7be54285d52cde241980", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "b536514737c3b77c4cc55fe1f846bcb3090de906e92cdc119c53cc9319f93ce7", + "renderedHash": "90dc770c020cce471396e00d3eec68377df7638c5956124628b3591eb28a8f89", "enabled": true, "emitted": { "kind": "skill", @@ -8015,13 +8148,13 @@ "harness": "codex", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "1e44b9baf9b34c01696c287282cf9a303ff42167896209d30f24abcdd28a100d", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "88fff5eb5e09dd6ed63d56799b56af08853870b9215d7be54285d52cde241980", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "b536514737c3b77c4cc55fe1f846bcb3090de906e92cdc119c53cc9319f93ce7", + "renderedHash": "90dc770c020cce471396e00d3eec68377df7638c5956124628b3591eb28a8f89", "enabled": true, "emitted": { "kind": "skill", @@ -8078,13 +8211,13 @@ "harness": "copilot", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "1e44b9baf9b34c01696c287282cf9a303ff42167896209d30f24abcdd28a100d", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "88fff5eb5e09dd6ed63d56799b56af08853870b9215d7be54285d52cde241980", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "b536514737c3b77c4cc55fe1f846bcb3090de906e92cdc119c53cc9319f93ce7", + "renderedHash": "90dc770c020cce471396e00d3eec68377df7638c5956124628b3591eb28a8f89", "enabled": true, "emitted": { "kind": "skill", @@ -8141,13 +8274,13 @@ "harness": "pi", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "1e44b9baf9b34c01696c287282cf9a303ff42167896209d30f24abcdd28a100d", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "88fff5eb5e09dd6ed63d56799b56af08853870b9215d7be54285d52cde241980", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "b536514737c3b77c4cc55fe1f846bcb3090de906e92cdc119c53cc9319f93ce7", + "renderedHash": "90dc770c020cce471396e00d3eec68377df7638c5956124628b3591eb28a8f89", "enabled": true, "emitted": { "kind": "skill", @@ -8205,7 +8338,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c4c87f61d4b51c532387d32daa24f0eda5fb1433ca6fe50d3261473410ec8ae4", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -8233,7 +8366,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c4c87f61d4b51c532387d32daa24f0eda5fb1433ca6fe50d3261473410ec8ae4", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -8260,7 +8393,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c4c87f61d4b51c532387d32daa24f0eda5fb1433ca6fe50d3261473410ec8ae4", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -8287,7 +8420,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c4c87f61d4b51c532387d32daa24f0eda5fb1433ca6fe50d3261473410ec8ae4", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null @@ -8313,13 +8446,13 @@ "harness": "claude", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "59dc6c64d9c08a8d7dd4abfb6784494d0866bd8d285029b094624d6c90f2fb56", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "7fef40dd6cf911411a9c4a340ddc550d73a8f0e3c9d7c4ff0b8280d4a139c3df", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "23271d3e56a6c34d0b62911a1c0e6d41fe5ed4a1e0bbb8aecfed264f14e975ca", + "renderedHash": "e5b70366847b3e0dcbeb0aadcf6b4c97380869acdef667d5d0105892f1549c93", "enabled": true, "emitted": { "kind": "skill", @@ -8359,13 +8492,13 @@ "harness": "codex", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "59dc6c64d9c08a8d7dd4abfb6784494d0866bd8d285029b094624d6c90f2fb56", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "7fef40dd6cf911411a9c4a340ddc550d73a8f0e3c9d7c4ff0b8280d4a139c3df", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "23271d3e56a6c34d0b62911a1c0e6d41fe5ed4a1e0bbb8aecfed264f14e975ca", + "renderedHash": "e5b70366847b3e0dcbeb0aadcf6b4c97380869acdef667d5d0105892f1549c93", "enabled": true, "emitted": { "kind": "skill", @@ -8404,13 +8537,13 @@ "harness": "copilot", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "59dc6c64d9c08a8d7dd4abfb6784494d0866bd8d285029b094624d6c90f2fb56", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "7fef40dd6cf911411a9c4a340ddc550d73a8f0e3c9d7c4ff0b8280d4a139c3df", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "23271d3e56a6c34d0b62911a1c0e6d41fe5ed4a1e0bbb8aecfed264f14e975ca", + "renderedHash": "e5b70366847b3e0dcbeb0aadcf6b4c97380869acdef667d5d0105892f1549c93", "enabled": true, "emitted": { "kind": "skill", @@ -8449,13 +8582,13 @@ "harness": "pi", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "59dc6c64d9c08a8d7dd4abfb6784494d0866bd8d285029b094624d6c90f2fb56", - "sourceCommit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9", + "sourceHash": "7fef40dd6cf911411a9c4a340ddc550d73a8f0e3c9d7c4ff0b8280d4a139c3df", + "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "23271d3e56a6c34d0b62911a1c0e6d41fe5ed4a1e0bbb8aecfed264f14e975ca", + "renderedHash": "e5b70366847b3e0dcbeb0aadcf6b4c97380869acdef667d5d0105892f1549c93", "enabled": true, "emitted": { "kind": "skill", @@ -8492,7 +8625,7 @@ "sources": { "kendex": { "repo": "vanillagreencom/kendex", - "commit": "45471b2a05abd05c7eb0c9e028ffc6b5eb050eb9" + "commit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34" } }, "claudeProjectDefault": "owned"