@seanmars/tospec 0.19.0-beta.8 → 0.20.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/CHANGELOG.md +60 -310
- package/README.md +69 -82
- package/assets/dashboard/app.js +11 -0
- package/assets/dashboard/style.css +7 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +89 -106
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/config.d.ts +9 -17
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +293 -145
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/dashboard.d.ts +57 -99
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +190 -313
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/decision.d.ts +38 -27
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +296 -128
- package/dist/commands/decision.js.map +1 -1
- package/dist/commands/metrics.d.ts +28 -51
- package/dist/commands/metrics.d.ts.map +1 -1
- package/dist/commands/metrics.js +62 -93
- package/dist/commands/metrics.js.map +1 -1
- package/dist/commands/shared-output.d.ts +12 -27
- package/dist/commands/shared-output.d.ts.map +1 -1
- package/dist/commands/shared-output.js +22 -45
- package/dist/commands/shared-output.js.map +1 -1
- package/dist/commands/show.d.ts +4 -7
- package/dist/commands/show.d.ts.map +1 -1
- package/dist/commands/show.js +23 -11
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/validate.d.ts +34 -58
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +225 -141
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/workflow/index.d.ts +1 -5
- package/dist/commands/workflow/index.d.ts.map +1 -1
- package/dist/commands/workflow/index.js +1 -5
- package/dist/commands/workflow/index.js.map +1 -1
- package/dist/commands/workflow/instructions.d.ts +14 -24
- package/dist/commands/workflow/instructions.d.ts.map +1 -1
- package/dist/commands/workflow/instructions.js +219 -128
- package/dist/commands/workflow/instructions.js.map +1 -1
- package/dist/commands/workflow/new-change.d.ts +2 -5
- package/dist/commands/workflow/new-change.d.ts.map +1 -1
- package/dist/commands/workflow/new-change.js +69 -32
- package/dist/commands/workflow/new-change.js.map +1 -1
- package/dist/commands/workflow/schemas.d.ts +1 -5
- package/dist/commands/workflow/schemas.d.ts.map +1 -1
- package/dist/commands/workflow/schemas.js +6 -17
- package/dist/commands/workflow/schemas.js.map +1 -1
- package/dist/commands/workflow/shared.d.ts +37 -42
- package/dist/commands/workflow/shared.d.ts.map +1 -1
- package/dist/commands/workflow/shared.js +23 -54
- package/dist/commands/workflow/shared.js.map +1 -1
- package/dist/commands/workflow/status.d.ts +7 -17
- package/dist/commands/workflow/status.d.ts.map +1 -1
- package/dist/commands/workflow/status.js +57 -72
- package/dist/commands/workflow/status.js.map +1 -1
- package/dist/commands/workflow/templates.d.ts +8 -8
- package/dist/commands/workflow/templates.d.ts.map +1 -1
- package/dist/commands/workflow/templates.js +32 -46
- package/dist/commands/workflow/templates.js.map +1 -1
- package/dist/core/archive.d.ts +22 -31
- package/dist/core/archive.d.ts.map +1 -1
- package/dist/core/archive.js +296 -283
- package/dist/core/archive.js.map +1 -1
- package/dist/core/artifact-graph/graph.d.ts +25 -42
- package/dist/core/artifact-graph/graph.d.ts.map +1 -1
- package/dist/core/artifact-graph/graph.js +45 -63
- package/dist/core/artifact-graph/graph.js.map +1 -1
- package/dist/core/artifact-graph/index.d.ts +1 -1
- package/dist/core/artifact-graph/index.d.ts.map +1 -1
- package/dist/core/artifact-graph/index.js +1 -1
- package/dist/core/artifact-graph/index.js.map +1 -1
- package/dist/core/artifact-graph/instruction-loader.d.ts +54 -120
- package/dist/core/artifact-graph/instruction-loader.d.ts.map +1 -1
- package/dist/core/artifact-graph/instruction-loader.js +129 -111
- package/dist/core/artifact-graph/instruction-loader.js.map +1 -1
- package/dist/core/artifact-graph/outputs.d.ts +9 -23
- package/dist/core/artifact-graph/outputs.d.ts.map +1 -1
- package/dist/core/artifact-graph/outputs.js +45 -38
- package/dist/core/artifact-graph/outputs.js.map +1 -1
- package/dist/core/artifact-graph/resolver.d.ts +36 -81
- package/dist/core/artifact-graph/resolver.d.ts.map +1 -1
- package/dist/core/artifact-graph/resolver.js +60 -101
- package/dist/core/artifact-graph/resolver.js.map +1 -1
- package/dist/core/artifact-graph/schema.d.ts +0 -6
- package/dist/core/artifact-graph/schema.d.ts.map +1 -1
- package/dist/core/artifact-graph/schema.js +7 -32
- package/dist/core/artifact-graph/schema.js.map +1 -1
- package/dist/core/artifact-graph/state.d.ts +1 -8
- package/dist/core/artifact-graph/state.d.ts.map +1 -1
- package/dist/core/artifact-graph/state.js +2 -17
- package/dist/core/artifact-graph/state.js.map +1 -1
- package/dist/core/artifact-graph/stub-detection.d.ts +6 -14
- package/dist/core/artifact-graph/stub-detection.d.ts.map +1 -1
- package/dist/core/artifact-graph/stub-detection.js +13 -16
- package/dist/core/artifact-graph/stub-detection.js.map +1 -1
- package/dist/core/artifact-graph/types.d.ts +4 -0
- package/dist/core/artifact-graph/types.d.ts.map +1 -1
- package/dist/core/artifact-graph/types.js +30 -10
- package/dist/core/artifact-graph/types.js.map +1 -1
- package/dist/core/available-tools.d.ts +3 -12
- package/dist/core/available-tools.d.ts.map +1 -1
- package/dist/core/available-tools.js +4 -13
- package/dist/core/available-tools.js.map +1 -1
- package/dist/core/change-metadata/schema.d.ts +1 -1
- package/dist/core/change-metadata/schema.d.ts.map +1 -1
- package/dist/core/change-metadata/schema.js +10 -7
- package/dist/core/change-metadata/schema.js.map +1 -1
- package/dist/core/change-presenter.d.ts +16 -27
- package/dist/core/change-presenter.d.ts.map +1 -1
- package/dist/core/change-presenter.js +53 -53
- package/dist/core/change-presenter.js.map +1 -1
- package/dist/core/change-status-policy.d.ts +4 -8
- package/dist/core/change-status-policy.d.ts.map +1 -1
- package/dist/core/change-status-policy.js +9 -17
- package/dist/core/change-status-policy.js.map +1 -1
- package/dist/core/codex-metrics.d.ts +25 -45
- package/dist/core/codex-metrics.d.ts.map +1 -1
- package/dist/core/codex-metrics.js +44 -88
- package/dist/core/codex-metrics.js.map +1 -1
- package/dist/core/codex-residue.d.ts +14 -15
- package/dist/core/codex-residue.d.ts.map +1 -1
- package/dist/core/codex-residue.js +18 -22
- package/dist/core/codex-residue.js.map +1 -1
- package/dist/core/command-generation/adapters/claude.d.ts +2 -9
- package/dist/core/command-generation/adapters/claude.d.ts.map +1 -1
- package/dist/core/command-generation/adapters/claude.js +2 -12
- package/dist/core/command-generation/adapters/claude.js.map +1 -1
- package/dist/core/command-generation/adapters/index.d.ts +1 -9
- package/dist/core/command-generation/adapters/index.d.ts.map +1 -1
- package/dist/core/command-generation/adapters/index.js +1 -9
- package/dist/core/command-generation/adapters/index.js.map +1 -1
- package/dist/core/command-generation/generator.d.ts +0 -17
- package/dist/core/command-generation/generator.d.ts.map +1 -1
- package/dist/core/command-generation/generator.js +0 -17
- package/dist/core/command-generation/generator.js.map +1 -1
- package/dist/core/command-generation/index.d.ts +2 -5
- package/dist/core/command-generation/index.d.ts.map +1 -1
- package/dist/core/command-generation/index.js +0 -9
- package/dist/core/command-generation/index.js.map +1 -1
- package/dist/core/command-generation/types.d.ts +10 -36
- package/dist/core/command-generation/types.d.ts.map +1 -1
- package/dist/core/command-generation/types.js +0 -6
- package/dist/core/command-generation/types.js.map +1 -1
- package/dist/core/command-generation/yaml.d.ts +3 -18
- package/dist/core/command-generation/yaml.d.ts.map +1 -1
- package/dist/core/command-generation/yaml.js +5 -23
- package/dist/core/command-generation/yaml.js.map +1 -1
- package/dist/core/config-prompts.d.ts +2 -4
- package/dist/core/config-prompts.d.ts.map +1 -1
- package/dist/core/config-prompts.js +2 -7
- package/dist/core/config-prompts.js.map +1 -1
- package/dist/core/config-schema.d.ts +7 -41
- package/dist/core/config-schema.d.ts.map +1 -1
- package/dist/core/config-schema.js +35 -74
- package/dist/core/config-schema.js.map +1 -1
- package/dist/core/config.d.ts +25 -49
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +22 -45
- package/dist/core/config.js.map +1 -1
- package/dist/core/dashboard-activity.d.ts +7 -9
- package/dist/core/dashboard-activity.d.ts.map +1 -1
- package/dist/core/dashboard-activity.js +26 -24
- package/dist/core/dashboard-activity.js.map +1 -1
- package/dist/core/dashboard-data.d.ts +35 -22
- package/dist/core/dashboard-data.d.ts.map +1 -1
- package/dist/core/dashboard-data.js +57 -72
- package/dist/core/dashboard-data.js.map +1 -1
- package/dist/core/global-config.d.ts +24 -53
- package/dist/core/global-config.d.ts.map +1 -1
- package/dist/core/global-config.js +38 -67
- package/dist/core/global-config.js.map +1 -1
- package/dist/core/init.d.ts +12 -28
- package/dist/core/init.d.ts.map +1 -1
- package/dist/core/init.js +90 -168
- package/dist/core/init.js.map +1 -1
- package/dist/core/list.d.ts.map +1 -1
- package/dist/core/list.js +80 -38
- package/dist/core/list.js.map +1 -1
- package/dist/core/local-server.d.ts +41 -83
- package/dist/core/local-server.d.ts.map +1 -1
- package/dist/core/local-server.js +53 -98
- package/dist/core/local-server.js.map +1 -1
- package/dist/core/markdown-render.d.ts +15 -23
- package/dist/core/markdown-render.d.ts.map +1 -1
- package/dist/core/markdown-render.js +25 -34
- package/dist/core/markdown-render.js.map +1 -1
- package/dist/core/migrate.d.ts +19 -16
- package/dist/core/migrate.d.ts.map +1 -1
- package/dist/core/migrate.js +151 -135
- package/dist/core/migrate.js.map +1 -1
- package/dist/core/parsers/change-parser.d.ts +7 -10
- package/dist/core/parsers/change-parser.d.ts.map +1 -1
- package/dist/core/parsers/change-parser.js +48 -56
- package/dist/core/parsers/change-parser.js.map +1 -1
- package/dist/core/parsers/markdown-parser.d.ts +8 -9
- package/dist/core/parsers/markdown-parser.d.ts.map +1 -1
- package/dist/core/parsers/markdown-parser.js +23 -30
- package/dist/core/parsers/markdown-parser.js.map +1 -1
- package/dist/core/parsers/requirement-blocks.d.ts +43 -15
- package/dist/core/parsers/requirement-blocks.d.ts.map +1 -1
- package/dist/core/parsers/requirement-blocks.js +142 -70
- package/dist/core/parsers/requirement-blocks.js.map +1 -1
- package/dist/core/parsers/requirement-text.d.ts +73 -79
- package/dist/core/parsers/requirement-text.d.ts.map +1 -1
- package/dist/core/parsers/requirement-text.js +137 -79
- package/dist/core/parsers/requirement-text.js.map +1 -1
- package/dist/core/parsers/spec-structure.d.ts.map +1 -1
- package/dist/core/parsers/spec-structure.js +10 -6
- package/dist/core/parsers/spec-structure.js.map +1 -1
- package/dist/core/profiles.d.ts +3 -10
- package/dist/core/profiles.d.ts.map +1 -1
- package/dist/core/profiles.js +5 -12
- package/dist/core/profiles.js.map +1 -1
- package/dist/core/project-config.d.ts +43 -44
- package/dist/core/project-config.d.ts.map +1 -1
- package/dist/core/project-config.js +107 -82
- package/dist/core/project-config.js.map +1 -1
- package/dist/core/project-layout.d.ts +9 -17
- package/dist/core/project-layout.d.ts.map +1 -1
- package/dist/core/project-layout.js +16 -26
- package/dist/core/project-layout.js.map +1 -1
- package/dist/core/root-selection.d.ts +8 -14
- package/dist/core/root-selection.d.ts.map +1 -1
- package/dist/core/root-selection.js +3 -6
- package/dist/core/root-selection.js.map +1 -1
- package/dist/core/rules.d.ts.map +1 -1
- package/dist/core/rules.js +2 -3
- package/dist/core/rules.js.map +1 -1
- package/dist/core/schema-names.d.ts +16 -0
- package/dist/core/schema-names.d.ts.map +1 -0
- package/dist/core/schema-names.js +16 -0
- package/dist/core/schema-names.js.map +1 -0
- package/dist/core/schemas/base.schema.d.ts.map +1 -1
- package/dist/core/schemas/base.schema.js +6 -12
- package/dist/core/schemas/base.schema.js.map +1 -1
- package/dist/core/schemas/change.schema.d.ts +8 -0
- package/dist/core/schemas/change.schema.d.ts.map +1 -1
- package/dist/core/schemas/change.schema.js +41 -10
- package/dist/core/schemas/change.schema.js.map +1 -1
- package/dist/core/shared/index.d.ts +2 -7
- package/dist/core/shared/index.d.ts.map +1 -1
- package/dist/core/shared/index.js +2 -7
- package/dist/core/shared/index.js.map +1 -1
- package/dist/core/shared/rules-generation.d.ts +5 -15
- package/dist/core/shared/rules-generation.d.ts.map +1 -1
- package/dist/core/shared/rules-generation.js +33 -37
- package/dist/core/shared/rules-generation.js.map +1 -1
- package/dist/core/shared/skill-generation.d.ts +28 -43
- package/dist/core/shared/skill-generation.d.ts.map +1 -1
- package/dist/core/shared/skill-generation.js +82 -51
- package/dist/core/shared/skill-generation.js.map +1 -1
- package/dist/core/shared/tool-detection.d.ts +35 -76
- package/dist/core/shared/tool-detection.d.ts.map +1 -1
- package/dist/core/shared/tool-detection.js +73 -93
- package/dist/core/shared/tool-detection.js.map +1 -1
- package/dist/core/skill-metrics.d.ts +36 -63
- package/dist/core/skill-metrics.d.ts.map +1 -1
- package/dist/core/skill-metrics.js +34 -73
- package/dist/core/skill-metrics.js.map +1 -1
- package/dist/core/spec-presenter.d.ts.map +1 -1
- package/dist/core/spec-presenter.js +5 -10
- package/dist/core/spec-presenter.js.map +1 -1
- package/dist/core/specs-apply.d.ts +16 -31
- package/dist/core/specs-apply.d.ts.map +1 -1
- package/dist/core/specs-apply.js +146 -195
- package/dist/core/specs-apply.js.map +1 -1
- package/dist/core/templates/fragments/interview.d.ts +2 -6
- package/dist/core/templates/fragments/interview.d.ts.map +1 -1
- package/dist/core/templates/fragments/interview.js +2 -6
- package/dist/core/templates/fragments/interview.js.map +1 -1
- package/dist/core/templates/fragments/next-step.d.ts +4 -8
- package/dist/core/templates/fragments/next-step.d.ts.map +1 -1
- package/dist/core/templates/fragments/next-step.js +4 -8
- package/dist/core/templates/fragments/next-step.js.map +1 -1
- package/dist/core/templates/fragments/validate.d.ts +13 -0
- package/dist/core/templates/fragments/validate.d.ts.map +1 -0
- package/dist/core/templates/fragments/validate.js +13 -0
- package/dist/core/templates/fragments/validate.js.map +1 -0
- package/dist/core/templates/fragments/verify.d.ts +9 -12
- package/dist/core/templates/fragments/verify.d.ts.map +1 -1
- package/dist/core/templates/fragments/verify.js +9 -12
- package/dist/core/templates/fragments/verify.js.map +1 -1
- package/dist/core/templates/index.d.ts +0 -6
- package/dist/core/templates/index.d.ts.map +1 -1
- package/dist/core/templates/index.js +0 -7
- package/dist/core/templates/index.js.map +1 -1
- package/dist/core/templates/skill-templates.d.ts +1 -5
- package/dist/core/templates/skill-templates.d.ts.map +1 -1
- package/dist/core/templates/skill-templates.js +0 -5
- package/dist/core/templates/skill-templates.js.map +1 -1
- package/dist/core/templates/types.d.ts +3 -7
- package/dist/core/templates/types.d.ts.map +1 -1
- package/dist/core/templates/types.js +0 -3
- package/dist/core/templates/types.js.map +1 -1
- package/dist/core/templates/workflows/apply.d.ts +3 -9
- package/dist/core/templates/workflows/apply.d.ts.map +1 -1
- package/dist/core/templates/workflows/apply.js +11 -13
- package/dist/core/templates/workflows/apply.js.map +1 -1
- package/dist/core/templates/workflows/archive.d.ts +0 -6
- package/dist/core/templates/workflows/archive.d.ts.map +1 -1
- package/dist/core/templates/workflows/archive.js +16 -5
- package/dist/core/templates/workflows/archive.js.map +1 -1
- package/dist/core/templates/workflows/decision.js +3 -3
- package/dist/core/templates/workflows/decision.js.map +1 -1
- package/dist/core/templates/workflows/explore.js +1 -1
- package/dist/core/templates/workflows/grill.d.ts.map +1 -1
- package/dist/core/templates/workflows/grill.js +0 -2
- package/dist/core/templates/workflows/grill.js.map +1 -1
- package/dist/core/templates/workflows/issue.d.ts +0 -6
- package/dist/core/templates/workflows/issue.d.ts.map +1 -1
- package/dist/core/templates/workflows/issue.js +3 -2
- package/dist/core/templates/workflows/issue.js.map +1 -1
- package/dist/core/templates/workflows/propose.d.ts +0 -6
- package/dist/core/templates/workflows/propose.d.ts.map +1 -1
- package/dist/core/templates/workflows/propose.js +2 -2
- package/dist/core/templates/workflows/propose.js.map +1 -1
- package/dist/core/templates/workflows/sync.d.ts +2 -8
- package/dist/core/templates/workflows/sync.d.ts.map +1 -1
- package/dist/core/templates/workflows/sync.js +4 -3
- package/dist/core/templates/workflows/sync.js.map +1 -1
- package/dist/core/templates/workflows/update.d.ts +0 -6
- package/dist/core/templates/workflows/update.d.ts.map +1 -1
- package/dist/core/templates/workflows/update.js +9 -2
- package/dist/core/templates/workflows/update.js.map +1 -1
- package/dist/core/update.d.ts +10 -36
- package/dist/core/update.d.ts.map +1 -1
- package/dist/core/update.js +59 -126
- package/dist/core/update.js.map +1 -1
- package/dist/core/user-state-migration.d.ts +13 -15
- package/dist/core/user-state-migration.d.ts.map +1 -1
- package/dist/core/user-state-migration.js +16 -20
- package/dist/core/user-state-migration.js.map +1 -1
- package/dist/core/validation/constants.d.ts +4 -10
- package/dist/core/validation/constants.d.ts.map +1 -1
- package/dist/core/validation/constants.js +25 -25
- package/dist/core/validation/constants.js.map +1 -1
- package/dist/core/validation/prose-length.d.ts +15 -0
- package/dist/core/validation/prose-length.d.ts.map +1 -0
- package/dist/core/validation/prose-length.js +29 -0
- package/dist/core/validation/prose-length.js.map +1 -0
- package/dist/core/validation/purpose-placeholder.d.ts +9 -16
- package/dist/core/validation/purpose-placeholder.d.ts.map +1 -1
- package/dist/core/validation/purpose-placeholder.js +30 -44
- package/dist/core/validation/purpose-placeholder.js.map +1 -1
- package/dist/core/validation/section-validator.d.ts +4 -4
- package/dist/core/validation/section-validator.d.ts.map +1 -1
- package/dist/core/validation/section-validator.js +30 -12
- package/dist/core/validation/section-validator.js.map +1 -1
- package/dist/core/validation/task-numbering.d.ts +6 -3
- package/dist/core/validation/task-numbering.d.ts.map +1 -1
- package/dist/core/validation/task-numbering.js +23 -11
- package/dist/core/validation/task-numbering.js.map +1 -1
- package/dist/core/validation/types.d.ts +18 -0
- package/dist/core/validation/types.d.ts.map +1 -1
- package/dist/core/validation/types.js +12 -1
- package/dist/core/validation/types.js.map +1 -1
- package/dist/core/validation/validator.d.ts +42 -68
- package/dist/core/validation/validator.d.ts.map +1 -1
- package/dist/core/validation/validator.js +468 -285
- package/dist/core/validation/validator.js.map +1 -1
- package/dist/prompts/searchable-multi-select.d.ts +3 -8
- package/dist/prompts/searchable-multi-select.d.ts.map +1 -1
- package/dist/prompts/searchable-multi-select.js +16 -39
- package/dist/prompts/searchable-multi-select.js.map +1 -1
- package/dist/utils/change-metadata.d.ts +11 -50
- package/dist/utils/change-metadata.d.ts.map +1 -1
- package/dist/utils/change-metadata.js +48 -67
- package/dist/utils/change-metadata.js.map +1 -1
- package/dist/utils/change-utils.d.ts +24 -76
- package/dist/utils/change-utils.d.ts.map +1 -1
- package/dist/utils/change-utils.js +95 -142
- package/dist/utils/change-utils.js.map +1 -1
- package/dist/utils/file-lock.d.ts +39 -0
- package/dist/utils/file-lock.d.ts.map +1 -0
- package/dist/utils/file-lock.js +149 -0
- package/dist/utils/file-lock.js.map +1 -0
- package/dist/utils/file-system.d.ts +12 -32
- package/dist/utils/file-system.d.ts.map +1 -1
- package/dist/utils/file-system.js +16 -40
- package/dist/utils/file-system.js.map +1 -1
- package/dist/utils/frontmatter.d.ts +7 -11
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +11 -11
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/interactive.d.ts +4 -9
- package/dist/utils/interactive.d.ts.map +1 -1
- package/dist/utils/interactive.js +2 -4
- package/dist/utils/interactive.js.map +1 -1
- package/dist/utils/item-discovery.d.ts +10 -20
- package/dist/utils/item-discovery.d.ts.map +1 -1
- package/dist/utils/item-discovery.js +31 -55
- package/dist/utils/item-discovery.js.map +1 -1
- package/dist/utils/link.d.ts +9 -18
- package/dist/utils/link.d.ts.map +1 -1
- package/dist/utils/link.js +9 -18
- package/dist/utils/link.js.map +1 -1
- package/dist/utils/requirement-diff.d.ts +13 -23
- package/dist/utils/requirement-diff.d.ts.map +1 -1
- package/dist/utils/requirement-diff.js +13 -23
- package/dist/utils/requirement-diff.js.map +1 -1
- package/dist/utils/spec-files.d.ts +7 -20
- package/dist/utils/spec-files.d.ts.map +1 -1
- package/dist/utils/spec-files.js +26 -51
- package/dist/utils/spec-files.js.map +1 -1
- package/dist/utils/task-progress.d.ts +11 -9
- package/dist/utils/task-progress.d.ts.map +1 -1
- package/dist/utils/task-progress.js +53 -32
- package/dist/utils/task-progress.js.map +1 -1
- package/dist/utils/timestamp.d.ts +5 -8
- package/dist/utils/timestamp.d.ts.map +1 -1
- package/dist/utils/timestamp.js +5 -8
- package/dist/utils/timestamp.js.map +1 -1
- package/package.json +2 -3
- package/schemas/issue/schema.yaml +8 -1
- package/schemas/issue/templates/spec.md +20 -3
- package/schemas/sdd/schema.yaml +20 -1
- package/schemas/sdd/templates/spec.md +20 -3
|
@@ -1,123 +1,118 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared, fence-aware requirement-reading helpers
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* (`Validator.extractRequirementText` / `countScenarios`) — and the two drifted
|
|
7
|
-
* apart. These helpers are the single source of truth for requirement-body
|
|
8
|
-
* extraction, scenario counting, and `SHALL`/`MUST` detection in
|
|
9
|
-
* `validate <change>`, `validate <spec>`, and `archive`.
|
|
2
|
+
* Shared, fence-aware requirement-reading helpers: the single source of truth
|
|
3
|
+
* for requirement-body extraction, scenario counting and `SHALL`/`MUST`
|
|
4
|
+
* detection in `validate <change>`, `validate <spec>` and `archive`. These were
|
|
5
|
+
* once implemented twice — main specs and change deltas — and drifted apart.
|
|
10
6
|
*/
|
|
11
7
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* The BOM matters because every pattern in this file is anchored with `^`. A
|
|
16
|
-
* BOM-prefixed file — the default from several Windows editors and from
|
|
17
|
-
* PowerShell's `Out-File` — turns its first line into
|
|
18
|
-
* `<BOM>## ADDED Requirements`, so the section scan matches nothing and the
|
|
19
|
-
* user is told "No delta sections found", a message that points nowhere near
|
|
20
|
-
* the cause. Only a *leading* BOM is stripped; U+FEFF anywhere else is content.
|
|
8
|
+
* Strip a leading UTF-8 BOM, then collapse CRLF/CR to LF, before any line-based
|
|
9
|
+
* reading.
|
|
21
10
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
11
|
+
* Every pattern in this file is anchored with `^`, so a BOM turns the first line
|
|
12
|
+
* into `<BOM>## ADDED Requirements`, the section scan matches nothing, and the
|
|
13
|
+
* user is told "No delta sections found". Only a *leading* BOM is stripped;
|
|
14
|
+
* U+FEFF anywhere else is content.
|
|
25
15
|
*/
|
|
26
16
|
export declare function normalizeDocument(content: string): string;
|
|
27
17
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* opening length, with nothing but whitespace after it.
|
|
18
|
+
* Strip a leading UTF-8 BOM, leaving line endings untouched \u2014 for readers that
|
|
19
|
+
* write the file back and so must preserve its endings, which rules out
|
|
20
|
+
* `normalizeDocument`. Writing the stripped text back is deliberate: every
|
|
21
|
+
* document tospec produces is UTF-8 *without* a BOM.
|
|
33
22
|
*/
|
|
23
|
+
export declare function stripBom(content: string): string;
|
|
34
24
|
export interface CodeFenceScan {
|
|
25
|
+
/** True for every line inside a fenced code block, fence lines included. */
|
|
35
26
|
mask: boolean[];
|
|
36
27
|
/** 1-based line of a fence that was opened but never closed, else null. */
|
|
37
28
|
unclosedFenceLine: number | null;
|
|
38
29
|
}
|
|
39
30
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
31
|
+
* Mask the lines inside fenced code blocks, mirroring markdown's own rules: a
|
|
32
|
+
* fence opens on a ```` ``` ````/`~~~` run of length >= 3 and closes on the same
|
|
33
|
+
* marker at >= the opening length with nothing but whitespace after it.
|
|
34
|
+
*
|
|
35
|
+
* An unclosed fence masks every following line, silently hiding the rest of the
|
|
36
|
+
* document, so it is reported separately for the validation path to raise.
|
|
44
37
|
*/
|
|
45
38
|
export declare function scanCodeFences(lines: string[]): CodeFenceScan;
|
|
46
39
|
export declare function buildCodeFenceMask(lines: string[]): boolean[];
|
|
47
40
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* paths stay in parity.
|
|
52
|
-
*
|
|
53
|
-
* Exported because archive's scenario-drift check reads scenarios too. It used
|
|
54
|
-
* to carry its own copy of this pattern, and the copies were not actually the
|
|
55
|
-
* same — parity between the two readers has to hold by construction, not by two
|
|
56
|
-
* literals that happen to agree.
|
|
41
|
+
* Only `#### Scenario:` counts as a scenario — a `#### Notes` or other level-4
|
|
42
|
+
* header under a requirement does not. Exported so archive's scenario-drift
|
|
43
|
+
* check shares it: it once carried its own, subtly different copy.
|
|
57
44
|
*/
|
|
58
45
|
export declare const SCENARIO_HEADER: RegExp;
|
|
59
46
|
/**
|
|
60
47
|
* The scenario name from a `#### Scenario:` header line, or null when the line
|
|
61
|
-
* is not one. The single place the name is peeled off
|
|
62
|
-
* reader normalizes it identically.
|
|
48
|
+
* is not one. The single place the name is peeled off, so every reader agrees.
|
|
63
49
|
*/
|
|
64
50
|
export declare function scenarioNameFrom(line: string): string | null;
|
|
65
51
|
/**
|
|
66
|
-
* The one predicate for normative-keyword detection
|
|
67
|
-
*
|
|
68
|
-
* and reject identical text.
|
|
52
|
+
* The one predicate for normative-keyword detection, matching whole words so the
|
|
53
|
+
* delta reader and the schema reader accept and reject identical text.
|
|
69
54
|
*/
|
|
70
55
|
export declare function containsShallOrMust(text: string): boolean;
|
|
71
56
|
/**
|
|
72
|
-
* Extract the full requirement body from the lines
|
|
73
|
-
* `### Requirement:` header
|
|
57
|
+
* Extract the full requirement body from the lines following a
|
|
58
|
+
* `### Requirement:` header, up to the first header on a non-fenced line —
|
|
59
|
+
* usually the first `#### Scenario:`, but also a stray `###` divider the delta
|
|
60
|
+
* reader absorbed into the block.
|
|
74
61
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* when other body text remains: a requirement written entirely as
|
|
80
|
-
* `**Constraint**: The system MUST ...` keeps that line as its body. Captured
|
|
81
|
-
* lines are trimmed and joined with newlines so a requirement whose text wraps
|
|
82
|
-
* across lines — or whose `SHALL`/`MUST` lands on a later line — is read in
|
|
83
|
-
* full.
|
|
62
|
+
* `**metadata**:` lines are skipped only when other body text remains, so a
|
|
63
|
+
* requirement written entirely as `**Constraint**: The system MUST ...` keeps
|
|
64
|
+
* that line as its body. Lines are joined with newlines so text that wraps — or
|
|
65
|
+
* whose `SHALL`/`MUST` lands on a later line — is read in full.
|
|
84
66
|
*/
|
|
85
67
|
export declare function extractRequirementBody(bodyLines: string[]): string;
|
|
86
68
|
/**
|
|
87
|
-
* Parser/display fallback for a requirement block with no body text
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* a keyword that appears only in the header still receives the body-keyword
|
|
92
|
-
* hint.
|
|
69
|
+
* Parser/display fallback for a requirement block with no body text, so a bare
|
|
70
|
+
* `### The system SHALL ...` header stays readable on the spec path. Validator
|
|
71
|
+
* body-keyword checks call `extractRequirementBody` directly instead, so a
|
|
72
|
+
* keyword that appears only in the header still gets the body-keyword hint.
|
|
93
73
|
*/
|
|
94
74
|
export declare function extractRequirementText(headerTitle: string, bodyLines: string[]): string;
|
|
95
|
-
/**
|
|
96
|
-
* Count the real scenarios in a requirement block: `#### ` headers on non-fenced
|
|
97
|
-
* lines. A `#### Scenario:` that lives inside a fenced example is not a real
|
|
98
|
-
* scenario and is not counted.
|
|
99
|
-
*/
|
|
75
|
+
/** Count real scenarios: a `#### Scenario:` inside a fenced example is not one. */
|
|
100
76
|
export declare function countScenarios(bodyLines: string[]): number;
|
|
101
77
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* Duplicates are kept — `findMissingScenarios` counts multiplicity.
|
|
78
|
+
* Scenario names in document order. Duplicates are kept — `findMissingScenarios`
|
|
79
|
+
* counts multiplicity.
|
|
105
80
|
*/
|
|
106
81
|
export declare function scenarioNamesOf(requirementRaw: string): string[];
|
|
107
82
|
/**
|
|
108
83
|
* Scenarios present in the current requirement that an incoming MODIFIED block
|
|
109
84
|
* would drop. A MODIFIED replaces the whole requirement, so anything it omits
|
|
110
|
-
* is deleted
|
|
111
|
-
*
|
|
85
|
+
* is deleted. Shared by `specs-apply` (archive) and the validator so validate
|
|
86
|
+
* reports exactly what archive refuses.
|
|
112
87
|
*
|
|
113
88
|
* Multiplicity-aware: a name present N times in current and M times in incoming
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* Shared by `specs-apply` (archive) and the validator so the two cannot drift:
|
|
118
|
-
* validate must report exactly what archive refuses, no more and no less.
|
|
89
|
+
* leaves max(0, N - M) missing. Set membership would treat N > M as fully
|
|
90
|
+
* covered and let a duplicate be dropped silently.
|
|
119
91
|
*/
|
|
120
92
|
export declare function findMissingScenarios(currentRaw: string, incomingRaw: string): string[];
|
|
93
|
+
/**
|
|
94
|
+
* A requirement block with the named scenarios cut out, header and body. Takes
|
|
95
|
+
* declared removals out of the "current" side before comparing: a scenario
|
|
96
|
+
* under `## REMOVED Scenarios` is going on purpose, so its bullets are not a
|
|
97
|
+
* loss to warn about.
|
|
98
|
+
*
|
|
99
|
+
* A scenario runs from its `#### Scenario:` header to the next header of any
|
|
100
|
+
* level — the boundary every other scenario reader here uses.
|
|
101
|
+
*/
|
|
102
|
+
export declare function withoutScenarios(requirementRaw: string, names: readonly string[]): string;
|
|
103
|
+
/**
|
|
104
|
+
* Bullet lines the current requirement has that an incoming MODIFIED drops —
|
|
105
|
+
* the quieter half of the scenario-name check above: a block that restates every
|
|
106
|
+
* scenario *name* correctly but carries older wording inside them.
|
|
107
|
+
*
|
|
108
|
+
* Bullets and nothing else, on purpose. WHEN/THEN/AND bullets are the grammar's
|
|
109
|
+
* atomic units and each lives on one line, so a dropped bullet is a real loss.
|
|
110
|
+
* Prose bodies are not compared: re-flowing a paragraph changes every line
|
|
111
|
+
* without changing a word.
|
|
112
|
+
*
|
|
113
|
+
* Multiplicity-aware for the same reason as `findMissingScenarios`.
|
|
114
|
+
*/
|
|
115
|
+
export declare function findDroppedBullets(currentRaw: string, incomingRaw: string): string[];
|
|
121
116
|
export interface ScenarioAnalysis {
|
|
122
117
|
scenarios: Array<{
|
|
123
118
|
title: string;
|
|
@@ -133,10 +128,9 @@ export interface ScenarioAnalysis {
|
|
|
133
128
|
}>;
|
|
134
129
|
}
|
|
135
130
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* scenarios at all. Fence-aware like the other readers.
|
|
131
|
+
* Which `####` headers are real scenarios, whether each scenario body contains
|
|
132
|
+
* the uppercase WHEN and THEN keywords, and which level-4 headers are not
|
|
133
|
+
* scenarios at all.
|
|
140
134
|
*/
|
|
141
135
|
export declare function analyzeScenarios(lines: string[]): ScenarioAnalysis;
|
|
142
136
|
//# sourceMappingURL=requirement-text.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirement-text.d.ts","sourceRoot":"","sources":["../../../src/core/parsers/requirement-text.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"requirement-text.d.ts","sourceRoot":"","sources":["../../../src/core/parsers/requirement-text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,2EAA2E;IAC3E,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,aAAa,CAsB7D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAE7D;AAgCD;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAAuB,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG5D;AAKD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAoBlE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAEvF;AAED,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ1D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CAUhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBtF;AAKD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAoBzF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BpF;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,KAAK,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,mEAAmE;QACnE,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC,CAAC;IACH,yEAAyE;IACzE,kBAAkB,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,gBAAgB,CA+BlE"}
|
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared, fence-aware requirement-reading helpers
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* (`Validator.extractRequirementText` / `countScenarios`) — and the two drifted
|
|
7
|
-
* apart. These helpers are the single source of truth for requirement-body
|
|
8
|
-
* extraction, scenario counting, and `SHALL`/`MUST` detection in
|
|
9
|
-
* `validate <change>`, `validate <spec>`, and `archive`.
|
|
2
|
+
* Shared, fence-aware requirement-reading helpers: the single source of truth
|
|
3
|
+
* for requirement-body extraction, scenario counting and `SHALL`/`MUST`
|
|
4
|
+
* detection in `validate <change>`, `validate <spec>` and `archive`. These were
|
|
5
|
+
* once implemented twice — main specs and change deltas — and drifted apart.
|
|
10
6
|
*/
|
|
11
7
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* The BOM matters because every pattern in this file is anchored with `^`. A
|
|
16
|
-
* BOM-prefixed file — the default from several Windows editors and from
|
|
17
|
-
* PowerShell's `Out-File` — turns its first line into
|
|
18
|
-
* `<BOM>## ADDED Requirements`, so the section scan matches nothing and the
|
|
19
|
-
* user is told "No delta sections found", a message that points nowhere near
|
|
20
|
-
* the cause. Only a *leading* BOM is stripped; U+FEFF anywhere else is content.
|
|
8
|
+
* Strip a leading UTF-8 BOM, then collapse CRLF/CR to LF, before any line-based
|
|
9
|
+
* reading.
|
|
21
10
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
11
|
+
* Every pattern in this file is anchored with `^`, so a BOM turns the first line
|
|
12
|
+
* into `<BOM>## ADDED Requirements`, the section scan matches nothing, and the
|
|
13
|
+
* user is told "No delta sections found". Only a *leading* BOM is stripped;
|
|
14
|
+
* U+FEFF anywhere else is content.
|
|
25
15
|
*/
|
|
26
16
|
export function normalizeDocument(content) {
|
|
27
|
-
return content
|
|
17
|
+
return stripBom(content).replace(/\r\n?/g, '\n');
|
|
28
18
|
}
|
|
29
19
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
20
|
+
* Strip a leading UTF-8 BOM, leaving line endings untouched \u2014 for readers that
|
|
21
|
+
* write the file back and so must preserve its endings, which rules out
|
|
22
|
+
* `normalizeDocument`. Writing the stripped text back is deliberate: every
|
|
23
|
+
* document tospec produces is UTF-8 *without* a BOM.
|
|
24
|
+
*/
|
|
25
|
+
export function stripBom(content) {
|
|
26
|
+
return content.replace(/^\uFEFF/, '');
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Mask the lines inside fenced code blocks, mirroring markdown's own rules: a
|
|
30
|
+
* fence opens on a ```` ``` ````/`~~~` run of length >= 3 and closes on the same
|
|
31
|
+
* marker at >= the opening length with nothing but whitespace after it.
|
|
32
|
+
*
|
|
33
|
+
* An unclosed fence masks every following line, silently hiding the rest of the
|
|
34
|
+
* document, so it is reported separately for the validation path to raise.
|
|
34
35
|
*/
|
|
35
36
|
export function scanCodeFences(lines) {
|
|
36
37
|
const mask = new Array(lines.length).fill(false);
|
|
@@ -75,21 +76,14 @@ const METADATA_LINE = /^\*\*[^*]+\*\*:/;
|
|
|
75
76
|
/** Any markdown header line — the boundary where a requirement body ends. */
|
|
76
77
|
const HEADER_LINE = /^#{1,6}\s/;
|
|
77
78
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* paths stay in parity.
|
|
82
|
-
*
|
|
83
|
-
* Exported because archive's scenario-drift check reads scenarios too. It used
|
|
84
|
-
* to carry its own copy of this pattern, and the copies were not actually the
|
|
85
|
-
* same — parity between the two readers has to hold by construction, not by two
|
|
86
|
-
* literals that happen to agree.
|
|
79
|
+
* Only `#### Scenario:` counts as a scenario — a `#### Notes` or other level-4
|
|
80
|
+
* header under a requirement does not. Exported so archive's scenario-drift
|
|
81
|
+
* check shares it: it once carried its own, subtly different copy.
|
|
87
82
|
*/
|
|
88
83
|
export const SCENARIO_HEADER = /^####\s+Scenario:/i;
|
|
89
84
|
/**
|
|
90
85
|
* The scenario name from a `#### Scenario:` header line, or null when the line
|
|
91
|
-
* is not one. The single place the name is peeled off
|
|
92
|
-
* reader normalizes it identically.
|
|
86
|
+
* is not one. The single place the name is peeled off, so every reader agrees.
|
|
93
87
|
*/
|
|
94
88
|
export function scenarioNameFrom(line) {
|
|
95
89
|
if (!SCENARIO_HEADER.test(line))
|
|
@@ -99,26 +93,22 @@ export function scenarioNameFrom(line) {
|
|
|
99
93
|
/** Any level-4 header — used to detect non-scenario `####` headers. */
|
|
100
94
|
const ANY_H4_HEADER = /^####\s+/;
|
|
101
95
|
/**
|
|
102
|
-
* The one predicate for normative-keyword detection
|
|
103
|
-
*
|
|
104
|
-
* and reject identical text.
|
|
96
|
+
* The one predicate for normative-keyword detection, matching whole words so the
|
|
97
|
+
* delta reader and the schema reader accept and reject identical text.
|
|
105
98
|
*/
|
|
106
99
|
export function containsShallOrMust(text) {
|
|
107
100
|
return /\b(SHALL|MUST)\b/.test(text);
|
|
108
101
|
}
|
|
109
102
|
/**
|
|
110
|
-
* Extract the full requirement body from the lines
|
|
111
|
-
* `### Requirement:` header
|
|
103
|
+
* Extract the full requirement body from the lines following a
|
|
104
|
+
* `### Requirement:` header, up to the first header on a non-fenced line —
|
|
105
|
+
* usually the first `#### Scenario:`, but also a stray `###` divider the delta
|
|
106
|
+
* reader absorbed into the block.
|
|
112
107
|
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* when other body text remains: a requirement written entirely as
|
|
118
|
-
* `**Constraint**: The system MUST ...` keeps that line as its body. Captured
|
|
119
|
-
* lines are trimmed and joined with newlines so a requirement whose text wraps
|
|
120
|
-
* across lines — or whose `SHALL`/`MUST` lands on a later line — is read in
|
|
121
|
-
* full.
|
|
108
|
+
* `**metadata**:` lines are skipped only when other body text remains, so a
|
|
109
|
+
* requirement written entirely as `**Constraint**: The system MUST ...` keeps
|
|
110
|
+
* that line as its body. Lines are joined with newlines so text that wraps — or
|
|
111
|
+
* whose `SHALL`/`MUST` lands on a later line — is read in full.
|
|
122
112
|
*/
|
|
123
113
|
export function extractRequirementBody(bodyLines) {
|
|
124
114
|
const mask = buildCodeFenceMask(bodyLines);
|
|
@@ -126,15 +116,15 @@ export function extractRequirementBody(bodyLines) {
|
|
|
126
116
|
const metadata = [];
|
|
127
117
|
for (let i = 0; i < bodyLines.length; i++) {
|
|
128
118
|
if (mask[i])
|
|
129
|
-
continue;
|
|
119
|
+
continue;
|
|
130
120
|
const line = bodyLines[i];
|
|
131
121
|
if (HEADER_LINE.test(line))
|
|
132
122
|
break; // first scenario or stray divider
|
|
133
123
|
const trimmed = line.trim();
|
|
134
124
|
if (trimmed.length === 0)
|
|
135
|
-
continue;
|
|
125
|
+
continue;
|
|
136
126
|
if (METADATA_LINE.test(trimmed)) {
|
|
137
|
-
metadata.push(trimmed);
|
|
127
|
+
metadata.push(trimmed);
|
|
138
128
|
continue;
|
|
139
129
|
}
|
|
140
130
|
captured.push(trimmed);
|
|
@@ -144,21 +134,15 @@ export function extractRequirementBody(bodyLines) {
|
|
|
144
134
|
return metadata.join('\n'); // metadata-only body: the metadata IS the body
|
|
145
135
|
}
|
|
146
136
|
/**
|
|
147
|
-
* Parser/display fallback for a requirement block with no body text
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
* a keyword that appears only in the header still receives the body-keyword
|
|
152
|
-
* hint.
|
|
137
|
+
* Parser/display fallback for a requirement block with no body text, so a bare
|
|
138
|
+
* `### The system SHALL ...` header stays readable on the spec path. Validator
|
|
139
|
+
* body-keyword checks call `extractRequirementBody` directly instead, so a
|
|
140
|
+
* keyword that appears only in the header still gets the body-keyword hint.
|
|
153
141
|
*/
|
|
154
142
|
export function extractRequirementText(headerTitle, bodyLines) {
|
|
155
143
|
return extractRequirementBody(bodyLines) || headerTitle.trim();
|
|
156
144
|
}
|
|
157
|
-
/**
|
|
158
|
-
* Count the real scenarios in a requirement block: `#### ` headers on non-fenced
|
|
159
|
-
* lines. A `#### Scenario:` that lives inside a fenced example is not a real
|
|
160
|
-
* scenario and is not counted.
|
|
161
|
-
*/
|
|
145
|
+
/** Count real scenarios: a `#### Scenario:` inside a fenced example is not one. */
|
|
162
146
|
export function countScenarios(bodyLines) {
|
|
163
147
|
const mask = buildCodeFenceMask(bodyLines);
|
|
164
148
|
let count = 0;
|
|
@@ -171,12 +155,11 @@ export function countScenarios(bodyLines) {
|
|
|
171
155
|
return count;
|
|
172
156
|
}
|
|
173
157
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* Duplicates are kept — `findMissingScenarios` counts multiplicity.
|
|
158
|
+
* Scenario names in document order. Duplicates are kept — `findMissingScenarios`
|
|
159
|
+
* counts multiplicity.
|
|
177
160
|
*/
|
|
178
161
|
export function scenarioNamesOf(requirementRaw) {
|
|
179
|
-
const lines = requirementRaw
|
|
162
|
+
const lines = normalizeDocument(requirementRaw).split('\n');
|
|
180
163
|
const mask = buildCodeFenceMask(lines);
|
|
181
164
|
const names = [];
|
|
182
165
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -191,15 +174,12 @@ export function scenarioNamesOf(requirementRaw) {
|
|
|
191
174
|
/**
|
|
192
175
|
* Scenarios present in the current requirement that an incoming MODIFIED block
|
|
193
176
|
* would drop. A MODIFIED replaces the whole requirement, so anything it omits
|
|
194
|
-
* is deleted
|
|
195
|
-
*
|
|
177
|
+
* is deleted. Shared by `specs-apply` (archive) and the validator so validate
|
|
178
|
+
* reports exactly what archive refuses.
|
|
196
179
|
*
|
|
197
180
|
* Multiplicity-aware: a name present N times in current and M times in incoming
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
* Shared by `specs-apply` (archive) and the validator so the two cannot drift:
|
|
202
|
-
* validate must report exactly what archive refuses, no more and no less.
|
|
181
|
+
* leaves max(0, N - M) missing. Set membership would treat N > M as fully
|
|
182
|
+
* covered and let a duplicate be dropped silently.
|
|
203
183
|
*/
|
|
204
184
|
export function findMissingScenarios(currentRaw, incomingRaw) {
|
|
205
185
|
const remainingIncoming = new Map();
|
|
@@ -218,11 +198,89 @@ export function findMissingScenarios(currentRaw, incomingRaw) {
|
|
|
218
198
|
}
|
|
219
199
|
return missing;
|
|
220
200
|
}
|
|
201
|
+
/** A `- ...` / `* ...` bullet, with its marker and surrounding space removed. */
|
|
202
|
+
const BULLET_LINE = /^[ \t]*[-*][ \t]+(.+?)[ \t]*$/;
|
|
203
|
+
/**
|
|
204
|
+
* A requirement block with the named scenarios cut out, header and body. Takes
|
|
205
|
+
* declared removals out of the "current" side before comparing: a scenario
|
|
206
|
+
* under `## REMOVED Scenarios` is going on purpose, so its bullets are not a
|
|
207
|
+
* loss to warn about.
|
|
208
|
+
*
|
|
209
|
+
* A scenario runs from its `#### Scenario:` header to the next header of any
|
|
210
|
+
* level — the boundary every other scenario reader here uses.
|
|
211
|
+
*/
|
|
212
|
+
export function withoutScenarios(requirementRaw, names) {
|
|
213
|
+
if (names.length === 0)
|
|
214
|
+
return requirementRaw;
|
|
215
|
+
const wanted = new Set(names.map((name) => name.trim().toLowerCase()));
|
|
216
|
+
const lines = normalizeDocument(requirementRaw).split('\n');
|
|
217
|
+
const mask = buildCodeFenceMask(lines);
|
|
218
|
+
const kept = [];
|
|
219
|
+
let dropping = false;
|
|
220
|
+
for (let i = 0; i < lines.length; i++) {
|
|
221
|
+
if (!mask[i]) {
|
|
222
|
+
const name = scenarioNameFrom(lines[i]);
|
|
223
|
+
if (name !== null) {
|
|
224
|
+
dropping = wanted.has(name.trim().toLowerCase());
|
|
225
|
+
}
|
|
226
|
+
else if (dropping && /^#{1,6}\s/.test(lines[i])) {
|
|
227
|
+
// Any other header ends the scenario being dropped.
|
|
228
|
+
dropping = false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (!dropping)
|
|
232
|
+
kept.push(lines[i]);
|
|
233
|
+
}
|
|
234
|
+
return kept.join('\n');
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Bullet lines the current requirement has that an incoming MODIFIED drops —
|
|
238
|
+
* the quieter half of the scenario-name check above: a block that restates every
|
|
239
|
+
* scenario *name* correctly but carries older wording inside them.
|
|
240
|
+
*
|
|
241
|
+
* Bullets and nothing else, on purpose. WHEN/THEN/AND bullets are the grammar's
|
|
242
|
+
* atomic units and each lives on one line, so a dropped bullet is a real loss.
|
|
243
|
+
* Prose bodies are not compared: re-flowing a paragraph changes every line
|
|
244
|
+
* without changing a word.
|
|
245
|
+
*
|
|
246
|
+
* Multiplicity-aware for the same reason as `findMissingScenarios`.
|
|
247
|
+
*/
|
|
248
|
+
export function findDroppedBullets(currentRaw, incomingRaw) {
|
|
249
|
+
const bulletsOf = (raw) => {
|
|
250
|
+
const lines = normalizeDocument(raw).split('\n');
|
|
251
|
+
const mask = buildCodeFenceMask(lines);
|
|
252
|
+
const bullets = [];
|
|
253
|
+
for (let i = 0; i < lines.length; i++) {
|
|
254
|
+
if (mask[i])
|
|
255
|
+
continue;
|
|
256
|
+
const match = BULLET_LINE.exec(lines[i]);
|
|
257
|
+
// Interior whitespace collapses so a re-indented or re-spaced bullet
|
|
258
|
+
// still matches itself.
|
|
259
|
+
if (match)
|
|
260
|
+
bullets.push(match[1].replace(/\s+/g, ' '));
|
|
261
|
+
}
|
|
262
|
+
return bullets;
|
|
263
|
+
};
|
|
264
|
+
const remainingIncoming = new Map();
|
|
265
|
+
for (const bullet of bulletsOf(incomingRaw)) {
|
|
266
|
+
remainingIncoming.set(bullet, (remainingIncoming.get(bullet) ?? 0) + 1);
|
|
267
|
+
}
|
|
268
|
+
const dropped = [];
|
|
269
|
+
for (const bullet of bulletsOf(currentRaw)) {
|
|
270
|
+
const remaining = remainingIncoming.get(bullet) ?? 0;
|
|
271
|
+
if (remaining > 0) {
|
|
272
|
+
remainingIncoming.set(bullet, remaining - 1);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
dropped.push(bullet);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return dropped;
|
|
279
|
+
}
|
|
221
280
|
/**
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
* scenarios at all. Fence-aware like the other readers.
|
|
281
|
+
* Which `####` headers are real scenarios, whether each scenario body contains
|
|
282
|
+
* the uppercase WHEN and THEN keywords, and which level-4 headers are not
|
|
283
|
+
* scenarios at all.
|
|
226
284
|
*/
|
|
227
285
|
export function analyzeScenarios(lines) {
|
|
228
286
|
const mask = buildCodeFenceMask(lines);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirement-text.js","sourceRoot":"","sources":["../../../src/core/parsers/requirement-text.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"requirement-text.js","sourceRoot":"","sources":["../../../src/core/parsers/requirement-text.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-structure.d.ts","sourceRoot":"","sources":["../../../src/core/parsers/spec-structure.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spec-structure.d.ts","sourceRoot":"","sources":["../../../src/core/parsers/spec-structure.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,cAAc,GAAG,kCAAkC,GAAG,uBAAuB,CAAC;IACpF,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB,EAAE,CAqFrF;AAED,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI5E"}
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import { buildCodeFenceMask } from './requirement-text.js';
|
|
2
|
-
import { normalizeRequirementName } from './requirement-blocks.js';
|
|
1
|
+
import { buildCodeFenceMask, normalizeDocument } from './requirement-text.js';
|
|
2
|
+
import { normalizeRequirementName, REQUIREMENT_HEADER_REGEX } from './requirement-blocks.js';
|
|
3
3
|
const REQUIREMENTS_SECTION_HEADER = /^##\s+Requirements\s*$/i;
|
|
4
4
|
const TOP_LEVEL_SECTION_HEADER = /^##\s+/;
|
|
5
5
|
const DELTA_HEADER = /^##\s+(ADDED|MODIFIED|REMOVED|RENAMED)\s+Requirements\s*$/i;
|
|
6
|
-
|
|
6
|
+
// Shared with the merge, not a local `\s+` copy: this guard exists to report
|
|
7
|
+
// every pair that collides in buildUpdatedSpec's Map, so it must read headers
|
|
8
|
+
// exactly as the merge does — `###Requirement: A` beside `### Requirement: A`
|
|
9
|
+
// passed the stricter copy and then lost one body on archive.
|
|
10
|
+
const REQUIREMENT_HEADER = REQUIREMENT_HEADER_REGEX;
|
|
7
11
|
export function findMainSpecStructureIssues(content) {
|
|
8
|
-
const normalized = content
|
|
12
|
+
const normalized = normalizeDocument(content);
|
|
9
13
|
const stripped = stripFencedCodeBlocksPreservingLines(normalized);
|
|
10
14
|
const lines = stripped.split('\n');
|
|
11
15
|
const issues = [];
|
|
12
|
-
// Keyed the way buildUpdatedSpec keys its blocks
|
|
13
|
-
// in that Map must be reported here, or this guard
|
|
16
|
+
// Keyed the way buildUpdatedSpec keys its blocks: any pair that would collide
|
|
17
|
+
// in that Map must be reported here, or this guard passes a spec the merge
|
|
14
18
|
// still corrupts.
|
|
15
19
|
const firstSeenAt = new Map();
|
|
16
20
|
const requirementsHeaderIndex = lines.findIndex(line => REQUIREMENTS_SECTION_HEADER.test(line));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-structure.js","sourceRoot":"","sources":["../../../src/core/parsers/spec-structure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"spec-structure.js","sourceRoot":"","sources":["../../../src/core/parsers/spec-structure.ts"],"names":[],"mappings":"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"}
|