Skill Proposal
Ce skill couvre l'étape Planning du workflow AI-DLC : créer des Proposals contenant des brouillons de documents (PRD, tech design) et des brouillons de tâches avec des DAGs de dépendances, puis les soumettre pour révision par l'Admin.
Vue d'ensemble
Après résolution de l'élaboration d'une Idea (voir le skill idea, skill_view("chorus:idea")), l'Agent PM crée une Proposal — un conteneur qui contient des brouillons de documents et des brouillons de tâches. À l'approbation de l'Admin, ces brouillons se matérialisent en vrais Documents et Tâches.
Elaboration resolved --> Create Proposal --> Add drafts --> Validate --> Submit --> Reviewer --> Admin review
Outils
Gestion des Proposals :
| Outil | Objectif |
|---|---|
chorus_pm_create_proposal |
Créer un conteneur de proposal vide |
chorus_pm_validate_proposal |
Valider la complétude de la proposal (retourne erreurs, avertissements, info) |
chorus_pm_submit_proposal |
Soumettre la proposal pour approbation Admin (draft -> pending) |
Brouillons de documents :
| Outil | Objectif |
|---|---|
chorus_pm_add_document_draft |
Ajouter un brouillon de document à la proposal |
chorus_pm_update_document_draft |
Mettre à jour le contenu du brouillon de document |
chorus_pm_remove_document_draft |
Retirer un brouillon de document de la proposal |
Brouillons de tâches :
| Outil | Objectif |
|---|---|
chorus_pm_add_task_draft |
Ajouter un brouillon de tâche (retourne draftUuid pour chaînage de dépendances) |
chorus_pm_update_task_draft |
Mettre à jour le brouillon de tâche |
chorus_pm_remove_task_draft |
Retirer un brouillon de tâche de la proposal |
Post-approbation (les tâches existent) :
| Outil | Objectif |
|---|---|
chorus_create_tasks |
Créer des tâches en batch (supporte les dépendances intra-batch via draftUuid) |
chorus_pm_assign_task |
Assigner une tâche à un Agent Développeur |
chorus_pm_create_document |
Créer un document autonome |
chorus_pm_update_document |
Mettre à jour le contenu du document (incrémente la version) |
chorus_update_task (avec addDependsOn / removeDependsOn) |
Ajouter ou retirer les dépendances de tâche (avec détection de cycles) |
Outils partagés (checkin, query, comment, search, notifications) : voir le skill overview (skill_view("chorus:chorus"))
Workflow
Étape 0 : Réutiliser les preuves et vérifier les nouvelles lacunes factuelles
Lisez la ou les Idea(s) d'entrée confirmée(s) ou les Documents, les spécifications actuelles, les Références et le contexte récent avant de rédiger. Réutilisez d'abord les résultats existants ; invoquez le skill research (skill_view("chorus:research"), règles partagées) uniquement pour une nouvelle lacune de conception factuelle ou une demande explicite de l'utilisateur, sauf skip explicite. Fournissez l'étape Proposal, la question focalisée, les preuves existantes et le budget. Ne répétez pas automatiquement la recherche d'Idea, y compris lors d'une reprise de planning ; cet itinéraire s'applique aussi aux entrées créées par formulaire/MCP sans flag de recherche.
Si la Proposal n'existe pas encore, conservez les URL/titres/types de source candidates dans le contexte courant, puis incluez-les dans references[] lors de l'appel Step 1 chorus_pm_create_proposal si possible. Lisez chorus_get_proposal après pour obtenir les vrais references[].uuid ; la création inline retourne l'UUID du conteneur, pas les UUIDs de preuves individuelles. Si elle existe déjà, réutilisez ses preuves ou attachez de nouvelles sources via chorus_add_reference et prenez l'UUID de référence retourné. Écrivez ensuite des citations comme [1](ref:<uuid-de-référence-réel>) à côté des déclarations soutenues dans la conception/les spécifications. Ne fabriquez jamais d'UUIDs ni ne substituez l'UUID Proposal.
En modes OpenSpec/spec-lite, résolvez le mode de spec existant et le localisateur comme ci-dessous, mettez à jour les fichiers locaux autoritaires avec les résultats et des citations réelles, puis miroir les octets de fichier en utilisant chorus mcp call … --arg-file content=<fichier> via terminal (ou, quand chorus n'est pas sur PATH, l'outil MCP natif avec content défini aux octets exacts du fichier lus via read_file). Pas de content MCP document dactylographié à la main ; la spec.md durable de spec-lite reste locale uniquement. Le mode libre-forme conserve son chemin de sauvegarde de brouillon normal. Les résultats vides/partiels préservent les inconnues et poursuivent la préparation. La recherche ne soumet, n'approuve ni ne contourne les restrictions de révision ; les proposals en attente/approuvées conservent leurs portails de révision existants. Une instruction Tracker de recherche seule retourne par l'itinéraire Idea au lieu d'entrer ce workflow de rédaction.
Étape 1 : Créer une Proposal vide
Résolvez le mode de spec (Étape 1.5) AVANT cette création. En modes OpenSpec et spec-lite, la description du conteneur DOIT porter une ligne de localisateur (OpenSpec change slug: <slug> ou Spec-lite: .chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/), et description ne peut être défini qu'à la création — décidez du mode + slug/chemin daté d'abord et incluez cette ligne dans cet appel unique. NE créez PAS un conteneur nu et ne réalisez ensuite que vous en aviez besoin. Le mode libre-forme omet toute ligne de localisateur.
Approche recommandée : Créez d'abord le conteneur de proposal (avec la ligne de localisateur du mode dans description le cas échéant), puis ajoutez progressivement les brouillons de documents et de tâches un par un.
chorus_pm_create_proposal({
projectUuid: "<project-uuid>",
title: "Implement <feature name>",
description: "Analysis and implementation plan for Idea #xxx",
inputType: "idea",
inputUuids: ["<idea-uuid>"]
})
Idées multiples : Vous pouvez combiner plusieurs ideas en une seule proposal en passant plusieurs UUIDs dans inputUuids.
Un thème ne peut pas être une entrée de proposal —
chorus_pm_create_proposalrejette toute idea d'entrée avecisContainer = true. Dérivez une idea enfant du thème et écrivez la proposal sur l'enfant à la place. (Voir la section theme-ideas du skill idea,skill_view("chorus:idea").)
Étape 1.5 : Sélectionner le mode de spec
Le mode de spec est déjà calculé pour vous par le plugin Chorus Hermes — ne le re-dérivez PAS. Son vérification pre_llm_call (premier tour de chaque session, et à nouveau après /reset ou compression du contexte) résout le mode avec spec_mode.py du plugin (l'explicite CHORUS_SPEC_MODE l'emporte ; sinon openspec quand un répertoire openspec/ et la CLI openspec sont tous deux présents dans le répertoire de travail ; sinon lite) et l'injecte comme la section ## Spec Mode de votre contexte : il indique CHORUS_SPEC_MODE=<lite|openspec|off> + une note de routage. (Pas de ## Spec Mode dans le contexte, p. ex. vous êtes un enfant delegate_task ? Voir openspec-aware §1 fallback manuel via skill_view("chorus:openspec-aware") — ne roll jamais la règle à la main.) Agissez sur cette valeur :
-
Si la section dit que le mode ne peut pas être honoré (
CHORUS_SPEC_MODE=openspecexplicite mais OpenSpec inutilisable — raison de conflit de config ou indice d'installation), arrêtez et surfacez-le ; ne faites pas de fallback. -
Sinon branchez sur le mode résolu :
-
resolved = spec-lite → charger le skill
spec-lite(skill_view("chorus:spec-lite")) et le suivre : choisissez$SLUG(une capacité, pas un seul changement). Assurez-vous que le.chorus/specs/<slug>/spec.mddurable existe (local uniquement, pas d'ids Chorus ; utilisez le template spec-durable inline du skillspec-lite) et mettez-le à jour en place. Créez le dossier daté de ce changement.chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/avec ses docs Chorus-typés synchronisés (prd.mdprincipal, optionneltech_design.md… ; utilisez le template de dossier daté inline du skillspec-lite). Mettez la ligne de localisateur littéraleSpec-lite: .chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/dans la Step 1 createdescription, puis miroir chaque<type>.mddu dossier daté vers son Document persistant (chorus_pm_add_document_draft --arg-filela première fois,chorus_pm_update_document --arg-fileaprès) viachorus mcp call … --arg-file content=.chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/<type>.md(exécutez viaterminal; voirskill_view("chorus:chorus-cli")).spec.mdn'est jamais miroir. Sautez l'Étape 2 ci-dessous. (Tâches viachorus_pm_add_task_draft; pas detasks.md.) -
resolved = OpenSpec (la section
## Spec ModeafficheCHORUS_OPENSPEC_ACTIVE=1— c.-à-d.CHORUS_SPEC_MODE=openspecou non défini, avec OpenSpec utilisable) → suivez le skillopenspec-aware§3 (skill_view("chorus:openspec-aware")). Choisissez$SLUG, scaffoldezopenspec/changes/<slug>/, écrivezproposal.md/design.md/specs/<capability>/spec.mdlocalement, puis mettez la ligne littéraleOpenSpec change slug: <slug>dans la Step 1 createdescription, et miroir chaque fichier local dans un brouillon de document.⛔ Obligatoire en mode OpenSpec : les appels de miroir remplissent
contentà partir du fichier local — préférezchorus mcp call … --arg-file content=<fichier>exécutée viaterminal; quandchorusn'est pas surPATH, retombez sur l'appel de l'outil MCP natif (mcp__chorus__chorus_pm_add_document_draft/mcp__chorus__chorus_pm_update_document_draft) aveccontentdéfini aux octets exacts du fichier retournés parread_file— voiropenspec-aware§3.6. Ne appelez paschorus_pm_add_document_draftavec un champcontentdactylographié à la main ou paraphrasé. Re-taper des milliers de lignes brûle 20 000+ tokens de contenu par proposal et brise l'égalité d'octets (openspec-aware§2 Règle 1). Sautez l'Étape 2 en mode OpenSpec — le flux de remplissage de fichier la remplace pour les documents. -
resolved = free-form (
CHORUS_SPEC_MODE=offexplicite) → procédez avec l'Étape 2 inchangée. Écrivez les brouillons inline comme Markdown libre via MCPchorus_pm_add_document_draftdirect.
Étape 2 : Ajouter des brouillons de documents
Ajoutez les brouillons de documents un à la fois :
# Add PRD
chorus_pm_add_document_draft({
proposalUuid: "<proposal-uuid>",
type: "prd",
title: "PRD: <Feature Name>",
content: "# PRD: <Feature Name>\n\n## Background\n...\n## Requirements\n..."
})
# Add Tech Design
chorus_pm_add_document_draft({
proposalUuid: "<proposal-uuid>",
type: "tech_design",
title: "Tech Design: <Feature Name>",
content: "# Technical Design\n\n## Architecture\n...\n## Implementation\n..."
})
Types de documents : prd, tech_design, adr, spec, guide
Étape 3 : Ajouter des brouillons de tâches
Ajoutez les brouillons de tâches un à la fois. La réponse retourne le draftUuid du nouveau brouillon — utilisez-le directement pour dependsOnDraftUuids dans les brouillons suivants.
acceptanceCriteriaItems est obligatoire — chaque brouillon de tâche doit inclure au moins un élément avec une description non vide, sinon l'appel est rejeté. Utilisez le tableau acceptanceCriteriaItems structuré (la chaîne Markdown acceptanceCriteria héritée ne satisfait pas l'exigence).
# First task -> response includes { draftUuid, draftTitle }
chorus_pm_add_task_draft({
proposalUuid: "<proposal-uuid>",
title: "Implement <component>",
description: "Detailed description of what to build...",
priority: "high",
storyPoints: 3,
acceptanceCriteriaItems: [
{ description: "Criteria 1", required: true },
{ description: "Criteria 2", required: true }
]
})
# Second task — depends on first
chorus_pm_add_task_draft({
proposalUuid: "<proposal-uuid>",
title: "Write tests for <component>",
description: "Unit and integration tests...",
priority: "medium",
storyPoints: 2,
acceptanceCriteriaItems: [
{ description: "Test coverage > 80%", required: true }
],
dependsOnDraftUuids: ["<draftUuid-from-first-task>"]
})
Pour éditer les critères d'un brouillon plus tard via
chorus_pm_update_task_draft, passez unacceptanceCriteriaItemsnon vide pour les remplacer ; omettez le champ pour les laisser inchangés. Le champ ne peut pas être utilisé pour effacer les critères.
Priorité de tâche : low, medium, high
Étape 4 : Réviser et affiner les brouillons
# Review current state. chorus_get_proposal defaults to section:"basic"
# (metadata + a lightweight draft index, no bodies). Use section:"full" to
# see every draft's content, or section:"documents"/"tasks" for one kind.
chorus_get_proposal({ proposalUuid: "<proposal-uuid>", section: "full" })
# Update a document draft
chorus_pm_update_document_draft({
proposalUuid: "<proposal-uuid>",
draftUuid: "<draft-uuid>",
content: "Updated content..."
})
# Update a task draft
chorus_pm_update_task_draft({
proposalUuid: "<proposal-uuid>",
draftUuid: "<draft-uuid>",
description: "Updated description...",
dependsOnDraftUuids: ["<other-draft-uuid>"]
})
# Remove a draft
chorus_pm_remove_task_draft({
proposalUuid: "<proposal-uuid>",
draftUuid: "<draft-uuid>"
})
Étape 5 : Valider et soumettre
Avant de soumettre, validez pour prévisualiser les problèmes :
chorus_pm_validate_proposal({ proposalUuid: "<proposal-uuid>" })
Retourne { valid, issues } avec niveaux erreur, avertissement et info. Corrigez les erreurs avant de soumettre.
Quand la validation réussit :
chorus_pm_submit_proposal({ proposalUuid: "<proposal-uuid>" })
Cela change le statut de draft à pending. Un Admin l'examinera (voir skill_view("chorus:review")).
Ajoutez un commentaire expliquant votre raisonnement :
chorus_add_comment({
targetType: "proposal",
targetUuid: "<proposal-uuid>",
content: "This proposal covers... Key decisions: ..."
})
Étape 5.5 : Exécuter le Proposal Reviewer
Le hook transform_tool_result du plugin Chorus Hermes ajoute un rappel au résultat de chorus_pm_submit_proposal : exécutez le chorus-proposal-reviewer indépendant et en lecture seule avant approbation admin. Exécutez-le comme un enfant delegate_task :
delegate_task(
goal="[chorus-reviewer:proposal] Review Chorus proposal <proposal-uuid> and post one VERDICT comment.",
context="[chorus-reviewer:proposal]\nFirst call skill_view(\"chorus:chorus-proposal-reviewer\") and follow it.\nProposal UUID: <proposal-uuid>\nProject UUID: <project-uuid>\nMax review rounds: 3\nFirst read existing comments to determine the round number; post VERDICT as a comment.\nRepo: <abs path>"
)
- Le marqueur
[chorus-reviewer:proposal]DOIT être la première ligne ducontext(gardez-le dansgoalaussi). Le plugin l'utilise pour exécuter l'enfant sous la garde du reviewer en lecture seule : les outils Chorus d'écriture autres quechorus_add_commentsont bloqués, tout commewrite_file,patch,terminal,execute_codeetdelegate_task. - L'enfant démarre avec un contexte isolé et ne sait rien de cette conversation. Mettez tout ce dont il a besoin (UUIDs proposal/project, limite de tours, chemin repo, chemins de fichiers spec locaux qu'il devrait
read_file) danscontext. delegate_taskse bloque jusqu'à ce que le reviewer termine et retourne son résumé ; rien n'a besoin d'être suivi ou fermé.
Après son retour, lisez les commentaires avec chorus_get_comments({ targetType: "proposal", targetUuid: "<proposal-uuid>" }) et trouvez la ligne VERDICT: de CE tour — le commentaire posté après que vous ayez envoyé le reviewer, pas un ancien tour :
- VERDICT: PASS — Aucun problème. Procédez à
chorus_admin_approve_proposal(si vous avezproposal:adminet l'humain vous a délégué l'approbation ; sinon laissez-le pour l'Admin). - VERDICT: PASS WITH NOTES — Notes mineures. Approuvez toujours.
- VERDICT: FAIL — BLOCKERs trouvés. N'approuvez PAS. Rejetez avec
chorus_pm_reject_proposal, corrigez, resoumettez (Étape 6) et exécutez à nouveau le reviewer — jusqu'à la limite de 3 tours.
Étape 6 : Gérer les retours
Après submission, le chorus-proposal-reviewer (Étape 5.5) poste un commentaire VERDICT. Si le VERDICT est FAIL, ou un Admin rejette la proposal, vous devez réviser et resoummettre.
IMPORTANT : Une proposal en statut pending ne peut pas être éditée. Vous devez la rejeter d'abord pour la retourner au statut draft avant d'éditer des brouillons.
-
Lisez les retours :
chorus_get_proposal({ proposalUuid: "<proposal-uuid>", section: "full" }) chorus_get_comments({ targetType: "proposal", targetUuid: "<proposal-uuid>" })Identifiez les BLOCKERs du VERDICT reviewer ou de la note de rejet.
-
Rejetez la proposal (auto-rejet de la vôtre, ou demandez à l'admin de rejeter celle de quelqu'un d'autre) :
chorus_pm_reject_proposal({ proposalUuid: "<proposal-uuid>", reviewNote: "Reviewer FAIL. Fixing BLOCKERs: <list>" })Cela retourne la proposal au statut
draft. Les agents PM ne peuvent rejeter que leurs propres proposals ; les agents admin peuvent rejeter toute proposal. -
Révisez les brouillons :
chorus_pm_update_document_draft({ proposalUuid: "<proposal-uuid>", draftUuid: "<uuid>", content: "..." }) chorus_pm_update_task_draft({ proposalUuid: "<proposal-uuid>", draftUuid: "<uuid>", ... }) -
Resoumettez :
chorus_pm_submit_proposal({ proposalUuid: "<proposal-uuid>" })Puis exécutez à nouveau le reviewer (Étape 5.5) pour le prochain tour.
Étape 7 : Post-approbation
Quand l'Admin approuve :
- Les brouillons de documents deviennent de vrais Documents
- Les brouillons de tâches deviennent de vraies Tâches (statut :
open, prêtes pour les développeurs) - Le statut affiché de l'Idea est automatiquement dérivé de la progression de la Proposal et des Tâches — aucune mise à jour manuelle nécessaire
Étape 8 : Gérer les dépendances de tâches (Optionnel)
Après création des tâches, vous pouvez gérer les dépendances :
Créer les tâches en batch avec dépendances intra-batch :
chorus_create_tasks({
projectUuid: "<project-uuid>",
tasks: [
{ draftUuid: "draft-db", title: "Create database schema", priority: "high", storyPoints: 2 },
{ draftUuid: "draft-api", title: "Implement API endpoints", priority: "high", storyPoints: 4, dependsOnDraftUuids: ["draft-db"] },
{ title: "Write integration tests", priority: "medium", storyPoints: 2, dependsOnDraftUuids: ["draft-api"] }
]
})
Ajouter/retirer les dépendances sur les tâches existantes :
chorus_update_task({ taskUuid: "<task-B-uuid>", addDependsOn: ["<task-A-uuid>"] })
chorus_update_task({ taskUuid: "<task-B-uuid>", removeDependsOn: ["<task-A-uuid>"] })
Les dépendances sont validées : même projet, pas d'autodépendance, pas de cycles (détection DFS).
Étape 9 : Assigner les tâches aux agents développeurs (Optionnel)
chorus_pm_assign_task({ taskUuid: "<task-uuid>", agentUuid: "<developer-agent-uuid>" })
# Optional: pin the task to a specific (agent, host, cwd) AgentInstance
chorus_pm_assign_task({ taskUuid: "<task-uuid>", agentUuid: "<developer-agent-uuid>", instanceUuid: "<agent-instance-uuid>" })
- La tâche doit être
openouassigned - L'agent cible doit avoir la permission
task: ["write"] - Passez
instanceUuidpour épingler la tâche à une instance spécifique en ligne (assigne commeagent_instance) ; omettez-le pour une assignationagentplain qui hérite l'instance épinglée de l'idea racine au moment du wake
Directives de rédaction de documents
Structure PRD
# PRD: <Feature Name>
## Background
Why this feature is needed.
## Requirements
### Functional Requirements
- FR-1: ...
### Non-Functional Requirements
- NFR-1: ...
## User Stories
- As a <role>, I want <action>, so that <benefit>
## Out of Scope
What is NOT included.
Structure Tech Design
# Technical Design: <Feature Name>
## Overview
High-level approach.
## Architecture
System design, component interactions.
## Data Model
Schema changes, new tables.
## API Design
New/modified endpoints.
## Module Contracts
Shared conventions across tasks: return value format, error handling pattern, cross-module call points.
## Implementation Plan
Step-by-step implementation order.
## Risks & Mitigations
Potential issues and how to address them.
Directives de rédaction de tâches
Les bonnes tâches sont :
- Module-scoped — Un module fonctionnel cohésif par tâche, pas une fonction ou fichier unique
- Testable — Des critères d'acceptation clairs et cohésifs sont obligatoires sur chaque tâche (au moins un élément non vide ; max 6 ; groupez les vérifications connexes en un critère mais listez la couverture clé, p. ex. « Tous les tests réussissent : tests unitaires de la couche service, tests d'intégration API, gestion des cas limites »)
- Dimensionnée — 1-8 story points (heures de travail de l'agent)
- Ordonnée — Utilisez
dependsOnDraftUuids/dependsOnTaskUuidspour exprimer l'ordre d'exécution - Descriptive — Incluez suffisamment de contexte pour qu'un agent développeur puisse démarrer sans questions. Pour les tâches avec dépendances inter-modules, référencez les Module Contracts du tech design dans l'AC
- Points de contrôle d'intégration — Pour les DAGs avec 4+ tâches, incluez au moins une tâche de point de contrôle d'intégration à un point de convergence dont l'AC exige l'exécution bout à bout des modules précédents ensemble
- Hallucination-aware — Quand les tâches impliquent des dépendances externes, notez dans la description de tâche que les développeurs doivent vérifier les spécifiques (signatures d'API, flags CLI, clés de config, IDs de modèle, etc.) par rapport aux docs officielles plutôt que de se fier à la mémoire LLM
Granularité de tâche
Chaque tâche doit correspondre à un module fonctionnel indépendamment exécutable et testable — pas une fonction, fichier ou endpoint API unique. Évitez de scinder les fonctionnalités étroitement liées en tâches séparées ; la surcharge du workflow Chorus par tâche (claim → implement → self-test → submit → verify) s'accumule rapidement.
Mauvais → Bons exemples :
- Mauvais :
Book Search+Book CRUD(2 tâches) → Bon :Book Management(1 tâche couvrant CRUD + Search pour la même entité) - Mauvais :
Chart Rendering+Statistics Calculation(2 tâches) → Bon :Data Analytics(1 tâche couvrant stats + visualisation comme un module)
Conseils
- Gardez le PRD focalisé sur quoi et pourquoi ; tech design focalisé sur comment
- Divisez les grandes fonctionnalités en tâches module-scoped cohésives — mais évitez de sur-diviser les fonctionnalités connexes en trop de minuscules tâches
- Ajoutez
storyPointspour aider à prioriser et estimer l'effort - Gardez les critères d'acceptation cohésifs — groupez les vérifications connexes en un élément plutôt que de lister chaque vérification séparément
- Configurez toujours le DAG de dépendance de tâche — les tâches sans dépendances sont supposées parallélisables
- Quand plusieurs tâches partagent des formats de données ou s'appellent mutuellement, définissez les contrats dans le tech design avant d'écrire l'AC des tâches
- Quand vous combinez plusieurs ideas, expliquez comment elles se rapportent dans la description de la proposal
Suivant
- Après submission, un Admin examinera en utilisant le skill review (
skill_view("chorus:review")) - Après approbation, les Développeurs réclament les tâches en utilisant le skill develop (
skill_view("chorus:develop")) - Pour l'élaboration d'Idea, voir
skill_view("chorus:idea") - Pour la vue d'ensemble de la plateforme, voir
skill_view("chorus:chorus")