qfai 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -36
- package/assets/defaults/agent-routing/qfai-implement.yml +9 -0
- package/assets/defaults/agent-routing/qfai-triage.yml +18 -0
- package/assets/defaults/workflows/answer-in-session.yml +8 -0
- package/assets/defaults/workflows/quarantine-flaky.yml +3 -0
- package/assets/defaults/workflows/repair-consistency.yml +1 -0
- package/assets/defaults/workflows/run-operation.yml +11 -0
- package/assets/defaults/workflows/run-owned-cleanup.yml +12 -0
- package/assets/defaults/workflows/write-procedure.yml +18 -0
- package/assets/graph/codegraph-native.mjs +174 -0
- package/assets/graph/graphify-native.py +72 -0
- package/assets/init/.claude/settings.json +9 -9
- package/assets/init/.codex/hooks.json +8 -8
- package/assets/init/.qfai/assistant/agent/frontend-engineer.md +5 -0
- package/assets/init/.qfai/assistant/agent/product-experience-architect.md +4 -0
- package/assets/init/.qfai/assistant/agent/product-surface-reviewer.md +7 -0
- package/assets/init/.qfai/assistant/agent/requirements-analyst.md +8 -0
- package/assets/init/.qfai/assistant/rule/communication.md +18 -8
- package/assets/init/.qfai/assistant/rule/constitution.md +31 -15
- package/assets/init/.qfai/assistant/rule/drift-protocol.md +119 -2
- package/assets/init/.qfai/assistant/rule/references/asset-authoring.md +6 -4
- package/assets/init/.qfai/assistant/rule/references/codex-delegation.md +27 -0
- package/assets/init/.qfai/assistant/rule/references/griller-recommendations.md +21 -9
- package/assets/init/.qfai/assistant/rule/references/worker-edit-boundary.md +48 -0
- package/assets/init/.qfai/assistant/rule/review-convergence.md +25 -12
- package/assets/init/.qfai/assistant/rule/shared-skill-delegation-baseline.md +16 -25
- package/assets/init/.qfai/assistant/rule/shared-skill-operating-baseline.md +16 -11
- package/assets/init/.qfai/assistant/rule/ui-definition-protocol.md +6 -1
- package/assets/init/.qfai/assistant/rule/workflow.md +2 -1
- package/assets/init/.qfai/assistant/skill/qfai-configure/SKILL.md +3 -3
- package/assets/init/.qfai/assistant/skill/qfai-discussion/SKILL.md +6 -0
- package/assets/init/.qfai/assistant/skill/qfai-discussion/references/discussion-completion-matrix.md +20 -15
- package/assets/init/.qfai/assistant/skill/qfai-discussion/references/ui-bearing-playbook.md +2 -4
- package/assets/init/.qfai/assistant/skill/qfai-discussion/references/ui_ux_best_practices.md +1 -6
- package/assets/init/.qfai/assistant/skill/qfai-discussion/templates/uiux/00_index.md +0 -16
- package/assets/init/.qfai/assistant/skill/qfai-grilling/SKILL.md +30 -20
- package/assets/init/.qfai/assistant/skill/qfai-grilling/references/delegated-session.md +4 -3
- package/assets/init/.qfai/assistant/skill/qfai-grilling/references/session-record.md +8 -2
- package/assets/init/.qfai/assistant/skill/qfai-implement/SKILL.md +16 -3
- package/assets/init/.qfai/assistant/skill/qfai-implement/references/parallelization-policy.md +9 -1
- package/assets/init/.qfai/assistant/skill/qfai-implement/references/red-admissibility.md +46 -0
- package/assets/init/.qfai/assistant/skill/qfai-implement/references/ui-affecting.md +5 -2
- package/assets/init/.qfai/assistant/skill/qfai-maintain/SKILL.md +3 -3
- package/assets/init/.qfai/assistant/skill/qfai-migration-v1-to-v2/SKILL.md +12 -6
- package/assets/init/.qfai/assistant/skill/qfai-migration-v1-to-v2/references/migration-guide.md +1 -265
- package/assets/init/.qfai/assistant/skill/qfai-migration-v1-to-v2/references/migration-placement.md +273 -0
- package/assets/init/.qfai/assistant/skill/qfai-prototyping/SKILL.md +4 -3
- package/assets/init/.qfai/assistant/skill/qfai-prototyping/references/review-payload-schema.md +2 -3
- package/assets/init/.qfai/assistant/skill/qfai-prototyping/references/reviewer-prompt.md +17 -1
- package/assets/init/.qfai/assistant/skill/qfai-run/SKILL.md +52 -37
- package/assets/init/.qfai/assistant/skill/qfai-run/references/codex-cloud-install.md +80 -0
- package/assets/init/.qfai/assistant/skill/qfai-run/references/evidence-delivery.md +322 -0
- package/assets/init/.qfai/assistant/skill/qfai-run/references/extraction.md +83 -49
- package/assets/init/.qfai/assistant/skill/qfai-run/references/operator-screens.md +226 -11
- package/assets/init/.qfai/assistant/skill/qfai-run/references/plan.md +6 -3
- package/assets/init/.qfai/assistant/skill/qfai-run/references/reached-step-observations.md +132 -0
- package/assets/init/.qfai/assistant/skill/qfai-run/references/stage-points.md +14 -0
- package/assets/init/.qfai/assistant/skill/qfai-run/scripts/codex-cloud-install.mjs +117 -0
- package/assets/init/.qfai/assistant/skill/qfai-sdd/SKILL.md +4 -3
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/contract-artifact-rules.md +1 -0
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/design-anti-patterns.md +23 -5
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/design-md-authoring.md +20 -7
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/requirements-decomposition.md +8 -0
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-execution-playbook.md +29 -4
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-phase-checklists.md +1 -1
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-pre-draft-grilling.md +4 -1
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-quality-gate.md +1 -1
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-triage.md +159 -4
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/spec-traceability-rules.md +14 -2
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/ui-contract-guide.md +146 -0
- package/assets/init/.qfai/assistant/skill/qfai-sdd/references/ui-design-contract-normalization.md +4 -29
- package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/change-request.md +38 -1
- package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/contracts/ui-contract.sample.yaml +52 -5
- package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/spec/decisions.md +12 -0
- package/assets/init/.qfai/assistant/skill/qfai-triage/SKILL.md +34 -21
- package/assets/init/.qfai/assistant/skill/qfai-verify/SKILL.md +5 -4
- package/assets/init/.qfai/assistant/skill/qfai-verify/references/context-load.md +9 -6
- package/assets/init/.qfai/assistant/skill/qfai-verify/references/verify-output-contract.md +80 -15
- package/assets/init/.qfai/assistant/skill/web-research/SKILL.md +35 -21
- package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/brave-search/config.toml +2 -4
- package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/brave-search/mcp-config.json +9 -5
- package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/firecrawl/.mcp.json +1 -2
- package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/firecrawl/config.toml +3 -3
- package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/firecrawl/mcp-config.json +11 -8
- package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/playwright/config.toml +1 -1
- package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/playwright/mcp-config.json +7 -3
- package/assets/init/.qfai/assistant/step/common-design-md/STEP.md +33 -20
- package/assets/init/.qfai/assistant/step/common-gate-run/STEP.md +124 -8
- package/assets/init/.qfai/assistant/step/common-grilling-record/STEP.md +10 -2
- package/assets/init/.qfai/assistant/step/common-policy-check/STEP.md +1 -0
- package/assets/init/.qfai/assistant/step/common-review-cycle/STEP.md +26 -9
- package/assets/init/.qfai/assistant/step/discussion-interview/STEP.md +15 -8
- package/assets/init/.qfai/assistant/step/discussion-oq/STEP.md +5 -1
- package/assets/init/.qfai/assistant/step/discussion-pack/STEP.md +6 -1
- package/assets/init/.qfai/assistant/step/discussion-research/STEP.md +2 -0
- package/assets/init/.qfai/assistant/step/discussion-uiux/STEP.md +6 -4
- package/assets/init/.qfai/assistant/step/implement-backport/STEP.md +1 -1
- package/assets/init/.qfai/assistant/step/implement-benchmark/STEP.md +7 -4
- package/assets/init/.qfai/assistant/step/implement-dep-bump/STEP.md +11 -2
- package/assets/init/.qfai/assistant/step/implement-diagnose/STEP.md +2 -0
- package/assets/init/.qfai/assistant/step/implement-oracle-parity/STEP.md +2 -2
- package/assets/init/.qfai/assistant/step/implement-procedure/STEP.md +69 -0
- package/assets/init/.qfai/assistant/step/implement-quarantine/STEP.md +24 -7
- package/assets/init/.qfai/assistant/step/implement-refactor/STEP.md +2 -2
- package/assets/init/.qfai/assistant/step/implement-regression-fix/STEP.md +7 -6
- package/assets/init/.qfai/assistant/step/implement-retire/STEP.md +6 -3
- package/assets/init/.qfai/assistant/step/implement-revert/STEP.md +4 -3
- package/assets/init/.qfai/assistant/step/implement-seam/STEP.md +6 -5
- package/assets/init/.qfai/assistant/step/implement-stress-harness/STEP.md +34 -3
- package/assets/init/.qfai/assistant/step/implement-sweep/STEP.md +4 -3
- package/assets/init/.qfai/assistant/step/implement-tdd/STEP.md +39 -5
- package/assets/init/.qfai/assistant/step/implement-tooling/STEP.md +22 -2
- package/assets/init/.qfai/assistant/step/maintain-edit/STEP.md +18 -14
- package/assets/init/.qfai/assistant/step/prototyping-grill/STEP.md +4 -3
- package/assets/init/.qfai/assistant/step/prototyping-loop/STEP.md +4 -0
- package/assets/init/.qfai/assistant/step/prototyping-preflight/STEP.md +9 -3
- package/assets/init/.qfai/assistant/step/sdd-contract/STEP.md +11 -0
- package/assets/init/.qfai/assistant/step/sdd-flow/STEP.md +2 -0
- package/assets/init/.qfai/assistant/step/sdd-story/STEP.md +10 -0
- package/assets/init/.qfai/assistant/step/sdd-triage/STEP.md +34 -10
- package/assets/init/.qfai/assistant/step/triage-answer/STEP.md +7 -6
- package/assets/init/.qfai/assistant/step/triage-close/STEP.md +33 -23
- package/assets/init/.qfai/assistant/step/triage-cluster/STEP.md +5 -3
- package/assets/init/.qfai/assistant/step/triage-decompose/STEP.md +2 -0
- package/assets/init/.qfai/assistant/step/triage-dedupe/STEP.md +4 -0
- package/assets/init/.qfai/assistant/step/triage-handoff/STEP.md +13 -4
- package/assets/init/.qfai/assistant/step/triage-investigate/STEP.md +8 -5
- package/assets/init/.qfai/assistant/step/triage-operate/STEP.md +50 -0
- package/assets/init/.qfai/assistant/step/triage-owned-cleanup/STEP.md +86 -0
- package/assets/init/.qfai/assistant/step/triage-request-info/STEP.md +2 -0
- package/assets/init/.qfai/assistant/step/triage-security-intake/STEP.md +6 -3
- package/assets/init/.qfai/assistant/step/verify-change-note/STEP.md +1 -0
- package/assets/init/.qfai/assistant/step/verify-commit/STEP.md +37 -9
- package/assets/init/.qfai/assistant/step/verify-external/STEP.md +5 -2
- package/assets/init/.qfai/assistant/step/verify-qfai-gate/STEP.md +14 -16
- package/assets/init/.qfai/assistant/step/verify-release-notes/STEP.md +1 -0
- package/assets/init/.qfai/assistant/step/verify-repeat-run/STEP.md +46 -4
- package/assets/init/.qfai/assistant/step/verify-repo-gate/STEP.md +133 -30
- package/assets/init/root/.agents/rules/ai-readable-markdown.md +2 -2
- package/assets/init/root/.agents/rules/api-budget.md +187 -8
- package/assets/init/root/.agents/rules/document-schema.md +17 -0
- package/assets/init/root/.agents/rules/documentation-clarity.md +163 -34
- package/assets/init/root/.agents/rules/graph-exploration.md +150 -0
- package/assets/init/root/.agents/rules/grilling.md +100 -43
- package/assets/init/root/.agents/rules/minimal-implementation.md +3 -3
- package/assets/init/root/.agents/rules/reminders.json +27 -18
- package/assets/init/root/.agents/rules/session-feedback.md +131 -0
- package/assets/init/root/.agents/rules/temporary-files.md +33 -0
- package/assets/init/root/.agents/rules/untrusted-content.md +2 -2
- package/assets/init/root/.agents/rules/user-questions.md +51 -40
- package/assets/init/root/.github/workflows/qfai-docs.yml +3 -3
- package/assets/init/root/.github/workflows/qfai-tests.yml +88 -35
- package/assets/init/root/.github/workflows/qfai-validate.yml +2 -2
- package/assets/init/root/AGENTS.md +24 -22
- package/assets/sandbox-templates/default-deny.yaml +9 -3
- package/assets/schemas/workflow/extraction.schema.json +89 -5
- package/assets/scripts/check-mdschema.mjs +77 -8
- package/assets/uix-rev/comparison-review.md +1 -1
- package/assets/uix-rev/contracts-review.md +1 -2
- package/dist/cli/index.cjs +9444 -10071
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.mjs +9421 -10041
- package/dist/cli/index.mjs.map +1 -1
- package/dist/graph/cli.cjs +1568 -0
- package/dist/graph/cli.cjs.map +1 -0
- package/dist/graph/cli.d.cts +9 -0
- package/dist/graph/cli.d.ts +9 -0
- package/dist/graph/cli.mjs +1541 -0
- package/dist/graph/cli.mjs.map +1 -0
- package/dist/graph/hook.cjs +817 -0
- package/dist/graph/hook.cjs.map +1 -0
- package/dist/graph/hook.d.cts +9 -0
- package/dist/graph/hook.d.ts +9 -0
- package/dist/graph/hook.mjs +792 -0
- package/dist/graph/hook.mjs.map +1 -0
- package/dist/index.cjs +7634 -8517
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +146 -658
- package/dist/index.d.ts +146 -658
- package/dist/index.mjs +7462 -8318
- package/dist/index.mjs.map +1 -1
- package/dist/process-C21nTvkT.d.cts +12 -0
- package/dist/process-C21nTvkT.d.ts +12 -0
- package/package.json +4 -6
- package/assets/init/root/CLAUDE.md +0 -46
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
{
|
|
7
7
|
"type": "command",
|
|
8
8
|
"statusMessage": "QFAI structured-question reminder",
|
|
9
|
-
"command": "node -e \"try{const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){const
|
|
9
|
+
"command": "node -e \"try{const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let j={};try{j=JSON.parse(f.readFileSync(0,'utf8'))||{}}catch{}let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}const e=JSON.parse(f.readFileSync(r,'utf8'))[process.argv[1]];if(e===undefined){}else{const {briefContext,...m}=e;if(n>1&&typeof briefContext==='string')m.hookSpecificOutput.additionalContext=briefContext;console.log(JSON.stringify(m))}}}catch{}\" structured-question",
|
|
10
10
|
"timeout": 10
|
|
11
11
|
}
|
|
12
12
|
]
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
{
|
|
17
17
|
"type": "command",
|
|
18
18
|
"statusMessage": "QFAI free-text entry reminder",
|
|
19
|
-
"command": "node -e \"try{const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){const
|
|
19
|
+
"command": "node -e \"try{const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let j={};try{j=JSON.parse(f.readFileSync(0,'utf8'))||{}}catch{}let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}const e=JSON.parse(f.readFileSync(r,'utf8'))[process.argv[1]];if(e===undefined){}else{const {briefContext,...m}=e;if(n>1&&typeof briefContext==='string')m.hookSpecificOutput.additionalContext=briefContext;console.log(JSON.stringify(m))}}}catch{}\" free-text-entry",
|
|
20
20
|
"timeout": 10
|
|
21
21
|
}
|
|
22
22
|
]
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
{
|
|
51
51
|
"type": "command",
|
|
52
52
|
"statusMessage": "QFAI grilling reminder: design artifact",
|
|
53
|
-
"command": "node -e \"try{const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let j={};try{j=JSON.parse(f.readFileSync(0,'utf8'))}catch{}let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}
|
|
53
|
+
"command": "node -e \"try{const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let j={};try{j=JSON.parse(f.readFileSync(0,'utf8'))||{}}catch{}let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}const e=JSON.parse(f.readFileSync(r,'utf8'))[process.argv[1]];if(e===undefined){}else{const {briefContext,...m}=e;if(n>1&&typeof briefContext==='string')m.hookSpecificOutput.additionalContext=briefContext;console.log(JSON.stringify(m))}}}catch{}\" grilling-design-artifact",
|
|
54
54
|
"timeout": 10
|
|
55
55
|
}
|
|
56
56
|
]
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
{
|
|
62
62
|
"type": "command",
|
|
63
63
|
"statusMessage": "QFAI grilling reminder: delegation",
|
|
64
|
-
"command": "node -e \"try{const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let j={};try{j=JSON.parse(f.readFileSync(0,'utf8'))}catch{}let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}
|
|
64
|
+
"command": "node -e \"try{const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let j={};try{j=JSON.parse(f.readFileSync(0,'utf8'))||{}}catch{}let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}const e=JSON.parse(f.readFileSync(r,'utf8'))[process.argv[1]];if(e===undefined){}else{const {briefContext,...m}=e;if(n>1&&typeof briefContext==='string')m.hookSpecificOutput.additionalContext=briefContext;console.log(JSON.stringify(m))}}}catch{}\" grilling-delegation",
|
|
65
65
|
"timeout": 10
|
|
66
66
|
}
|
|
67
67
|
]
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
{
|
|
73
73
|
"type": "command",
|
|
74
74
|
"statusMessage": "QFAI api-budget reminder",
|
|
75
|
-
"command": "node -e \"try{const j=JSON.parse(require('fs').readFileSync(0,'utf8')),i=j.tool_input.command;if(typeof i==='string'&&/[^\\w.-]gh[^\\w.-]|api\\.github\\.com/.test(' '+i+' ')){const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}
|
|
75
|
+
"command": "node -e \"try{const j=JSON.parse(require('fs').readFileSync(0,'utf8')),i=j.tool_input.command;if(typeof i==='string'&&/[^\\w.-]gh[^\\w.-]|api\\.github\\.com/.test(' '+i+' ')){const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}const e=JSON.parse(f.readFileSync(r,'utf8'))[process.argv[1]];if(e===undefined){}else{const {briefContext,...m}=e;if(n>1&&typeof briefContext==='string')m.hookSpecificOutput.additionalContext=briefContext;console.log(JSON.stringify(m))}}}}catch{}\" api-budget",
|
|
76
76
|
"timeout": 10
|
|
77
77
|
}
|
|
78
78
|
]
|
|
@@ -85,13 +85,13 @@
|
|
|
85
85
|
{
|
|
86
86
|
"type": "command",
|
|
87
87
|
"statusMessage": "QFAI documentation-clarity reminder",
|
|
88
|
-
"command": "node -e \"try{const j=JSON.parse(require('fs').readFileSync(0,'utf8')),i=j.tool_input.command;if(typeof i==='string'&&/^\\*\\*\\* Add File: .*\\.md\\r?\\n/m.test(i)){const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}
|
|
88
|
+
"command": "node -e \"try{const j=JSON.parse(require('fs').readFileSync(0,'utf8')),i=j.tool_input.command;if(typeof i==='string'&&/^\\*\\*\\* Add File: .*\\.md\\r?\\n/m.test(i)){const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}const e=JSON.parse(f.readFileSync(r,'utf8'))[process.argv[1]];if(e===undefined){}else{const {briefContext,...m}=e;if(n>1&&typeof briefContext==='string')m.hookSpecificOutput.additionalContext=briefContext;console.log(JSON.stringify(m))}}}}catch{}\" documentation-clarity-after-write",
|
|
89
89
|
"timeout": 10
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
"type": "command",
|
|
93
93
|
"statusMessage": "QFAI documentation-clarity reminder",
|
|
94
|
-
"command": "node -e \"try{const j=JSON.parse(require('fs').readFileSync(0,'utf8')),i=j.tool_input.command;if(typeof i==='string'&&/^\\*\\*\\* Update File: .*\\.md\\r?\\n/m.test(i)){const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}
|
|
94
|
+
"command": "node -e \"try{const j=JSON.parse(require('fs').readFileSync(0,'utf8')),i=j.tool_input.command;if(typeof i==='string'&&/^\\*\\*\\* Update File: .*\\.md\\r?\\n/m.test(i)){const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}const e=JSON.parse(f.readFileSync(r,'utf8'))[process.argv[1]];if(e===undefined){}else{const {briefContext,...m}=e;if(n>1&&typeof briefContext==='string')m.hookSpecificOutput.additionalContext=briefContext;console.log(JSON.stringify(m))}}}}catch{}\" documentation-clarity-after-edit",
|
|
95
95
|
"timeout": 10
|
|
96
96
|
}
|
|
97
97
|
]
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
{
|
|
103
103
|
"type": "command",
|
|
104
104
|
"statusMessage": "QFAI minimal-implementation reminder",
|
|
105
|
-
"command": "node -e \"try{const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let go=true,j={};try{j=JSON.parse(f.readFileSync(0,'utf8'))}catch{}try{const R=p.dirname(p.dirname(p.dirname(r))),n=(x=>{const s=x.split(p.sep),b=s.pop();return p.isAbsolute(x)||s[0]==='..'||s.some(y=>['tmp','test','tests','__tests__','node_modules','.qfai','.agents'].includes(y))||b[0]==='.'||/\\.(test|spec)\\./.test(b)||['.md','.mdx','.markdown','.txt','.rst','.yml','.yaml','.json','.jsonc','.json5','.toml','.ini','.csv','.tsv','.lock','.svg','.png','.jpg','.jpeg','.gif'].includes(p.extname(b).toLowerCase())}),a=[...j.tool_input.command.matchAll(/^\\*\\*\\* (?:(?:Add|Update|Delete) File|Move to): (.+)/gm)].map(m=>p.relative(R,p.resolve(process.cwd(),m[1].trim())));if(a.length>0&&a.every(n))go=false}catch{}if(go){let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}
|
|
105
|
+
"command": "node -e \"try{const f=require('fs'),p=require('path');let d=process.cwd(),r;for(;;){const c=p.join(d,'.agents','rules','reminders.json');if(r===undefined&&f.existsSync(c))r=c;if(f.existsSync(p.join(d,'.git')))break;const u=p.dirname(d);if(u===d){r=undefined;break}d=u}if(r){let go=true,j={};try{j=JSON.parse(f.readFileSync(0,'utf8'))}catch{}try{const R=p.dirname(p.dirname(p.dirname(r))),n=(x=>{const s=x.split(p.sep),b=s.pop();return p.isAbsolute(x)||s[0]==='..'||s.some(y=>['tmp','test','tests','__tests__','node_modules','.qfai','.agents'].includes(y))||b[0]==='.'||/\\.(test|spec)\\./.test(b)||['.md','.mdx','.markdown','.txt','.rst','.yml','.yaml','.json','.jsonc','.json5','.toml','.ini','.csv','.tsv','.lock','.svg','.png','.jpg','.jpeg','.gif'].includes(p.extname(b).toLowerCase())}),a=[...j.tool_input.command.matchAll(/^\\*\\*\\* (?:(?:Add|Update|Delete) File|Move to): (.+)/gm)].map(m=>p.relative(R,p.resolve(process.cwd(),m[1].trim())));if(a.length>0&&a.every(n))go=false}catch{}if(go){let n=1;if(typeof j.session_id==='string'){try{const t=p.join(require('os').tmpdir(),['qfai-reminder',j.session_id,j.agent_id||'main',process.argv[1]].join('-').replace(/[^\\w.-]/g,'_'));f.appendFileSync(t,'.');n=f.statSync(t).size}catch{}}const e=JSON.parse(f.readFileSync(r,'utf8'))[process.argv[1]];if(e===undefined){}else{const {briefContext,...m}=e;if(n>1&&typeof briefContext==='string')m.hookSpecificOutput.additionalContext=briefContext;console.log(JSON.stringify(m))}}}}catch{}\" minimal-implementation",
|
|
106
106
|
"timeout": 10
|
|
107
107
|
}
|
|
108
108
|
]
|
|
@@ -45,6 +45,11 @@ specialization_tags:
|
|
|
45
45
|
a deliberate shortcut with its ceiling and the condition that lifts it.
|
|
46
46
|
- Apply `.qfai/assistant/rule/ui-procurement.md`: install a component before writing one, and for anything the prototype does not show, take the adopted system's default rather than inventing one.
|
|
47
47
|
- Apply `.agents/rules/interface-clarity.md`: label a control in the user's words, never the parameter's. The label stays; the sentence explaining it goes.
|
|
48
|
+
- Read each screen's `supplements` and `structure` in its UI contract before adding any text.
|
|
49
|
+
Show the title, the group headings, the labels and the declared supplements, and no other text.
|
|
50
|
+
A text the screen needs that the contract lacks, or a declared one the screen should not show,
|
|
51
|
+
is a change to the contract and goes back to `/qfai-sdd`.
|
|
52
|
+
Element ids stay the same when only wording changes.
|
|
48
53
|
|
|
49
54
|
## Inputs you must read
|
|
50
55
|
|
|
@@ -51,6 +51,10 @@ specialization_tags:
|
|
|
51
51
|
- Apply `.agents/rules/minimal-implementation.md`: the first rung is this stage's — whether the thing needs to exist. After a spec row is agreed, that question is a Change Request.
|
|
52
52
|
- Apply `.qfai/assistant/rule/ui-procurement.md`: the theme is adopted from a published one, and a screen's composition comes from a catalogue before it is drawn.
|
|
53
53
|
- Apply `.agents/rules/interface-clarity.md`: a screen that needs explaining is a screen that needs redesigning. Hint text only where a need was demonstrated and the control was improved first.
|
|
54
|
+
- Record the decisions that rule leads to in the screen contract: the `supplements` a screen shows,
|
|
55
|
+
each with the reason it is needed, and the `structure` of any heading beyond the title
|
|
56
|
+
(`.qfai/assistant/skill/qfai-sdd/references/ui-contract-guide.md`).
|
|
57
|
+
Fix the control before adding a supplement for it.
|
|
54
58
|
|
|
55
59
|
## Inputs you must read
|
|
56
60
|
|
|
@@ -61,6 +61,13 @@ specialization_tags:
|
|
|
61
61
|
- Require more work only on what `.qfai/assistant/rule/shared-skill-delegation-baseline.md#what-a-reviewer-may-demand-more-of-must` admits, and report any other gap as advisory.
|
|
62
62
|
- Apply `.qfai/assistant/rule/ui-procurement.md`: report a region that was drawn where a catalogue had it, and name the item that would have served.
|
|
63
63
|
- Apply `.agents/rules/interface-clarity.md`: report copy that explains the interface as a finding against the control under it, and name the control to fix.
|
|
64
|
+
- Compare the rendered text with each screen's `supplements` and `structure` in its UI contract.
|
|
65
|
+
A text no contract key declares is excess; a declared supplement that is not shown is an unmet need.
|
|
66
|
+
Name the screen, the task or state, the duplicated meaning or unmet need, and the text to remove or the control or structure to repair.
|
|
67
|
+
Apply `.qfai/assistant/skill/qfai-sdd/references/design-anti-patterns.md#copy-that-adds-no-meaning`.
|
|
68
|
+
Never cut a condition, cost, destination, result, recovery step, consequence, label, accessible name, role or state,
|
|
69
|
+
and never move one into a tooltip or placeholder.
|
|
70
|
+
Word counts are observations, never a verdict.
|
|
64
71
|
|
|
65
72
|
## Inputs you must read
|
|
66
73
|
|
|
@@ -64,6 +64,14 @@ specialization_tags:
|
|
|
64
64
|
`/qfai-prototyping` at the validate lane, under `QFAI-AUD-001`. The shipped
|
|
65
65
|
`ui-contract.sample.yaml` carries filled entries; replace them with the
|
|
66
66
|
screen's own rather than emptying the list.
|
|
67
|
+
- For UI-bearing surfaces: every screen also declares `supplements` (`[]` when it
|
|
68
|
+
shows no text beyond its title, group headings and labels), and `structure` when
|
|
69
|
+
it shows a heading beyond its title. Check each proposed text element against the
|
|
70
|
+
screen's tasks and the information the user needs there, and write the ones that
|
|
71
|
+
stay into the contract with the reason. A text that only repeats a heading, an
|
|
72
|
+
action or a condition the user already has is left out. Discussion sidecars
|
|
73
|
+
inform these keys; they do not replace them. See
|
|
74
|
+
`.qfai/assistant/skill/qfai-sdd/references/ui-contract-guide.md`.
|
|
67
75
|
|
|
68
76
|
## Stop conditions
|
|
69
77
|
|
|
@@ -45,14 +45,24 @@ Applies to every text an agent produces: pull request and issue titles and
|
|
|
45
45
|
bodies, source-code comments, and Markdown files — inside the current change
|
|
46
46
|
only, never beyond its diff.
|
|
47
47
|
|
|
48
|
-
-
|
|
49
|
-
project understands, anywhere in source code or Markdown files. Those
|
|
50
|
-
in the pull request, the commit message and the changelog.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
-
|
|
48
|
+
- Keep out issue or pull-request numbers, ticket identifiers and names only
|
|
49
|
+
this project understands, anywhere in source code or Markdown files. Those
|
|
50
|
+
belong in the pull request, the commit message and the changelog.
|
|
51
|
+
Pull request and issue bodies may contain numbers and links.
|
|
52
|
+
- Keep out any account of how the work went. State the current behaviour and
|
|
53
|
+
why it is that way; the history is already in the git log and the pull
|
|
54
|
+
request.
|
|
55
|
+
- Settle the message, then open with the conclusion: the title or opening says
|
|
56
|
+
the result, with no preamble.
|
|
57
|
+
- Cut what is self-evident, repeated or wordy, and announcements, recaps and
|
|
58
|
+
empty intensifiers.
|
|
59
|
+
- Use ordinary vocabulary, one claim per sentence, and name who acts; software
|
|
60
|
+
does not know or decide.
|
|
61
|
+
- Mark what is unverified, and say what a claim rests on.
|
|
62
|
+
- Use bullet lists and tables for parallel items, with lines short enough to
|
|
63
|
+
scan.
|
|
64
|
+
- Open a report with the outcome, and separate what was checked from what was
|
|
65
|
+
not.
|
|
56
66
|
- Re-read every changed line afterwards. Text that reads as a literal
|
|
57
67
|
translation is a defect in any language pair — rewrite it the way someone
|
|
58
68
|
writing natively in that language would.
|
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
This document defines **non‑negotiable operating rules** for QFAI agents and subagents.
|
|
4
4
|
It is inspired by proven “constitution / articles / guardrails” patterns in existing SDD toolchains, but adapted to QFAI’s minimal workflow.
|
|
5
5
|
|
|
6
|
+
Actual user instructions take priority over repository guidelines. Recorded
|
|
7
|
+
applicable user authority is defined in
|
|
8
|
+
`.agents/rules/grilling.md#explicit-delegation-for-a-discussion`: an explicit
|
|
9
|
+
in-scope delegation may authorize reversible requested judgment without a
|
|
10
|
+
fictional individual approval answer. It supplies no unknown fact or authority
|
|
11
|
+
for an operation outside its scope.
|
|
12
|
+
|
|
6
13
|
Inside an `npx qfai workflow` run, what authorizes the run's work and the one target a work order binds its stage to are stated in `.qfai/assistant/rule/shared-skill-operating-baseline.md#what-authorizes-a-runs-work`. They add to these articles and except none.
|
|
7
14
|
|
|
8
15
|
---
|
|
@@ -260,7 +267,7 @@ sanctioned move, and neither is asking a sixth clarification anyway.
|
|
|
260
267
|
**A grilling session survives exhaustion too**, and for the same reason: its
|
|
261
268
|
questions never spent budget, so there is none left to run out of. A session
|
|
262
269
|
already under way continues to its own end condition, a delegated one still
|
|
263
|
-
|
|
270
|
+
requiring actual user authority for critical decisions, and a stage reached after
|
|
264
271
|
exhaustion still opens one where its work calls for it. Treating a spent budget
|
|
265
272
|
as the end of a session would put the design decisions back where this article
|
|
266
273
|
found them — settled quietly, on an assumption nobody was asked about.
|
|
@@ -322,16 +329,18 @@ If confidence is low, inspect the repository further.
|
|
|
322
329
|
|
|
323
330
|
**Stop on detection.** Where a contradiction in the spec, an unconsidered case,
|
|
324
331
|
or a technical obstacle surfaces mid-run, stop rather than deciding alone.
|
|
325
|
-
Settle it between the agents
|
|
326
|
-
|
|
327
|
-
|
|
332
|
+
Settle it between the agents. A critical decision needs an actual user answer
|
|
333
|
+
or recorded applicable authorization under
|
|
334
|
+
`.agents/rules/grilling.md#explicit-delegation-for-a-discussion`; without it,
|
|
335
|
+
ask when permitted or register it open. A contradiction with the spec is
|
|
336
|
+
critical. Nothing is recorded beyond the stage's final report.
|
|
328
337
|
|
|
329
338
|
**Only one outcome is the Drift Protocol's.**
|
|
330
339
|
|
|
331
|
-
| The stop concludes | What follows
|
|
332
|
-
| ---------------------------------------------------------------------------------------- |
|
|
333
|
-
| Settled input must change | `.qfai/assistant/rule/drift-protocol.md`: stop
|
|
334
|
-
| The obstacle is this run's to solve — an unavailable dependency, an approach that failed | The run solves it. Nothing upstream changes, so there is nothing to approve
|
|
340
|
+
| The stop concludes | What follows |
|
|
341
|
+
| ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
342
|
+
| Settled input must change | `.qfai/assistant/rule/drift-protocol.md`: stop dependent work, raise the Change Request, record actual applicable user authority before changing it |
|
|
343
|
+
| The obstacle is this run's to solve — an unavailable dependency, an approach that failed | The run solves it. Nothing upstream changes, so there is nothing to approve |
|
|
335
344
|
|
|
336
345
|
Stopping does not change settled input and is not a second way to. What it
|
|
337
346
|
contributes to a Change Request is what that protocol asks of the class: for
|
|
@@ -366,7 +375,9 @@ rule master names.
|
|
|
366
375
|
Rules:
|
|
367
376
|
|
|
368
377
|
0. **A no-question mode is read first.** Where rule 4 applies, no question is put
|
|
369
|
-
|
|
378
|
+
to the user, so there is nothing whose availability rules 1 to 3 could judge.
|
|
379
|
+
Actual qualifying explicit delegation may still permit agent-to-agent rounds
|
|
380
|
+
under the master; no-question mode alone does not. Read
|
|
370
381
|
the other way round, a mode that withholds the tool would make it unavailable,
|
|
371
382
|
route the question to rule 3's plain-text fallback, and hand the agent a rule
|
|
372
383
|
that says to ask beside one that says not to.
|
|
@@ -406,12 +417,14 @@ Rules:
|
|
|
406
417
|
this rule is activated by the `--auto` flag alone.
|
|
407
418
|
6. **A grilling session does not reach the user under `--auto`.** Its questions
|
|
408
419
|
are exempt from the Article VI budget, not from rule 4: a no-question mode
|
|
409
|
-
|
|
420
|
+
sends no question to the user, whatever it is for. The session still runs — it
|
|
410
421
|
settles what the repository settles, dispatches sub-agents for the facts, and
|
|
411
|
-
in a delegated session adopts the griller's recommendation for
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
422
|
+
in a delegated session adopts the griller's recommendation for non-critical
|
|
423
|
+
decisions. A critical decision needs an actual user answer or recorded
|
|
424
|
+
applicable authorization; without it the node stays open. It opens every **node**
|
|
425
|
+
left over, including uncovered critical decisions and unavailable user-held
|
|
426
|
+
facts, **as a question in the register the stage reads**, so the
|
|
427
|
+
stage cannot complete over it. Every node, not every
|
|
415
428
|
decision: a fact only the user holds cannot be settled from evidence either,
|
|
416
429
|
and opening the decisions while dropping the facts loses exactly the nodes no
|
|
417
430
|
lookup could have reached. Where a document requires the field to hold
|
|
@@ -419,7 +432,10 @@ Rules:
|
|
|
419
432
|
open question; a labelled value under an open question is not a settled
|
|
420
433
|
decision. What rule 4 does not license is the assumption **alone**, which
|
|
421
434
|
reads as settled to whoever finds it next. A fact declared undefaultable has
|
|
422
|
-
no value to write down at all: the run stops and names it.
|
|
435
|
+
no value to write down at all: the run stops and names it. A qualifying
|
|
436
|
+
explicitly delegated session ends `adopted` only with the master's empty-tree,
|
|
437
|
+
actual-input and authority conditions met. No-question mode alone cannot
|
|
438
|
+
close a node or authorize a reserved decision.
|
|
423
439
|
|
|
424
440
|
This article survives context compaction because `.qfai/assistant/rule/constitution.md` is a P1 reload target.
|
|
425
441
|
|
|
@@ -11,7 +11,22 @@ open-questions.md, and every file under paths.contractsDir. Production code and
|
|
|
11
11
|
obligation may change in a later task, but the change must preserve or deliberately reapprove that obligation.
|
|
12
12
|
QFAI-owned files under .qfai/assistant/rule/ are updated through the package, then synchronized by init.
|
|
13
13
|
|
|
14
|
-
A new change-request row in decisions.md is permitted without an earlier change request.
|
|
14
|
+
A new change-request row in decisions.md is permitted without an earlier change request.
|
|
15
|
+
Existing rows are append-only records: a prior row may change its Status cell,
|
|
16
|
+
while its ID, Content, and Approach stay fixed. The sole ID-change exception is
|
|
17
|
+
explicit local renumbering of a unique branch-added decision absent from the
|
|
18
|
+
unique common ancestor of HEAD and a required local base. That operation changes
|
|
19
|
+
only its ID and provably branch-added exact references. Inherited row cells and
|
|
20
|
+
references stay fixed. A changed obligation needs a new row, even when an older
|
|
21
|
+
row discusses the same topic.
|
|
22
|
+
|
|
23
|
+
The sole Approach-change exception is the published decision prefix recovery
|
|
24
|
+
below. It preserves the target's ID, Content, Status and complete original
|
|
25
|
+
Approach suffix. It excludes inherited rows and open-question rows.
|
|
26
|
+
|
|
27
|
+
The sole row-removal exception is the merge-added identical decision copy
|
|
28
|
+
recovery below. It removes only proven raw-identical surplus copies of a
|
|
29
|
+
decision and keeps one original. It excludes open-question rows.
|
|
15
30
|
|
|
16
31
|
## Allowed exceptions (minimal whitelist)
|
|
17
32
|
|
|
@@ -25,6 +40,105 @@ diff changes no file under `01_policy/`, `02_business-flow/` or
|
|
|
25
40
|
paths.contractsDir appends no `Change request:` row. A row naming a story file
|
|
26
41
|
the bugfix did not touch would state an upstream change that did not happen.
|
|
27
42
|
|
|
43
|
+
## Published decision prefix recovery
|
|
44
|
+
|
|
45
|
+
The SDD owner may prepend only an approved Evidence/Grounds prefix to a
|
|
46
|
+
published malformed decision added by the branch. Approval of this protocol
|
|
47
|
+
does not authorize any target. First obtain a separate new in-force recovery
|
|
48
|
+
change request naming the target and its repository-relative file.
|
|
49
|
+
|
|
50
|
+
1. Fix the explicit base commit and its unique common ancestor with current
|
|
51
|
+
HEAD. The target ID must be absent from both. The documented published
|
|
52
|
+
source commit must be an ancestor of current HEAD and expose the unique
|
|
53
|
+
original row. Inherited records and open-question rows are excluded.
|
|
54
|
+
2. Read the original raw cell bytes. The row must be single-line valid UTF-8,
|
|
55
|
+
with exactly one ASCII padding space at each Approach delimiter and no
|
|
56
|
+
additional boundary whitespace. Hash the stored Approach bytes with
|
|
57
|
+
SHA-256, excluding only the delimiter pipes and those two padding spaces.
|
|
58
|
+
Do not decode escapes, trim text or normalize it. Ambiguous boundaries,
|
|
59
|
+
additional padding or invalid UTF-8 stop recovery.
|
|
60
|
+
3. Confirm the original Residual risk and Rollback items already satisfy the
|
|
61
|
+
required ordered, nonempty form. The new Approach must be exactly
|
|
62
|
+
`- Evidence: <actual file references> - Grounds: `, including its trailing
|
|
63
|
+
space, followed by the complete original Approach as a byte-identical
|
|
64
|
+
suffix. Preserve the original wording, order, facts, authority and scope.
|
|
65
|
+
The prefixed row must satisfy the existing form checks.
|
|
66
|
+
4. Record the target ID, published source commit, fixed base and common
|
|
67
|
+
ancestor, old and new Approach digests, exact prefix, actual file evidence,
|
|
68
|
+
approval authority, recovery reason, residual risk and rollback in the new
|
|
69
|
+
request. The old digest must match the published source Approach; the new
|
|
70
|
+
digest must match the exact prefix plus that source value. Record actual
|
|
71
|
+
authority; do not invent a user answer or approval.
|
|
72
|
+
5. Immediately before writing, recheck the unique current target, its
|
|
73
|
+
byte-identical ID, Content and Status, and its recorded old Approach digest.
|
|
74
|
+
Unknown or unavailable provenance, inherited or duplicate targets, stale
|
|
75
|
+
data or a change beyond the approved prefix stops recovery before writing.
|
|
76
|
+
Apply only that prefix. Keep every other row byte-identical and run the existing
|
|
77
|
+
validation without an exemption.
|
|
78
|
+
6. Rollback removes only the recorded prefix when the current new Approach
|
|
79
|
+
digest still matches. Otherwise preserve the current row and stop. Removal
|
|
80
|
+
restores the original Approach and its validation failure. Do not reset,
|
|
81
|
+
amend or force push.
|
|
82
|
+
|
|
83
|
+
Status changes, supersession and a diagnostic's rewrite suggestion supply no
|
|
84
|
+
recovery authority and clear no form error. Inherited malformed records need a
|
|
85
|
+
separate owning change request; this operation cannot repair them. These are
|
|
86
|
+
owner instructions, not an automatic recovery command or a concurrency guarantee.
|
|
87
|
+
|
|
88
|
+
## Merge-added identical decision copy recovery
|
|
89
|
+
|
|
90
|
+
The SDD owner may manually remove only raw-identical surplus copies of a
|
|
91
|
+
decision row that an exact two-parent bad merge introduced. Approval of this
|
|
92
|
+
protocol authorizes no target. First append a separate new in-force change
|
|
93
|
+
request that names the exact `decisions.md` path and the decision ID.
|
|
94
|
+
|
|
95
|
+
1. Name the bad merge. It must be an available ancestor of current HEAD with
|
|
96
|
+
exactly two parents, and it must expose the introduced surplus. Name both
|
|
97
|
+
parents and their unique common ancestor. Each of the three must hold exactly
|
|
98
|
+
one byte-identical original of the row. Fix the explicit base and its unique
|
|
99
|
+
comparison ancestor; both must hold one original and no surplus selected for
|
|
100
|
+
removal. A missing or non-ancestor merge, a third parent, a non-unique
|
|
101
|
+
ancestor or a source that does not hold exactly one original stops recovery.
|
|
102
|
+
2. Read the complete stored UTF-8 raw row of every selected current occurrence:
|
|
103
|
+
all four cells, delimiters, padding and line ending. Hash each with SHA-256,
|
|
104
|
+
including the line ending. Do not trim, decode escapes or normalize endings.
|
|
105
|
+
Nonidentical cells, padding or endings are a different collision and are
|
|
106
|
+
outside this recovery.
|
|
107
|
+
3. Record in the request the path, the ID, the bad merge, both parents, the
|
|
108
|
+
ancestor, the base and its comparison ancestor, the location of each
|
|
109
|
+
occurrence, the raw hash, the retain/remove mapping, the actual authority,
|
|
110
|
+
the residual risk and the rollback. Record actual authority; invent no
|
|
111
|
+
answer. The request fixes input lineage only.
|
|
112
|
+
4. After the request is appended, have the evidence for the write reviewed
|
|
113
|
+
independently and adopted. It fixes the actual write HEAD, base and
|
|
114
|
+
comparison ancestor, the complete preimage and replacement bytes and hashes,
|
|
115
|
+
the mapping and the current authority. The request does not name its own
|
|
116
|
+
commit, so the actual write revision stays distinct from the lineage above.
|
|
117
|
+
This adds no receipt grammar and no validator input.
|
|
118
|
+
5. Immediately before writing, recheck the refs, their availability, the path,
|
|
119
|
+
the authority, the occurrence count, the mapping and the bytes. Stale,
|
|
120
|
+
missing, ambiguous, conflicting or changed proof stops before writing.
|
|
121
|
+
Changed observations need refreshed reviewed evidence. A changed target or
|
|
122
|
+
operation needs a new request; do not rewrite the cells of an earlier one.
|
|
123
|
+
6. Remove only the mapped surplus occurrences. Keep one complete original, every
|
|
124
|
+
distinct decision and reference, every unrelated current byte and the Git
|
|
125
|
+
history. Do not change a Status, rewrite a reference or reorder other
|
|
126
|
+
history. Open-question rows, nonidentical collisions, ordinary duplicate
|
|
127
|
+
cleanup and surplus that the base or its comparison ancestor already holds
|
|
128
|
+
are excluded.
|
|
129
|
+
7. Rollback restores the recorded complete preimage only while the current file
|
|
130
|
+
is byte-identical to its owned replacement. Otherwise keep the current bytes,
|
|
131
|
+
stop and name the unrestored path. Restoring brings back the duplicate
|
|
132
|
+
failure. Do not reset, amend or force push.
|
|
133
|
+
|
|
134
|
+
The existing duplicate check, positional drift, consumed-DONE authorization and
|
|
135
|
+
valid Status-only rules keep applying without an exemption. Other drift that
|
|
136
|
+
the file already has stays diagnosed; it is not a prerequisite for this
|
|
137
|
+
correction. An actual required stage gate still stops dependent work. Correcting
|
|
138
|
+
the copies is not a whole-target PASS, and the request stays at WIP while a named
|
|
139
|
+
action or required check is unfinished. These are owner instructions, not a
|
|
140
|
+
command, an executor or a concurrency, atomicity or power-loss guarantee.
|
|
141
|
+
|
|
28
142
|
## Drift classes
|
|
29
143
|
|
|
30
144
|
Intent drift means an approved obligation should change. Record the current obligation, the proposed behavior, realistic
|
|
@@ -112,6 +226,9 @@ copy of a locked file before deciding its lock is wrong.
|
|
|
112
226
|
## Non-negotiable constraints
|
|
113
227
|
|
|
114
228
|
- Downstream stages do not patch protected upstream artifacts before an in-force Change request: decision row authorizes the path. The drift profile compares the branch against baseBranch and reports QFAI-DRIFT-001 for an unapproved protected change. The SDD owner may create the request row itself without a prior row.
|
|
115
|
-
-
|
|
229
|
+
QFAI-DRIFT-003 is a warning that nothing was compared, because baseBranch does not resolve.
|
|
230
|
+
QFAI-DRIFT-004 is a warning that an uncommitted edit to a protected file is not compared:
|
|
231
|
+
record the Change request row before you commit the change.
|
|
232
|
+
- Existing decisions.md and open-questions.md rows retain their ID, Content, and Approach, except for the explicit branch-added decision renumbering, published decision prefix recovery and merge-added identical decision copy recovery above. Inherited rows retain those cells without exception. A former row may change Status; new content is appended as a new row.
|
|
116
233
|
- Vendored assistant rules are changed in the package and synchronized into projects by `npx qfai init --force`, which overwrites a local edit. A project rule lives in a `*.local.md` overlay beside the vendored one.
|
|
117
234
|
- When approval is unavailable, keep the affected items stopped and report the decision needed. Continue unrelated work.
|
|
@@ -14,11 +14,13 @@ A `SKILL.md` states the contract and points at the file that carries the detail.
|
|
|
14
14
|
- **One topic per file.** Do not replace an oversized `SKILL.md` with an oversized `references/everything.md`; that is the same problem one directory down. Split by topic and keep each file readable on its own — a reader who followed one pointer should not have to scan past three unrelated subjects to reach the one they came for.
|
|
15
15
|
- **Every pointer resolves.** A line that moves detail out must name the file (and anchor, when the file covers more than one topic) so the reader is never left guessing where the rule went.
|
|
16
16
|
|
|
17
|
-
A hard line ceiling backs this up: **800 lines per assistant asset file**, for every `.qfai/assistant/**/*.{md,yml,yaml}` file, counted as `content.split(/\r?\n/).length` — blank lines included.
|
|
18
|
-
|
|
17
|
+
A hard line ceiling backs this up: **500 lines per Markdown assistant asset file** and **800 lines per YAML assistant asset file**, for every `.qfai/assistant/**/*.{md,yml,yaml}` file, counted as `content.split(/\r?\n/).length` — blank lines included.
|
|
18
|
+
`npx qfai doctor` measures it and reports every file over its ceiling as `assets.lineBudget`.
|
|
19
|
+
The ceiling is a backstop, not the rule: a file approaching it is a signal to move a section out, not to raise the number.
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
The Markdown ceiling is the limit an agent can follow in one file: it follows fewer instructions as its context grows, and follows those in the middle of a long file worst. A Markdown file has a `references/` home to move detail into. A YAML asset is parsed as data and cannot be split that way (see below), which is why its ceiling is higher.
|
|
22
|
+
|
|
23
|
+
A body at its ceiling stops shedding topics and starts packing them into longer lines, and a line count cannot see that. The width ceiling below is what catches it.
|
|
22
24
|
|
|
23
25
|
**A width ceiling makes the count honest: 400 characters per line.** A count of lines bounds reading cost only while a line is a roughly constant unit of reading, and packing broke that — one line in the shipped tree ran 9,104 characters against a median of 118, and cost the budget one unit. The two are read together, because each permits what the other refuses: width alone allows a thin
|
|
24
26
|
file of a thousand short lines, and the count alone allows a packed one.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Codex Delegation
|
|
2
|
+
|
|
3
|
+
Read before the first `spawn_agent` call when the host is Codex.
|
|
4
|
+
|
|
5
|
+
## Codex delegation notes
|
|
6
|
+
|
|
7
|
+
A sub-agent should cost the orchestrator one brief and one final answer. A call
|
|
8
|
+
that only checks progress, such as a short wait, a sleep or an agent listing,
|
|
9
|
+
is one more model call, so the orchestrator makes none.
|
|
10
|
+
|
|
11
|
+
- **Self-contained brief.** Call `spawn_agent` with `fork_turns: "none"` and a
|
|
12
|
+
`message` that holds everything the sub-agent needs: the task, the files to
|
|
13
|
+
read, the paths it may write, the checks to run and the shape of its answer.
|
|
14
|
+
`fork_turns` defaults to `"all"`, which copies the whole parent thread into
|
|
15
|
+
the sub-agent. Where the tool takes `fork_context` instead, leave it out or
|
|
16
|
+
pass `false`.
|
|
17
|
+
- **One final answer, no interim messages.** The brief tells the sub-agent to
|
|
18
|
+
send no `send_message` updates and to return its result once, as its final
|
|
19
|
+
answer. Where `wait_agent` takes no `targets`, every queued message ends the
|
|
20
|
+
orchestrator's wait early.
|
|
21
|
+
- **Long wait.** With no work of its own left, the orchestrator calls
|
|
22
|
+
`wait_agent` with a `timeout_ms` of minutes within the maximum the tool states,
|
|
23
|
+
such as `600000`, not 10 to 60 seconds. A wait that times out is
|
|
24
|
+
followed by another long wait.
|
|
25
|
+
- **No polling.** Never wait with `sleep`, a loop of short `wait_agent` calls or
|
|
26
|
+
repeated `list_agents` calls. `followup_task` gives a sub-agent a new task; it
|
|
27
|
+
never asks for progress.
|
|
@@ -6,15 +6,27 @@ Read when a griller's recommendation is used.
|
|
|
6
6
|
|
|
7
7
|
A grilling session puts a recommended answer beside each question (`.agents/rules/grilling.md`). Who settled the decision decides what happens next.
|
|
8
8
|
|
|
9
|
-
| The decision was settled
|
|
10
|
-
|
|
|
11
|
-
| By the user, from the recommendation among the inputs
|
|
12
|
-
| Agent to agent,
|
|
13
|
-
| Agent to agent, critical,
|
|
14
|
-
|
|
15
|
-
**The second row is how a delegated session is meant to end**
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
| The decision was settled | What follows |
|
|
10
|
+
| ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
|
11
|
+
| By the user, from the recommendation among the inputs | The decision is theirs. The griller may review the artifact |
|
|
12
|
+
| Agent to agent, non-critical or with recorded applicable human authority | The decision stands. The griller that recommended it does not review the artifact |
|
|
13
|
+
| Agent to agent, critical, without an actual user answer or recorded applicable authority | The artifact is wrong, and no reviewer can clear it |
|
|
14
|
+
|
|
15
|
+
**The second row is how a delegated session is meant to end**
|
|
16
|
+
(`.agents/rules/grilling.md`), not a finding. The reviewer checks the final
|
|
17
|
+
report and, for a critical decision, the actual
|
|
18
|
+
applicable user authority defined in
|
|
19
|
+
`.agents/rules/grilling.md#explicit-delegation-for-a-discussion`.
|
|
20
|
+
An explicit delegation covering reversible requested judgment is authority,
|
|
21
|
+
not an individual human option answer. The recommending griller remains
|
|
22
|
+
disqualified from reviewing an agent adoption. A reviewer that doubts its merit
|
|
23
|
+
raises an ordinary finding against the artifact under its own remit.
|
|
24
|
+
|
|
25
|
+
**The third row is not a routing problem.** Without an actual answer or
|
|
26
|
+
recorded applicable user authority, a critical decision stays open. A run that
|
|
27
|
+
cannot ask records it as an open question rather than adopting it. Agent
|
|
28
|
+
agreement cannot supply authority, and a different reviewer cannot repair its
|
|
29
|
+
absence. No-question mode alone authorizes no decision.
|
|
18
30
|
The reviewer must return `REVISE` and name the decision: it is reopened and put to the user, or recorded open where no question can be asked.
|
|
19
31
|
|
|
20
32
|
The first row needs a reason, because the intuitive one is wrong. A sub-agent starting with a reset context cannot defer to something it does not remember, so deference is not the risk. **Correlation** is: a fresh instance of the same agent, on the same model, over the same evidence, re-derives the preference that produced the recommendation and finds it good on the merits. Resetting the
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Worker edits and work orders
|
|
2
|
+
|
|
3
|
+
Read when assigning worker write paths or handling a refused edit.
|
|
4
|
+
|
|
5
|
+
## Edit boundary
|
|
6
|
+
|
|
7
|
+
The work order names the checkout assigned to the task by the host, the worker's
|
|
8
|
+
write paths and the permitted edit method. Creating a Git worktree does not
|
|
9
|
+
grant the host's tools permission to edit it. Even an assigned checkout can
|
|
10
|
+
receive a refusal; verify the actual edit result rather than claiming access.
|
|
11
|
+
|
|
12
|
+
If an edit is refused, stop writes to that target. Report the tool, working
|
|
13
|
+
directory, target path and refusal text, omitting secrets. Return the owned
|
|
14
|
+
paths and a reviewable diff that can be prepared within the worker's permitted
|
|
15
|
+
area. Do not bypass the refusal through a shell, script or another tool.
|
|
16
|
+
This does not forbid shell authoring where the host already permits it.
|
|
17
|
+
|
|
18
|
+
The orchestrator checks the diff against the current files in its own permitted
|
|
19
|
+
checkout before applying it. If that edit is refused too, leave the application
|
|
20
|
+
pending and continue only independent work. Follow the existing worktree or
|
|
21
|
+
shared-index mode in `.qfai/assistant/rule/workflow.md#concurrency-stage-independent-mandatory`
|
|
22
|
+
when assigning writers and integrating their paths.
|
|
23
|
+
|
|
24
|
+
## Work order template
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
Task title: <short>
|
|
28
|
+
Role: <sub-agent role>
|
|
29
|
+
Review series: <reviewed artifact> + <reviewer role> + <replacement ordinal> # review work orders only
|
|
30
|
+
Goal: <what to decide/produce>
|
|
31
|
+
Checkout: <absolute checkout assigned to this task by the host>
|
|
32
|
+
Write paths: <exact owned paths, or none for a read-only task>
|
|
33
|
+
Edit method: <host-permitted tool; worktree creation does not grant access>
|
|
34
|
+
If an edit is refused: stop that target; return tool, cwd, target, refusal text, owned paths and a reviewable diff
|
|
35
|
+
Inputs (refs):
|
|
36
|
+
- <file/section>
|
|
37
|
+
- .qfai/assistant/rule/drift-protocol.md#core-rule <!-- the protected set, in front of the agent -->
|
|
38
|
+
Constraints:
|
|
39
|
+
- must: enforce Drift Protocol
|
|
40
|
+
- must: follow applicable test-layer or validation policy
|
|
41
|
+
- must_not: patch upstream artifacts directly; every upstream change requires
|
|
42
|
+
STOP + Change Request + owner rerun per .qfai/assistant/rule/drift-protocol.md
|
|
43
|
+
Output format:
|
|
44
|
+
- <headings / bullet schema>
|
|
45
|
+
Time budget: none | <seconds> # advisory: nothing stops at it. See .qfai/assistant/rule/stage-cost.md
|
|
46
|
+
Elapsed line: end every message with `elapsed <seconds>s / <budget>s`, or `elapsed <seconds>s` when the budget is none
|
|
47
|
+
Acceptance bar: <accept when ...> | <rework when ...> # never `PASS`/`REVISE`: that is the reviewer's vocabulary and the completion gate matches on it, so a doer told to report in it emits a verdict on its own work
|
|
48
|
+
```
|