@soleri/core 9.2.0 → 9.3.1
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/data/flows/build.flow.yaml +8 -9
- package/data/flows/deliver.flow.yaml +9 -10
- package/data/flows/design.flow.yaml +3 -4
- package/data/flows/enhance.flow.yaml +5 -6
- package/data/flows/explore.flow.yaml +3 -4
- package/data/flows/fix.flow.yaml +5 -6
- package/data/flows/plan.flow.yaml +4 -5
- package/data/flows/review.flow.yaml +3 -4
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +98 -22
- package/dist/curator/curator.js.map +1 -1
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/engine/module-manifest.d.ts +2 -0
- package/dist/engine/module-manifest.d.ts.map +1 -1
- package/dist/engine/module-manifest.js +136 -1
- package/dist/engine/module-manifest.js.map +1 -1
- package/dist/engine/register-engine.d.ts.map +1 -1
- package/dist/engine/register-engine.js +25 -1
- package/dist/engine/register-engine.js.map +1 -1
- package/dist/flows/gate-evaluator.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/operator/operator-profile.d.ts.map +1 -1
- package/dist/operator/operator-profile.js +11 -5
- package/dist/operator/operator-profile.js.map +1 -1
- package/dist/operator/operator-signals.d.ts.map +1 -1
- package/dist/operator/operator-signals.js.map +1 -1
- package/dist/planning/evidence-collector.js.map +1 -1
- package/dist/planning/gap-passes.d.ts.map +1 -1
- package/dist/planning/gap-passes.js +23 -6
- package/dist/planning/gap-passes.js.map +1 -1
- package/dist/planning/gap-patterns.d.ts.map +1 -1
- package/dist/planning/gap-patterns.js +57 -11
- package/dist/planning/gap-patterns.js.map +1 -1
- package/dist/planning/github-projection.d.ts.map +1 -1
- package/dist/planning/github-projection.js +39 -20
- package/dist/planning/github-projection.js.map +1 -1
- package/dist/planning/impact-analyzer.d.ts.map +1 -1
- package/dist/planning/impact-analyzer.js +20 -18
- package/dist/planning/impact-analyzer.js.map +1 -1
- package/dist/planning/plan-lifecycle.d.ts.map +1 -1
- package/dist/planning/plan-lifecycle.js +22 -9
- package/dist/planning/plan-lifecycle.js.map +1 -1
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +60 -17
- package/dist/planning/planner.js.map +1 -1
- package/dist/planning/rationalization-detector.d.ts.map +1 -1
- package/dist/planning/rationalization-detector.js.map +1 -1
- package/dist/planning/reconciliation-engine.d.ts.map +1 -1
- package/dist/planning/reconciliation-engine.js.map +1 -1
- package/dist/planning/task-complexity-assessor.d.ts +42 -0
- package/dist/planning/task-complexity-assessor.d.ts.map +1 -0
- package/dist/planning/task-complexity-assessor.js +132 -0
- package/dist/planning/task-complexity-assessor.js.map +1 -0
- package/dist/planning/task-verifier.d.ts.map +1 -1
- package/dist/planning/task-verifier.js +14 -6
- package/dist/planning/task-verifier.js.map +1 -1
- package/dist/runtime/admin-ops.d.ts.map +1 -1
- package/dist/runtime/admin-ops.js +18 -0
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
- package/dist/runtime/admin-setup-ops.js +2 -1
- package/dist/runtime/admin-setup-ops.js.map +1 -1
- package/dist/runtime/branching-ops.d.ts +12 -0
- package/dist/runtime/branching-ops.d.ts.map +1 -0
- package/dist/runtime/branching-ops.js +100 -0
- package/dist/runtime/branching-ops.js.map +1 -0
- package/dist/runtime/context-health.d.ts.map +1 -1
- package/dist/runtime/context-health.js.map +1 -1
- package/dist/runtime/facades/branching-facade.d.ts +7 -0
- package/dist/runtime/facades/branching-facade.d.ts.map +1 -0
- package/dist/runtime/facades/branching-facade.js +8 -0
- package/dist/runtime/facades/branching-facade.js.map +1 -0
- package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -1
- package/dist/runtime/facades/chat-service-ops.js +3 -1
- package/dist/runtime/facades/chat-service-ops.js.map +1 -1
- package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -1
- package/dist/runtime/facades/chat-transport-ops.js.map +1 -1
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +42 -0
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/facades/intake-facade.d.ts +9 -0
- package/dist/runtime/facades/intake-facade.d.ts.map +1 -0
- package/dist/runtime/facades/intake-facade.js +11 -0
- package/dist/runtime/facades/intake-facade.js.map +1 -0
- package/dist/runtime/facades/links-facade.d.ts +9 -0
- package/dist/runtime/facades/links-facade.d.ts.map +1 -0
- package/dist/runtime/facades/links-facade.js +10 -0
- package/dist/runtime/facades/links-facade.js.map +1 -0
- package/dist/runtime/facades/operator-facade.d.ts.map +1 -1
- package/dist/runtime/facades/operator-facade.js.map +1 -1
- package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
- package/dist/runtime/facades/plan-facade.js +4 -1
- package/dist/runtime/facades/plan-facade.js.map +1 -1
- package/dist/runtime/facades/tier-facade.d.ts +7 -0
- package/dist/runtime/facades/tier-facade.d.ts.map +1 -0
- package/dist/runtime/facades/tier-facade.js +8 -0
- package/dist/runtime/facades/tier-facade.js.map +1 -0
- package/dist/runtime/facades/vault-facade.d.ts +9 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +44 -187
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/github-integration.d.ts.map +1 -1
- package/dist/runtime/github-integration.js +11 -4
- package/dist/runtime/github-integration.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +75 -42
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
- package/dist/runtime/planning-extra-ops.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +3 -1
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/session-briefing.d.ts.map +1 -1
- package/dist/runtime/session-briefing.js +5 -1
- package/dist/runtime/session-briefing.js.map +1 -1
- package/dist/runtime/tier-ops.d.ts +13 -0
- package/dist/runtime/tier-ops.d.ts.map +1 -0
- package/dist/runtime/tier-ops.js +110 -0
- package/dist/runtime/tier-ops.js.map +1 -0
- package/dist/skills/sync-skills.d.ts.map +1 -1
- package/dist/skills/sync-skills.js +1 -1
- package/dist/skills/sync-skills.js.map +1 -1
- package/dist/vault/linking.d.ts.map +1 -1
- package/dist/vault/linking.js +41 -5
- package/dist/vault/linking.js.map +1 -1
- package/dist/vault/vault-entries.d.ts.map +1 -1
- package/dist/vault/vault-entries.js +68 -26
- package/dist/vault/vault-entries.js.map +1 -1
- package/dist/vault/vault-maintenance.d.ts.map +1 -1
- package/dist/vault/vault-maintenance.js +6 -2
- package/dist/vault/vault-maintenance.js.map +1 -1
- package/dist/vault/vault-markdown-sync.d.ts.map +1 -1
- package/dist/vault/vault-markdown-sync.js.map +1 -1
- package/dist/vault/vault-memories.d.ts.map +1 -1
- package/dist/vault/vault-memories.js +3 -1
- package/dist/vault/vault-memories.js.map +1 -1
- package/dist/vault/vault-schema.js +36 -10
- package/dist/vault/vault-schema.js.map +1 -1
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +5 -1
- package/dist/vault/vault.js.map +1 -1
- package/package.json +7 -7
- package/src/agency/agency-manager.test.ts +60 -40
- package/src/agency/default-rules.test.ts +17 -9
- package/src/capabilities/registry.test.ts +2 -12
- package/src/chat/agent-loop.test.ts +33 -43
- package/src/chat/mcp-bridge.test.ts +7 -2
- package/src/claudemd/inject.test.ts +2 -12
- package/src/context/context-engine.test.ts +96 -51
- package/src/control/intent-router.test.ts +3 -3
- package/src/curator/classifier.test.ts +14 -8
- package/src/curator/contradiction-detector.test.ts +30 -5
- package/src/curator/curator.ts +278 -56
- package/src/curator/duplicate-detector.test.ts +77 -15
- package/src/curator/quality-gate.test.ts +71 -31
- package/src/curator/tag-manager.test.ts +12 -4
- package/src/domain-packs/knowledge-installer.test.ts +2 -10
- package/src/domain-packs/token-resolver.test.ts +1 -3
- package/src/domain-packs/types.test.ts +16 -2
- package/src/enforcement/registry.test.ts +2 -8
- package/src/engine/bin/soleri-engine.ts +3 -1
- package/src/engine/module-manifest.test.ts +48 -4
- package/src/engine/module-manifest.ts +138 -1
- package/src/engine/register-engine.test.ts +6 -1
- package/src/engine/register-engine.ts +26 -3
- package/src/errors/classify.test.ts +6 -2
- package/src/errors/retry.test.ts +1 -4
- package/src/facades/facade-factory.test.ts +110 -64
- package/src/flows/epilogue.test.ts +16 -10
- package/src/flows/gate-evaluator.test.ts +12 -6
- package/src/flows/gate-evaluator.ts +1 -3
- package/src/governance/governance.test.ts +137 -21
- package/src/health/health-registry.test.ts +8 -1
- package/src/index.ts +8 -0
- package/src/intake/content-classifier.test.ts +121 -51
- package/src/intake/dedup-gate.test.ts +38 -22
- package/src/intake/intake-pipeline.test.ts +5 -3
- package/src/intake/text-ingester.test.ts +26 -20
- package/src/llm/key-pool.test.ts +1 -3
- package/src/llm/llm-client.test.ts +1 -4
- package/src/llm/oauth-discovery.test.ts +16 -16
- package/src/llm/utils.test.ts +62 -18
- package/src/logging/logger.test.ts +4 -1
- package/src/loop/loop-manager.test.ts +2 -6
- package/src/migrations/migration-runner.edge-cases.test.ts +2 -7
- package/src/operator/operator-profile-extended.test.ts +15 -5
- package/src/operator/operator-profile.test.ts +26 -8
- package/src/operator/operator-profile.ts +38 -22
- package/src/operator/operator-signals-extended.test.ts +35 -23
- package/src/operator/operator-signals.test.ts +6 -10
- package/src/operator/operator-signals.ts +2 -1
- package/src/operator/prompts/hook-precompact-operator-dispatch.md +10 -6
- package/src/operator/prompts/subagent-soft-signal-extractor.md +5 -0
- package/src/operator/prompts/subagent-synthesis-cognition.md +19 -10
- package/src/operator/prompts/subagent-synthesis-communication.md +13 -7
- package/src/operator/prompts/subagent-synthesis-technical.md +19 -9
- package/src/operator/prompts/subagent-synthesis-trust.md +27 -21
- package/src/persona/defaults.test.ts +1 -5
- package/src/planning/evidence-collector.test.ts +147 -38
- package/src/planning/evidence-collector.ts +1 -4
- package/src/planning/gap-analysis-alternatives.test.ts +41 -11
- package/src/planning/gap-passes.test.ts +215 -33
- package/src/planning/gap-passes.ts +115 -46
- package/src/planning/gap-patterns.test.ts +87 -13
- package/src/planning/gap-patterns.ts +114 -31
- package/src/planning/github-projection.test.ts +6 -1
- package/src/planning/github-projection.ts +41 -20
- package/src/planning/impact-analyzer.test.ts +10 -23
- package/src/planning/impact-analyzer.ts +33 -46
- package/src/planning/plan-lifecycle.test.ts +103 -36
- package/src/planning/plan-lifecycle.ts +49 -18
- package/src/planning/planner.test.ts +12 -2
- package/src/planning/planner.ts +198 -58
- package/src/planning/rationalization-detector.test.ts +5 -20
- package/src/planning/rationalization-detector.ts +14 -16
- package/src/planning/reconciliation-engine.test.ts +20 -3
- package/src/planning/reconciliation-engine.ts +1 -2
- package/src/planning/task-complexity-assessor.test.ts +298 -0
- package/src/planning/task-complexity-assessor.ts +183 -0
- package/src/planning/task-verifier.test.ts +59 -27
- package/src/planning/task-verifier.ts +15 -9
- package/src/playbooks/playbook-executor.test.ts +1 -3
- package/src/plugins/plugin-loader.test.ts +19 -14
- package/src/plugins/plugin-registry.test.ts +45 -33
- package/src/project/project-registry.test.ts +23 -12
- package/src/prompts/template-manager.test.ts +4 -1
- package/src/queue/job-queue.test.ts +10 -14
- package/src/runtime/admin-extra-ops.test.ts +5 -19
- package/src/runtime/admin-ops.test.ts +22 -1
- package/src/runtime/admin-ops.ts +19 -0
- package/src/runtime/admin-setup-ops.test.ts +3 -4
- package/src/runtime/admin-setup-ops.ts +9 -2
- package/src/runtime/archive-ops.test.ts +4 -1
- package/src/runtime/branching-ops.test.ts +144 -0
- package/src/runtime/branching-ops.ts +107 -0
- package/src/runtime/capture-ops.test.ts +7 -21
- package/src/runtime/chain-ops.test.ts +16 -6
- package/src/runtime/claude-md-helpers.test.ts +1 -3
- package/src/runtime/context-health.test.ts +1 -3
- package/src/runtime/context-health.ts +1 -3
- package/src/runtime/curator-extra-ops.test.ts +3 -1
- package/src/runtime/domain-ops.test.ts +46 -36
- package/src/runtime/facades/admin-facade.test.ts +1 -4
- package/src/runtime/facades/archive-facade.test.ts +21 -7
- package/src/runtime/facades/brain-facade.test.ts +176 -72
- package/src/runtime/facades/branching-facade.test.ts +43 -0
- package/src/runtime/facades/branching-facade.ts +11 -0
- package/src/runtime/facades/chat-facade.test.ts +81 -28
- package/src/runtime/facades/chat-service-ops.test.ts +178 -73
- package/src/runtime/facades/chat-service-ops.ts +3 -1
- package/src/runtime/facades/chat-session-ops.test.ts +25 -10
- package/src/runtime/facades/chat-transport-ops.test.ts +101 -34
- package/src/runtime/facades/chat-transport-ops.ts +0 -1
- package/src/runtime/facades/context-facade.test.ts +19 -4
- package/src/runtime/facades/control-facade.test.ts +3 -3
- package/src/runtime/facades/index.ts +42 -0
- package/src/runtime/facades/intake-facade.test.ts +215 -0
- package/src/runtime/facades/intake-facade.ts +14 -0
- package/src/runtime/facades/links-facade.test.ts +203 -0
- package/src/runtime/facades/links-facade.ts +13 -0
- package/src/runtime/facades/loop-facade.test.ts +22 -5
- package/src/runtime/facades/memory-facade.test.ts +19 -5
- package/src/runtime/facades/operator-facade.test.ts +17 -4
- package/src/runtime/facades/operator-facade.ts +11 -3
- package/src/runtime/facades/orchestrate-facade.test.ts +7 -1
- package/src/runtime/facades/plan-facade.test.ts +29 -12
- package/src/runtime/facades/plan-facade.ts +7 -2
- package/src/runtime/facades/tier-facade.test.ts +47 -0
- package/src/runtime/facades/tier-facade.ts +11 -0
- package/src/runtime/facades/vault-facade.test.ts +174 -242
- package/src/runtime/facades/vault-facade.ts +55 -199
- package/src/runtime/github-integration.ts +11 -8
- package/src/runtime/grading-ops.test.ts +39 -8
- package/src/runtime/intake-ops.test.ts +69 -16
- package/src/runtime/loop-ops.test.ts +16 -6
- package/src/runtime/memory-cross-project-ops.test.ts +25 -14
- package/src/runtime/orchestrate-ops.test.ts +204 -0
- package/src/runtime/orchestrate-ops.ts +103 -65
- package/src/runtime/pack-ops.test.ts +23 -6
- package/src/runtime/planning-extra-ops.test.ts +17 -7
- package/src/runtime/planning-extra-ops.ts +3 -1
- package/src/runtime/playbook-ops.test.ts +26 -3
- package/src/runtime/plugin-ops.test.ts +83 -25
- package/src/runtime/project-ops.test.ts +26 -6
- package/src/runtime/runtime.ts +3 -1
- package/src/runtime/session-briefing.test.ts +183 -54
- package/src/runtime/session-briefing.ts +8 -2
- package/src/runtime/sync-ops.test.ts +3 -12
- package/src/runtime/telemetry-ops.test.ts +31 -6
- package/src/runtime/tier-ops.test.ts +159 -0
- package/src/runtime/tier-ops.ts +119 -0
- package/src/runtime/vault-extra-ops.test.ts +32 -8
- package/src/runtime/vault-sharing-ops.test.ts +1 -4
- package/src/skills/sync-skills.ts +2 -12
- package/src/transport/ws-server.test.ts +7 -4
- package/src/vault/__tests__/vault-characterization.test.ts +492 -81
- package/src/vault/linking.test.ts +50 -17
- package/src/vault/linking.ts +48 -7
- package/src/vault/obsidian-sync.test.ts +6 -3
- package/src/vault/scope-detector.test.ts +1 -3
- package/src/vault/vault-branching.test.ts +9 -7
- package/src/vault/vault-entries.ts +209 -65
- package/src/vault/vault-maintenance.ts +7 -12
- package/src/vault/vault-manager.test.ts +10 -10
- package/src/vault/vault-markdown-sync.ts +4 -1
- package/src/vault/vault-memories.ts +7 -7
- package/src/vault/vault-scaling.test.ts +5 -5
- package/src/vault/vault-schema.ts +72 -15
- package/src/vault/vault.ts +55 -9
- package/src/brain/strength-scorer.ts +0 -404
- package/src/engine/index.ts +0 -21
- package/src/persona/index.ts +0 -9
- package/src/vault/vault-interfaces.ts +0 -56
|
@@ -25,13 +25,40 @@ function makePlan(overrides: Partial<Plan> = {}): Plan {
|
|
|
25
25
|
scope: 'Auth module, middleware, and user service. Does not include OAuth providers.',
|
|
26
26
|
status: 'draft',
|
|
27
27
|
decisions: [
|
|
28
|
-
{
|
|
28
|
+
{
|
|
29
|
+
decision: 'Use JWT for stateless auth',
|
|
30
|
+
rationale: 'Because it scales horizontally without shared session store',
|
|
31
|
+
},
|
|
29
32
|
],
|
|
30
33
|
tasks: [
|
|
31
|
-
{
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
{
|
|
35
|
+
id: 'task-1',
|
|
36
|
+
title: 'Add JWT signing',
|
|
37
|
+
description: 'Implement JWT sign/verify using built-in crypto module',
|
|
38
|
+
status: 'pending',
|
|
39
|
+
updatedAt: Date.now(),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'task-2',
|
|
43
|
+
title: 'Add auth middleware',
|
|
44
|
+
description: 'Create Express middleware that validates JWT from Authorization header',
|
|
45
|
+
status: 'pending',
|
|
46
|
+
updatedAt: Date.now(),
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'task-3',
|
|
50
|
+
title: 'Add login endpoint',
|
|
51
|
+
description: 'POST /auth/login returns JWT after verifying credentials',
|
|
52
|
+
status: 'pending',
|
|
53
|
+
updatedAt: Date.now(),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 'task-4',
|
|
57
|
+
title: 'Add test coverage',
|
|
58
|
+
description: 'Test JWT signing, middleware rejection, and login flow end-to-end',
|
|
59
|
+
status: 'pending',
|
|
60
|
+
updatedAt: Date.now(),
|
|
61
|
+
},
|
|
35
62
|
],
|
|
36
63
|
checks: [],
|
|
37
64
|
createdAt: Date.now(),
|
|
@@ -63,7 +90,9 @@ describe('Pattern constants (passes 5-8)', () => {
|
|
|
63
90
|
});
|
|
64
91
|
|
|
65
92
|
it('GENERIC_OBJECTIVE_PATTERNS does not match detailed objectives', () => {
|
|
66
|
-
expect(
|
|
93
|
+
expect(
|
|
94
|
+
GENERIC_OBJECTIVE_PATTERNS.some((p) => p.test('Create a user auth module with JWT')),
|
|
95
|
+
).toBe(false);
|
|
67
96
|
});
|
|
68
97
|
|
|
69
98
|
it('RATIONALE_INDICATORS contains reasoning words', () => {
|
|
@@ -107,7 +136,13 @@ describe('Pass 5: Clarity', () => {
|
|
|
107
136
|
it('flags tasks with very short descriptions', () => {
|
|
108
137
|
const plan = makePlan({
|
|
109
138
|
tasks: [
|
|
110
|
-
{
|
|
139
|
+
{
|
|
140
|
+
id: 't1',
|
|
141
|
+
title: 'Do thing',
|
|
142
|
+
description: 'Short',
|
|
143
|
+
status: 'pending',
|
|
144
|
+
updatedAt: Date.now(),
|
|
145
|
+
},
|
|
111
146
|
{ id: 't2', title: 'Do other', description: '', status: 'pending', updatedAt: Date.now() },
|
|
112
147
|
],
|
|
113
148
|
});
|
|
@@ -123,7 +158,8 @@ describe('Pass 5: Clarity', () => {
|
|
|
123
158
|
|
|
124
159
|
it('limits ambiguous words shown to 5', () => {
|
|
125
160
|
const plan = makePlan({
|
|
126
|
-
objective:
|
|
161
|
+
objective:
|
|
162
|
+
'Maybe perhaps we might could possibly somehow probably do various several things soon with some easy simple appropriate changes etc',
|
|
127
163
|
scope: 'Everything. Not limited.',
|
|
128
164
|
});
|
|
129
165
|
const gaps = analyzeClarity(plan);
|
|
@@ -158,7 +194,13 @@ describe('Pass 6: Semantic Quality', () => {
|
|
|
158
194
|
it('flags too few tasks', () => {
|
|
159
195
|
const plan = makePlan({
|
|
160
196
|
tasks: [
|
|
161
|
-
{
|
|
197
|
+
{
|
|
198
|
+
id: 't1',
|
|
199
|
+
title: 'Single task',
|
|
200
|
+
description: 'Do everything in one task',
|
|
201
|
+
status: 'pending',
|
|
202
|
+
updatedAt: Date.now(),
|
|
203
|
+
},
|
|
162
204
|
],
|
|
163
205
|
});
|
|
164
206
|
const gaps = analyzeSemanticQuality(plan);
|
|
@@ -167,7 +209,11 @@ describe('Pass 6: Semantic Quality', () => {
|
|
|
167
209
|
|
|
168
210
|
it('flags too many tasks (> 20)', () => {
|
|
169
211
|
const tasks = Array.from({ length: 21 }, (_, i) => ({
|
|
170
|
-
id: `t${i}`,
|
|
212
|
+
id: `t${i}`,
|
|
213
|
+
title: `Task ${i}`,
|
|
214
|
+
description: `Description for task ${i} with enough detail`,
|
|
215
|
+
status: 'pending' as const,
|
|
216
|
+
updatedAt: Date.now(),
|
|
171
217
|
}));
|
|
172
218
|
const plan = makePlan({ tasks });
|
|
173
219
|
const gaps = analyzeSemanticQuality(plan);
|
|
@@ -184,7 +230,9 @@ describe('Pass 6: Semantic Quality', () => {
|
|
|
184
230
|
|
|
185
231
|
it('does not flag decisions with proper rationale', () => {
|
|
186
232
|
const plan = makePlan({
|
|
187
|
-
decisions: [
|
|
233
|
+
decisions: [
|
|
234
|
+
{ decision: 'Use JWT', rationale: 'This is better because it scales horizontally' },
|
|
235
|
+
],
|
|
188
236
|
});
|
|
189
237
|
const gaps = analyzeSemanticQuality(plan);
|
|
190
238
|
expect(gaps.some((g) => g._trigger === 'shallow_rationale')).toBe(false);
|
|
@@ -193,9 +241,27 @@ describe('Pass 6: Semantic Quality', () => {
|
|
|
193
241
|
it('flags duplicate task titles', () => {
|
|
194
242
|
const plan = makePlan({
|
|
195
243
|
tasks: [
|
|
196
|
-
{
|
|
197
|
-
|
|
198
|
-
|
|
244
|
+
{
|
|
245
|
+
id: 't1',
|
|
246
|
+
title: 'Implement feature',
|
|
247
|
+
description: 'First implementation',
|
|
248
|
+
status: 'pending',
|
|
249
|
+
updatedAt: Date.now(),
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
id: 't2',
|
|
253
|
+
title: 'Implement feature',
|
|
254
|
+
description: 'Duplicate title',
|
|
255
|
+
status: 'pending',
|
|
256
|
+
updatedAt: Date.now(),
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
id: 't3',
|
|
260
|
+
title: 'Test feature',
|
|
261
|
+
description: 'Test the feature with assertions',
|
|
262
|
+
status: 'pending',
|
|
263
|
+
updatedAt: Date.now(),
|
|
264
|
+
},
|
|
199
265
|
],
|
|
200
266
|
});
|
|
201
267
|
const gaps = analyzeSemanticQuality(plan);
|
|
@@ -212,7 +278,13 @@ describe('Pass 6: Semantic Quality', () => {
|
|
|
212
278
|
const plan = makePlan({
|
|
213
279
|
decisions: [],
|
|
214
280
|
tasks: [
|
|
215
|
-
{
|
|
281
|
+
{
|
|
282
|
+
id: 't1',
|
|
283
|
+
title: 'Single task',
|
|
284
|
+
description: 'Do the thing',
|
|
285
|
+
status: 'pending',
|
|
286
|
+
updatedAt: Date.now(),
|
|
287
|
+
},
|
|
216
288
|
],
|
|
217
289
|
});
|
|
218
290
|
const gaps = analyzeSemanticQuality(plan);
|
|
@@ -224,9 +296,28 @@ describe('Pass 7: Knowledge Depth', () => {
|
|
|
224
296
|
it('awards bonus for 5+ vault pattern references', () => {
|
|
225
297
|
const plan = makePlan({
|
|
226
298
|
tasks: [
|
|
227
|
-
{
|
|
228
|
-
|
|
229
|
-
|
|
299
|
+
{
|
|
300
|
+
id: 't1',
|
|
301
|
+
title: 'Apply patterns',
|
|
302
|
+
description: 'Use zod-form-validation and react-query-caching and error-boundary-pattern',
|
|
303
|
+
status: 'pending',
|
|
304
|
+
updatedAt: Date.now(),
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
id: 't2',
|
|
308
|
+
title: 'More patterns',
|
|
309
|
+
description:
|
|
310
|
+
'Use accessibility-focus-ring and semantic-token-usage and component-variant-pattern',
|
|
311
|
+
status: 'pending',
|
|
312
|
+
updatedAt: Date.now(),
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
id: 't3',
|
|
316
|
+
title: 'Testing',
|
|
317
|
+
description: 'Test with vitest-snapshot-testing approach',
|
|
318
|
+
status: 'pending',
|
|
319
|
+
updatedAt: Date.now(),
|
|
320
|
+
},
|
|
230
321
|
],
|
|
231
322
|
});
|
|
232
323
|
const gaps = analyzeKnowledgeDepth(plan);
|
|
@@ -237,9 +328,27 @@ describe('Pass 7: Knowledge Depth', () => {
|
|
|
237
328
|
it('awards bonus for 2-4 vault pattern references', () => {
|
|
238
329
|
const plan = makePlan({
|
|
239
330
|
tasks: [
|
|
240
|
-
{
|
|
241
|
-
|
|
242
|
-
|
|
331
|
+
{
|
|
332
|
+
id: 't1',
|
|
333
|
+
title: 'Apply patterns',
|
|
334
|
+
description: 'Use zod-form-validation and react-query-caching',
|
|
335
|
+
status: 'pending',
|
|
336
|
+
updatedAt: Date.now(),
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
id: 't2',
|
|
340
|
+
title: 'Build',
|
|
341
|
+
description: 'Build the component',
|
|
342
|
+
status: 'pending',
|
|
343
|
+
updatedAt: Date.now(),
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
id: 't3',
|
|
347
|
+
title: 'Test',
|
|
348
|
+
description: 'Run the test suite',
|
|
349
|
+
status: 'pending',
|
|
350
|
+
updatedAt: Date.now(),
|
|
351
|
+
},
|
|
243
352
|
],
|
|
244
353
|
});
|
|
245
354
|
const gaps = analyzeKnowledgeDepth(plan);
|
|
@@ -249,11 +358,46 @@ describe('Pass 7: Knowledge Depth', () => {
|
|
|
249
358
|
it('awards bonus for high acceptance criteria coverage', () => {
|
|
250
359
|
const plan = makePlan({
|
|
251
360
|
tasks: [
|
|
252
|
-
{
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
361
|
+
{
|
|
362
|
+
id: 't1',
|
|
363
|
+
title: 'T1',
|
|
364
|
+
description: 'Desc 1',
|
|
365
|
+
status: 'pending',
|
|
366
|
+
updatedAt: Date.now(),
|
|
367
|
+
acceptanceCriteria: ['Criteria A'],
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
id: 't2',
|
|
371
|
+
title: 'T2',
|
|
372
|
+
description: 'Desc 2',
|
|
373
|
+
status: 'pending',
|
|
374
|
+
updatedAt: Date.now(),
|
|
375
|
+
acceptanceCriteria: ['Criteria B'],
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
id: 't3',
|
|
379
|
+
title: 'T3',
|
|
380
|
+
description: 'Desc 3',
|
|
381
|
+
status: 'pending',
|
|
382
|
+
updatedAt: Date.now(),
|
|
383
|
+
acceptanceCriteria: ['Criteria C'],
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
id: 't4',
|
|
387
|
+
title: 'T4',
|
|
388
|
+
description: 'Desc 4',
|
|
389
|
+
status: 'pending',
|
|
390
|
+
updatedAt: Date.now(),
|
|
391
|
+
acceptanceCriteria: ['Criteria D'],
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
id: 't5',
|
|
395
|
+
title: 'T5',
|
|
396
|
+
description: 'Desc 5',
|
|
397
|
+
status: 'pending',
|
|
398
|
+
updatedAt: Date.now(),
|
|
399
|
+
acceptanceCriteria: ['Criteria E'],
|
|
400
|
+
},
|
|
257
401
|
],
|
|
258
402
|
});
|
|
259
403
|
const gaps = analyzeKnowledgeDepth(plan);
|
|
@@ -263,7 +407,14 @@ describe('Pass 7: Knowledge Depth', () => {
|
|
|
263
407
|
it('does not award acceptance criteria bonus below 80% threshold', () => {
|
|
264
408
|
const plan = makePlan({
|
|
265
409
|
tasks: [
|
|
266
|
-
{
|
|
410
|
+
{
|
|
411
|
+
id: 't1',
|
|
412
|
+
title: 'T1',
|
|
413
|
+
description: 'Desc',
|
|
414
|
+
status: 'pending',
|
|
415
|
+
updatedAt: Date.now(),
|
|
416
|
+
acceptanceCriteria: ['A'],
|
|
417
|
+
},
|
|
267
418
|
{ id: 't2', title: 'T2', description: 'Desc', status: 'pending', updatedAt: Date.now() },
|
|
268
419
|
{ id: 't3', title: 'T3', description: 'Desc', status: 'pending', updatedAt: Date.now() },
|
|
269
420
|
],
|
|
@@ -273,7 +424,8 @@ describe('Pass 7: Knowledge Depth', () => {
|
|
|
273
424
|
});
|
|
274
425
|
|
|
275
426
|
it('awards bonus for rich task descriptions (avg >= 80 chars)', () => {
|
|
276
|
-
const longDesc =
|
|
427
|
+
const longDesc =
|
|
428
|
+
'This is a very detailed task description that provides specific technical context about what needs to be implemented.';
|
|
277
429
|
const plan = makePlan({
|
|
278
430
|
tasks: [
|
|
279
431
|
{ id: 't1', title: 'T1', description: longDesc, status: 'pending', updatedAt: Date.now() },
|
|
@@ -288,9 +440,27 @@ describe('Pass 7: Knowledge Depth', () => {
|
|
|
288
440
|
it('awards bonus for domain knowledge indicators', () => {
|
|
289
441
|
const plan = makePlan({
|
|
290
442
|
tasks: [
|
|
291
|
-
{
|
|
292
|
-
|
|
293
|
-
|
|
443
|
+
{
|
|
444
|
+
id: 't1',
|
|
445
|
+
title: 'A11y audit',
|
|
446
|
+
description: 'Check WCAG 2.1 compliance and aria-label usage with vault patterns',
|
|
447
|
+
status: 'pending',
|
|
448
|
+
updatedAt: Date.now(),
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
id: 't2',
|
|
452
|
+
title: 'Contrast',
|
|
453
|
+
description: '4.5:1 contrast ratio for all text, anti-pattern detection',
|
|
454
|
+
status: 'pending',
|
|
455
|
+
updatedAt: Date.now(),
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
id: 't3',
|
|
459
|
+
title: 'Touch',
|
|
460
|
+
description: '44px touch target minimum, acceptance criteria for all buttons',
|
|
461
|
+
status: 'pending',
|
|
462
|
+
updatedAt: Date.now(),
|
|
463
|
+
},
|
|
294
464
|
],
|
|
295
465
|
});
|
|
296
466
|
const gaps = analyzeKnowledgeDepth(plan);
|
|
@@ -300,7 +470,13 @@ describe('Pass 7: Knowledge Depth', () => {
|
|
|
300
470
|
it('returns no bonuses for basic plan', () => {
|
|
301
471
|
const plan = makePlan({
|
|
302
472
|
tasks: [
|
|
303
|
-
{
|
|
473
|
+
{
|
|
474
|
+
id: 't1',
|
|
475
|
+
title: 'Do thing',
|
|
476
|
+
description: 'Do it',
|
|
477
|
+
status: 'pending',
|
|
478
|
+
updatedAt: Date.now(),
|
|
479
|
+
},
|
|
304
480
|
],
|
|
305
481
|
});
|
|
306
482
|
const gaps = analyzeKnowledgeDepth(plan);
|
|
@@ -311,7 +487,13 @@ describe('Pass 7: Knowledge Depth', () => {
|
|
|
311
487
|
it('excludes common hyphenated words from pattern refs', () => {
|
|
312
488
|
const plan = makePlan({
|
|
313
489
|
tasks: [
|
|
314
|
-
{
|
|
490
|
+
{
|
|
491
|
+
id: 't1',
|
|
492
|
+
title: 'T1',
|
|
493
|
+
description: 'Use front-end and back-end and real-time and client-side and server-side',
|
|
494
|
+
status: 'pending',
|
|
495
|
+
updatedAt: Date.now(),
|
|
496
|
+
},
|
|
315
497
|
],
|
|
316
498
|
});
|
|
317
499
|
const gaps = analyzeKnowledgeDepth(plan);
|
|
@@ -6,20 +6,26 @@
|
|
|
6
6
|
|
|
7
7
|
import type { Plan } from './planner.js';
|
|
8
8
|
import type { PlanGap } from './gap-types.js';
|
|
9
|
-
import {
|
|
10
|
-
gap,
|
|
11
|
-
taskText,
|
|
12
|
-
decisionText,
|
|
13
|
-
decisionsText,
|
|
14
|
-
containsAny,
|
|
15
|
-
} from './gap-patterns.js';
|
|
9
|
+
import { gap, taskText, decisionText, decisionsText, containsAny } from './gap-patterns.js';
|
|
16
10
|
|
|
17
11
|
// ─── Pattern Constants (Passes 5-8) ─────────────────────────────
|
|
18
12
|
|
|
19
13
|
export const AMBIGUOUS_WORDS = [
|
|
20
|
-
'maybe',
|
|
21
|
-
'
|
|
22
|
-
'
|
|
14
|
+
'maybe',
|
|
15
|
+
'perhaps',
|
|
16
|
+
'might',
|
|
17
|
+
'could',
|
|
18
|
+
'some',
|
|
19
|
+
'etc',
|
|
20
|
+
'soon',
|
|
21
|
+
'simple',
|
|
22
|
+
'easy',
|
|
23
|
+
'appropriate',
|
|
24
|
+
'various',
|
|
25
|
+
'several',
|
|
26
|
+
'probably',
|
|
27
|
+
'possibly',
|
|
28
|
+
'somehow',
|
|
23
29
|
];
|
|
24
30
|
|
|
25
31
|
export const GENERIC_OBJECTIVE_PATTERNS = [
|
|
@@ -29,8 +35,13 @@ export const GENERIC_OBJECTIVE_PATTERNS = [
|
|
|
29
35
|
];
|
|
30
36
|
|
|
31
37
|
export const RATIONALE_INDICATORS = [
|
|
32
|
-
'because',
|
|
33
|
-
'
|
|
38
|
+
'because',
|
|
39
|
+
'since',
|
|
40
|
+
'due to',
|
|
41
|
+
'in order to',
|
|
42
|
+
'so that',
|
|
43
|
+
'given that',
|
|
44
|
+
'as a result',
|
|
34
45
|
];
|
|
35
46
|
|
|
36
47
|
export const SHALLOW_INDICATORS = ['better', 'good', 'best', 'nice', 'great', 'improved'];
|
|
@@ -64,10 +75,12 @@ export function analyzeClarity(plan: Plan): PlanGap[] {
|
|
|
64
75
|
if (found.length > 0) {
|
|
65
76
|
gaps.push(
|
|
66
77
|
gap(
|
|
67
|
-
'minor',
|
|
78
|
+
'minor',
|
|
79
|
+
'clarity',
|
|
68
80
|
`Ambiguous language detected: ${found.slice(0, 5).join(', ')}${found.length > 5 ? ` (+${found.length - 5} more)` : ''}.`,
|
|
69
81
|
'Replace vague terms with concrete, specific language.',
|
|
70
|
-
undefined,
|
|
82
|
+
undefined,
|
|
83
|
+
`ambiguous_words:${found.join(',')}`,
|
|
71
84
|
),
|
|
72
85
|
);
|
|
73
86
|
}
|
|
@@ -76,10 +89,12 @@ export function analyzeClarity(plan: Plan): PlanGap[] {
|
|
|
76
89
|
if (shortTasks.length > 0) {
|
|
77
90
|
gaps.push(
|
|
78
91
|
gap(
|
|
79
|
-
'minor',
|
|
92
|
+
'minor',
|
|
93
|
+
'clarity',
|
|
80
94
|
`${shortTasks.length} task(s) with very short descriptions: ${shortTasks.map((t) => t.id).join(', ')}.`,
|
|
81
95
|
'Add detailed descriptions to all tasks explaining what needs to be done.',
|
|
82
|
-
'tasks',
|
|
96
|
+
'tasks',
|
|
97
|
+
'short_task_descriptions',
|
|
83
98
|
),
|
|
84
99
|
);
|
|
85
100
|
}
|
|
@@ -99,10 +114,12 @@ export function analyzeSemanticQuality(plan: Plan): PlanGap[] {
|
|
|
99
114
|
if (isGeneric || words.length < 5) {
|
|
100
115
|
gaps.push(
|
|
101
116
|
gap(
|
|
102
|
-
'major',
|
|
117
|
+
'major',
|
|
118
|
+
'semantic-quality',
|
|
103
119
|
`Objective is too generic${words.length < 5 ? ` (${words.length} words)` : ''}: "${plan.objective.trim()}".`,
|
|
104
120
|
'Expand the objective to describe the specific outcome, context, and constraints.',
|
|
105
|
-
'objective',
|
|
121
|
+
'objective',
|
|
122
|
+
'generic_objective',
|
|
106
123
|
),
|
|
107
124
|
);
|
|
108
125
|
}
|
|
@@ -111,19 +128,23 @@ export function analyzeSemanticQuality(plan: Plan): PlanGap[] {
|
|
|
111
128
|
if (plan.tasks.length > 0 && plan.tasks.length < 3) {
|
|
112
129
|
gaps.push(
|
|
113
130
|
gap(
|
|
114
|
-
'minor',
|
|
131
|
+
'minor',
|
|
132
|
+
'semantic-quality',
|
|
115
133
|
`Only ${plan.tasks.length} task(s) — plan may lack sufficient breakdown.`,
|
|
116
134
|
'Break down the work into 3-15 well-defined tasks for better tracking.',
|
|
117
|
-
'tasks',
|
|
135
|
+
'tasks',
|
|
136
|
+
'too_few_tasks',
|
|
118
137
|
),
|
|
119
138
|
);
|
|
120
139
|
} else if (plan.tasks.length > 20) {
|
|
121
140
|
gaps.push(
|
|
122
141
|
gap(
|
|
123
|
-
'major',
|
|
142
|
+
'major',
|
|
143
|
+
'semantic-quality',
|
|
124
144
|
`${plan.tasks.length} tasks — plan scope may be too large.`,
|
|
125
145
|
'Split into multiple plans or consolidate related tasks to stay under 20.',
|
|
126
|
-
'tasks',
|
|
146
|
+
'tasks',
|
|
147
|
+
'too_many_tasks',
|
|
127
148
|
),
|
|
128
149
|
);
|
|
129
150
|
}
|
|
@@ -135,10 +156,12 @@ export function analyzeSemanticQuality(plan: Plan): PlanGap[] {
|
|
|
135
156
|
if (hasShallow && !hasRationale) {
|
|
136
157
|
gaps.push(
|
|
137
158
|
gap(
|
|
138
|
-
'minor',
|
|
159
|
+
'minor',
|
|
160
|
+
'semantic-quality',
|
|
139
161
|
`Decision ${i + 1} uses subjective language without justification.`,
|
|
140
162
|
'Replace "better/good/best" with concrete reasoning using "because/since/due to".',
|
|
141
|
-
`decisions[${i}]`,
|
|
163
|
+
`decisions[${i}]`,
|
|
164
|
+
'shallow_rationale',
|
|
142
165
|
),
|
|
143
166
|
);
|
|
144
167
|
}
|
|
@@ -153,10 +176,12 @@ export function analyzeSemanticQuality(plan: Plan): PlanGap[] {
|
|
|
153
176
|
if (duplicates.length > 0) {
|
|
154
177
|
gaps.push(
|
|
155
178
|
gap(
|
|
156
|
-
'minor',
|
|
179
|
+
'minor',
|
|
180
|
+
'semantic-quality',
|
|
157
181
|
`Duplicate task titles: ${[...new Set(duplicates)].join(', ')}.`,
|
|
158
182
|
'Give each task a unique, descriptive title.',
|
|
159
|
-
'tasks',
|
|
183
|
+
'tasks',
|
|
184
|
+
'duplicate_task_titles',
|
|
160
185
|
),
|
|
161
186
|
);
|
|
162
187
|
}
|
|
@@ -164,10 +189,12 @@ export function analyzeSemanticQuality(plan: Plan): PlanGap[] {
|
|
|
164
189
|
if (plan.tasks.length >= 3 && plan.decisions.length === 0) {
|
|
165
190
|
gaps.push(
|
|
166
191
|
gap(
|
|
167
|
-
'major',
|
|
192
|
+
'major',
|
|
193
|
+
'semantic-quality',
|
|
168
194
|
`${plan.tasks.length} tasks but no decisions documented.`,
|
|
169
195
|
'Document key decisions and their rationale — at least 1 per 3 tasks.',
|
|
170
|
-
'decisions',
|
|
196
|
+
'decisions',
|
|
197
|
+
'no_decisions',
|
|
171
198
|
),
|
|
172
199
|
);
|
|
173
200
|
}
|
|
@@ -196,20 +223,35 @@ export function analyzeKnowledgeDepth(plan: Plan): PlanGap[] {
|
|
|
196
223
|
|
|
197
224
|
if (namedPatternCount >= 5) {
|
|
198
225
|
gaps.push(
|
|
199
|
-
gap(
|
|
226
|
+
gap(
|
|
227
|
+
'bonus',
|
|
228
|
+
'knowledge-depth',
|
|
200
229
|
`${namedPatternCount} vault pattern references across tasks — strong knowledge-informed plan.`,
|
|
201
|
-
'',
|
|
230
|
+
'',
|
|
231
|
+
'tasks',
|
|
232
|
+
'vault_pattern_refs_high',
|
|
233
|
+
),
|
|
202
234
|
);
|
|
203
235
|
gaps.push(
|
|
204
|
-
gap(
|
|
236
|
+
gap(
|
|
237
|
+
'bonus',
|
|
238
|
+
'knowledge-depth',
|
|
205
239
|
'Vault pattern density indicates expert-level domain knowledge.',
|
|
206
|
-
'',
|
|
240
|
+
'',
|
|
241
|
+
'tasks',
|
|
242
|
+
'vault_pattern_density',
|
|
243
|
+
),
|
|
207
244
|
);
|
|
208
245
|
} else if (namedPatternCount >= 2) {
|
|
209
246
|
gaps.push(
|
|
210
|
-
gap(
|
|
247
|
+
gap(
|
|
248
|
+
'bonus',
|
|
249
|
+
'knowledge-depth',
|
|
211
250
|
`${namedPatternCount} vault pattern references across tasks.`,
|
|
212
|
-
'',
|
|
251
|
+
'',
|
|
252
|
+
'tasks',
|
|
253
|
+
'vault_pattern_refs_medium',
|
|
254
|
+
),
|
|
213
255
|
);
|
|
214
256
|
}
|
|
215
257
|
|
|
@@ -224,9 +266,14 @@ export function analyzeKnowledgeDepth(plan: Plan): PlanGap[] {
|
|
|
224
266
|
|
|
225
267
|
if (plan.tasks.length > 0 && tasksWithCriteria / plan.tasks.length >= 0.8) {
|
|
226
268
|
gaps.push(
|
|
227
|
-
gap(
|
|
269
|
+
gap(
|
|
270
|
+
'bonus',
|
|
271
|
+
'knowledge-depth',
|
|
228
272
|
`${tasksWithCriteria}/${plan.tasks.length} tasks have acceptance criteria (${totalCriteria} total).`,
|
|
229
|
-
'',
|
|
273
|
+
'',
|
|
274
|
+
'tasks',
|
|
275
|
+
'high_acceptance_criteria',
|
|
276
|
+
),
|
|
230
277
|
);
|
|
231
278
|
}
|
|
232
279
|
|
|
@@ -237,9 +284,14 @@ export function analyzeKnowledgeDepth(plan: Plan): PlanGap[] {
|
|
|
237
284
|
|
|
238
285
|
if (indicatorHits >= 4) {
|
|
239
286
|
gaps.push(
|
|
240
|
-
gap(
|
|
287
|
+
gap(
|
|
288
|
+
'bonus',
|
|
289
|
+
'knowledge-depth',
|
|
241
290
|
`${indicatorHits} domain-specific knowledge indicators found (WCAG, ARIA, contrast ratios, touch targets, etc.).`,
|
|
242
|
-
'',
|
|
291
|
+
'',
|
|
292
|
+
'tasks',
|
|
293
|
+
'domain_knowledge_indicators',
|
|
294
|
+
),
|
|
243
295
|
);
|
|
244
296
|
}
|
|
245
297
|
|
|
@@ -248,9 +300,14 @@ export function analyzeKnowledgeDepth(plan: Plan): PlanGap[] {
|
|
|
248
300
|
plan.tasks.reduce((sum, t) => sum + (t.description?.length ?? 0), 0) / plan.tasks.length;
|
|
249
301
|
if (avgDescLength >= 80) {
|
|
250
302
|
gaps.push(
|
|
251
|
-
gap(
|
|
303
|
+
gap(
|
|
304
|
+
'bonus',
|
|
305
|
+
'knowledge-depth',
|
|
252
306
|
`Task descriptions average ${Math.round(avgDescLength)} chars — detailed and specific.`,
|
|
253
|
-
'',
|
|
307
|
+
'',
|
|
308
|
+
'tasks',
|
|
309
|
+
'rich_task_descriptions',
|
|
310
|
+
),
|
|
254
311
|
);
|
|
255
312
|
}
|
|
256
313
|
}
|
|
@@ -266,30 +323,42 @@ export function analyzeAlternatives(plan: Plan): PlanGap[] {
|
|
|
266
323
|
|
|
267
324
|
if (!alts || alts.length === 0) {
|
|
268
325
|
gaps.push(
|
|
269
|
-
gap(
|
|
326
|
+
gap(
|
|
327
|
+
'major',
|
|
328
|
+
'alternative-analysis',
|
|
270
329
|
'No alternatives considered — risk of tunnel vision.',
|
|
271
330
|
'Add at least 2 rejected alternatives with pros, cons, and rejection rationale.',
|
|
272
|
-
'alternatives',
|
|
331
|
+
'alternatives',
|
|
332
|
+
'no_alternatives',
|
|
333
|
+
),
|
|
273
334
|
);
|
|
274
335
|
return gaps;
|
|
275
336
|
}
|
|
276
337
|
|
|
277
338
|
if (alts.length < 2) {
|
|
278
339
|
gaps.push(
|
|
279
|
-
gap(
|
|
340
|
+
gap(
|
|
341
|
+
'minor',
|
|
342
|
+
'alternative-analysis',
|
|
280
343
|
`Only ${alts.length} alternative explored — consider at least 2.`,
|
|
281
344
|
'Add another rejected alternative to strengthen decision rationale.',
|
|
282
|
-
'alternatives',
|
|
345
|
+
'alternatives',
|
|
346
|
+
'few_alternatives',
|
|
347
|
+
),
|
|
283
348
|
);
|
|
284
349
|
}
|
|
285
350
|
|
|
286
351
|
for (let i = 0; i < alts.length; i++) {
|
|
287
352
|
if (!alts[i].rejected_reason || alts[i].rejected_reason.trim().length === 0) {
|
|
288
353
|
gaps.push(
|
|
289
|
-
gap(
|
|
354
|
+
gap(
|
|
355
|
+
'minor',
|
|
356
|
+
'alternative-analysis',
|
|
290
357
|
`Alternative ${i + 1} ("${alts[i].approach}") missing rejection rationale.`,
|
|
291
358
|
'Explain why this alternative was rejected.',
|
|
292
|
-
`alternatives[${i}]`,
|
|
359
|
+
`alternatives[${i}]`,
|
|
360
|
+
'missing_rejection_rationale',
|
|
361
|
+
),
|
|
293
362
|
);
|
|
294
363
|
}
|
|
295
364
|
}
|