docassert 0.3.0__tar.gz → 0.4.0__tar.gz

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.
Files changed (108) hide show
  1. {docassert-0.3.0/docassert.egg-info → docassert-0.4.0}/PKG-INFO +6 -2
  2. {docassert-0.3.0 → docassert-0.4.0}/README.md +5 -1
  3. {docassert-0.3.0 → docassert-0.4.0}/docassert/__init__.py +1 -1
  4. docassert-0.4.0/docassert/_data/skills/doc-to-pmo/SKILL.md +100 -0
  5. {docassert-0.3.0 → docassert-0.4.0}/docassert/config.py +16 -6
  6. {docassert-0.3.0 → docassert-0.4.0/docassert.egg-info}/PKG-INFO +6 -2
  7. {docassert-0.3.0 → docassert-0.4.0}/docassert.egg-info/SOURCES.txt +1 -0
  8. {docassert-0.3.0 → docassert-0.4.0}/tests/test_config.py +15 -1
  9. {docassert-0.3.0 → docassert-0.4.0}/LICENSE +0 -0
  10. {docassert-0.3.0 → docassert-0.4.0}/NOTICE +0 -0
  11. {docassert-0.3.0 → docassert-0.4.0}/docassert/__main__.py +0 -0
  12. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/consistency.yaml +0 -0
  13. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/adr.criteria.yaml +0 -0
  14. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/benefits-realization.criteria.yaml +0 -0
  15. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/brd.criteria.yaml +0 -0
  16. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/business-case.criteria.yaml +0 -0
  17. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/charter.criteria.yaml +0 -0
  18. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/data-migration-plan.criteria.yaml +0 -0
  19. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/frnfr.criteria.yaml +0 -0
  20. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/hypercare-plan.criteria.yaml +0 -0
  21. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/post-implementation-review.criteria.yaml +0 -0
  22. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/prd.criteria.yaml +0 -0
  23. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/project.criteria.yaml +0 -0
  24. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/qa-test-plan.criteria.yaml +0 -0
  25. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/raci-stakeholder.criteria.yaml +0 -0
  26. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/release-cutover-plan.criteria.yaml +0 -0
  27. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/risk-register.criteria.yaml +0 -0
  28. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/rollback-plan.criteria.yaml +0 -0
  29. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/runbook.criteria.yaml +0 -0
  30. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/status-report.criteria.yaml +0 -0
  31. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/test-cases.criteria.yaml +0 -0
  32. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/criteria/user-story.criteria.yaml +0 -0
  33. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/profiles/agile-delivery.yaml +0 -0
  34. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/profiles/lean-startup.yaml +0 -0
  35. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/profiles/regulated-industry.yaml +0 -0
  36. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/adr.schema.json +0 -0
  37. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/benefits-realization.schema.json +0 -0
  38. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/brd.schema.json +0 -0
  39. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/business-case.schema.json +0 -0
  40. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/charter.schema.json +0 -0
  41. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/data-migration-plan.schema.json +0 -0
  42. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/frnfr.schema.json +0 -0
  43. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/hypercare-plan.schema.json +0 -0
  44. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/post-implementation-review.schema.json +0 -0
  45. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/prd.schema.json +0 -0
  46. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/project.schema.json +0 -0
  47. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/qa-test-plan.schema.json +0 -0
  48. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/raci-stakeholder.schema.json +0 -0
  49. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/release-cutover-plan.schema.json +0 -0
  50. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/risk-register.schema.json +0 -0
  51. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/rollback-plan.schema.json +0 -0
  52. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/runbook.schema.json +0 -0
  53. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/status-report.schema.json +0 -0
  54. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/test-cases.schema.json +0 -0
  55. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/schema/user-story.schema.json +0 -0
  56. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/adr.template.md +0 -0
  57. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/benefits-realization.template.md +0 -0
  58. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/brd.template.md +0 -0
  59. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/business-case.template.md +0 -0
  60. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/charter.template.md +0 -0
  61. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/data-migration-plan.template.md +0 -0
  62. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/frnfr.template.md +0 -0
  63. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/hypercare-plan.template.md +0 -0
  64. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/post-implementation-review.template.md +0 -0
  65. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/prd.template.md +0 -0
  66. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/project.template.md +0 -0
  67. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/qa-test-plan.template.md +0 -0
  68. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/raci-stakeholder.template.md +0 -0
  69. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/release-cutover-plan.template.md +0 -0
  70. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/risk-register.template.md +0 -0
  71. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/rollback-plan.template.md +0 -0
  72. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/runbook.template.md +0 -0
  73. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/status-report.template.md +0 -0
  74. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/test-cases.template.md +0 -0
  75. {docassert-0.3.0 → docassert-0.4.0}/docassert/_data/templates/user-story.template.md +0 -0
  76. {docassert-0.3.0 → docassert-0.4.0}/docassert/cli.py +0 -0
  77. {docassert-0.3.0 → docassert-0.4.0}/docassert/consistency.py +0 -0
  78. {docassert-0.3.0 → docassert-0.4.0}/docassert/extract.py +0 -0
  79. {docassert-0.3.0 → docassert-0.4.0}/docassert/graph.py +0 -0
  80. {docassert-0.3.0 → docassert-0.4.0}/docassert/loader.py +0 -0
  81. {docassert-0.3.0 → docassert-0.4.0}/docassert/models.py +0 -0
  82. {docassert-0.3.0 → docassert-0.4.0}/docassert/profiles.py +0 -0
  83. {docassert-0.3.0 → docassert-0.4.0}/docassert/projects.py +0 -0
  84. {docassert-0.3.0 → docassert-0.4.0}/docassert/report.py +0 -0
  85. {docassert-0.3.0 → docassert-0.4.0}/docassert/rtm.py +0 -0
  86. {docassert-0.3.0 → docassert-0.4.0}/docassert/scaffold.py +0 -0
  87. {docassert-0.3.0 → docassert-0.4.0}/docassert/semantic.py +0 -0
  88. {docassert-0.3.0 → docassert-0.4.0}/docassert/status.py +0 -0
  89. {docassert-0.3.0 → docassert-0.4.0}/docassert/structural.py +0 -0
  90. {docassert-0.3.0 → docassert-0.4.0}/docassert.egg-info/dependency_links.txt +0 -0
  91. {docassert-0.3.0 → docassert-0.4.0}/docassert.egg-info/entry_points.txt +0 -0
  92. {docassert-0.3.0 → docassert-0.4.0}/docassert.egg-info/requires.txt +0 -0
  93. {docassert-0.3.0 → docassert-0.4.0}/docassert.egg-info/top_level.txt +0 -0
  94. {docassert-0.3.0 → docassert-0.4.0}/pyproject.toml +0 -0
  95. {docassert-0.3.0 → docassert-0.4.0}/setup.cfg +0 -0
  96. {docassert-0.3.0 → docassert-0.4.0}/tests/test_consistency.py +0 -0
  97. {docassert-0.3.0 → docassert-0.4.0}/tests/test_defects.py +0 -0
  98. {docassert-0.3.0 → docassert-0.4.0}/tests/test_extract.py +0 -0
  99. {docassert-0.3.0 → docassert-0.4.0}/tests/test_graph.py +0 -0
  100. {docassert-0.3.0 → docassert-0.4.0}/tests/test_kinds_delivery.py +0 -0
  101. {docassert-0.3.0 → docassert-0.4.0}/tests/test_kinds_governance.py +0 -0
  102. {docassert-0.3.0 → docassert-0.4.0}/tests/test_kinds_operate.py +0 -0
  103. {docassert-0.3.0 → docassert-0.4.0}/tests/test_kinds_reporting.py +0 -0
  104. {docassert-0.3.0 → docassert-0.4.0}/tests/test_profiles.py +0 -0
  105. {docassert-0.3.0 → docassert-0.4.0}/tests/test_projects.py +0 -0
  106. {docassert-0.3.0 → docassert-0.4.0}/tests/test_scaffold.py +0 -0
  107. {docassert-0.3.0 → docassert-0.4.0}/tests/test_status.py +0 -0
  108. {docassert-0.3.0 → docassert-0.4.0}/tests/test_structural.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docassert
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: Unit testing for business documents — validate structured Markdown docs against a configurable audit standard.
5
5
  Author: C4G Enterprises Inc.
6
6
  License: Apache-2.0
@@ -75,7 +75,11 @@ docassert pages --out _site # a portfolio dashboard + a page per proje
75
75
  Config resolves **local override → packaged default**: docassert ships sensible
76
76
  defaults, and your repo's own `criteria/` (or `schema/`, `profiles/`,
77
77
  `consistency.yaml`) wins when present. `docassert init` copies the defaults in so
78
- you can customize them.
78
+ you can customize them — including the **doc-to-pmo Claude skill** into
79
+ `.claude/skills/`, so Claude Code in your repo knows how to convert existing
80
+ Word/PDF documents into testable docassert documents (faithfully — gaps are
81
+ flagged as TODOs, never invented). The skill's source is
82
+ [`skills/doc-to-pmo/SKILL.md`](skills/doc-to-pmo/SKILL.md).
79
83
 
80
84
  ## Commands
81
85
 
@@ -37,7 +37,11 @@ docassert pages --out _site # a portfolio dashboard + a page per proje
37
37
  Config resolves **local override → packaged default**: docassert ships sensible
38
38
  defaults, and your repo's own `criteria/` (or `schema/`, `profiles/`,
39
39
  `consistency.yaml`) wins when present. `docassert init` copies the defaults in so
40
- you can customize them.
40
+ you can customize them — including the **doc-to-pmo Claude skill** into
41
+ `.claude/skills/`, so Claude Code in your repo knows how to convert existing
42
+ Word/PDF documents into testable docassert documents (faithfully — gaps are
43
+ flagged as TODOs, never invented). The skill's source is
44
+ [`skills/doc-to-pmo/SKILL.md`](skills/doc-to-pmo/SKILL.md).
41
45
 
42
46
  ## Commands
43
47
 
@@ -5,4 +5,4 @@ standard: deterministic structural checks that gate a merge, plus optional
5
5
  AI-graded semantic checks that advise.
6
6
  """
7
7
 
8
- __version__ = "0.3.0"
8
+ __version__ = "0.4.0"
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: doc-to-pmo
3
+ description: Convert an existing business document (Word .docx, PDF, or pasted text) into a docassert Markdown document so it can be unit-tested and gated in CI. Use when someone wants to bring an existing charter, BRD, PRD, risk register, or any other supported kind into a PMO-as-Code repo.
4
+ ---
5
+
6
+ # doc-to-pmo
7
+
8
+ Convert a source document into a standard docassert document. **Map the content
9
+ faithfully — never invent missing facts to make the audit pass.** A document
10
+ that lacks measurable success criteria *should* fail the audit; your job is to
11
+ surface that, not hide it.
12
+
13
+ Requires docassert (`pipx install docassert`; add `"docassert[convert]"` for
14
+ .docx/.pdf extraction).
15
+
16
+ ## Steps
17
+
18
+ 1. **Identify the kind.** Supported kinds: `charter`, `business-case`, `brd`,
19
+ `prd`, `frnfr`, `user-story`, `test-cases`, `adr`, `risk-register`,
20
+ `raci-stakeholder`, `qa-test-plan`, `data-migration-plan`,
21
+ `release-cutover-plan`, `rollback-plan`, `hypercare-plan`, `runbook`,
22
+ `status-report`, `post-implementation-review`, `benefits-realization`.
23
+ One source file may yield several documents (a "BRD" is often really a
24
+ BRD + PRD + NFRs + risks). Propose the split to the user before writing.
25
+
26
+ 2. **Anchor the project.** Every document belongs to a project
27
+ (`PRJ-NNN-CODE`). Check `projects.yaml` or `documents/` for an existing
28
+ anchor; if there is none, create one (ask the user for the code, name, and
29
+ sponsor — don't guess):
30
+
31
+ ```bash
32
+ docassert new project --code AUR --name "Aurora — Customer Onboarding"
33
+ ```
34
+
35
+ 3. **Extract the source text** (`.docx`, `.pdf`, `.md`, `.txt`):
36
+
37
+ ```bash
38
+ docassert extract path/to/source.docx
39
+ ```
40
+
41
+ For pasted text or Google Docs, ask the user to paste the content or export
42
+ to `.docx`/`.pdf` first.
43
+
44
+ 4. **Scaffold, then fill.** Let docassert create the file with the identity
45
+ (frontmatter `project:`, namespaced `id:`) already correct, then map the
46
+ source content into its sections:
47
+
48
+ ```bash
49
+ docassert new brd --project PRJ-001-AUR
50
+ # docassert: created documents/PRJ-001-AUR/brd.md
51
+ # docassert: next item id: AUR-BR-001
52
+ ```
53
+
54
+ Keep `status: draft` unless the source clearly states an approval.
55
+
56
+ 5. **Author traceable items where the kind defines them.** Requirements,
57
+ criteria, tests, risks, and decisions are bullets with a stable namespaced
58
+ id and typed links — use the `next item id` hints for numbering:
59
+
60
+ ```
61
+ - **AUR-BR-001**: The business shall reduce onboarding time to under 2 days.
62
+ - **AUR-PR-001** (traces: AUR-BR-001): The product shall provide a self-serve flow.
63
+ - **AUR-RISK-001** (threatens: AUR-BR-001): Migration may slip. Probability: High.
64
+ Impact: High. Owner: alex.kim. Response: dual-run for two weeks.
65
+ ```
66
+
67
+ Relations: `traces` (child → parent requirement), `verifies` (AC → PR/FR),
68
+ `tests` (TC → AC), `threatens` (RISK → BR/PR), `affects` (ADR → FR/NFR).
69
+ Only link items that genuinely relate in the source.
70
+
71
+ 6. **Flag gaps honestly.** Wherever the source does not supply required
72
+ information, insert a bullet or note beginning with `TODO:` describing what
73
+ is missing (e.g. `- TODO: no measurable success criteria found in the
74
+ source — add a metric and threshold.`). Do **not** fabricate a number, an
75
+ owner, a date, or a mitigation.
76
+
77
+ 7. **Validate and report.**
78
+
79
+ ```bash
80
+ docassert validate documents/PRJ-001-AUR/*.md
81
+ docassert consistency
82
+ ```
83
+
84
+ Summarise what passed, what blocks, and exactly which TODOs the user must
85
+ resolve before the document can merge.
86
+
87
+ 8. **Hand off.** Tell the user to review the generated files, resolve the
88
+ TODOs, then commit and open a pull request — CI re-runs the same audit and
89
+ gates the merge.
90
+
91
+ ## Guardrails
92
+
93
+ - **Faithful over passing**: it is correct and expected for a weak source to
94
+ produce a document that fails the audit. That is the pipeline working.
95
+ - Never invent approvals, owners, budgets, dates, or measurable thresholds.
96
+ - Never mark a document `approved`; that is a human decision made in review.
97
+ - If you are unsure whether something in the source is a real measurable
98
+ criterion, leave it as written and let the audit judge it.
99
+ - Confidential sources stay local: don't push converted content to a public
100
+ repo without the user's say-so.
@@ -101,22 +101,32 @@ def available_profiles() -> list[str]:
101
101
 
102
102
 
103
103
  # ── scaffolding (docassert init) ────────────────────────────────────────────
104
- _INIT_TREE = ["criteria", "schema", "profiles", "templates", "consistency.yaml"]
104
+ # (packaged source, destination in the repo). The doc-to-pmo Claude skill lands
105
+ # under .claude/skills/ so Claude Code discovers it in the user's repo.
106
+ _INIT_TREE = [
107
+ ("criteria", "criteria"),
108
+ ("schema", "schema"),
109
+ ("profiles", "profiles"),
110
+ ("templates", "templates"),
111
+ ("consistency.yaml", "consistency.yaml"),
112
+ ("skills", ".claude/skills"),
113
+ ]
105
114
 
106
115
 
107
116
  def init(dest: str | Path = ".") -> list[str]:
108
117
  """Copy the packaged defaults into `dest`, skipping anything already present.
109
- Returns the top-level names that were created."""
118
+ Returns the destination names that were created."""
110
119
  dest = Path(dest)
111
120
  created: list[str] = []
112
- for name in _INIT_TREE:
113
- target = dest / name
121
+ for src_name, dest_name in _INIT_TREE:
122
+ target = dest / dest_name
114
123
  if target.exists():
115
124
  continue
116
- src = DATA_DIR / name
125
+ src = DATA_DIR / src_name
117
126
  if src.is_dir():
118
127
  shutil.copytree(src, target)
119
128
  else:
129
+ target.parent.mkdir(parents=True, exist_ok=True)
120
130
  target.write_text(src.read_text(encoding="utf-8"), encoding="utf-8")
121
- created.append(name)
131
+ created.append(dest_name)
122
132
  return created
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docassert
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: Unit testing for business documents — validate structured Markdown docs against a configurable audit standard.
5
5
  Author: C4G Enterprises Inc.
6
6
  License: Apache-2.0
@@ -75,7 +75,11 @@ docassert pages --out _site # a portfolio dashboard + a page per proje
75
75
  Config resolves **local override → packaged default**: docassert ships sensible
76
76
  defaults, and your repo's own `criteria/` (or `schema/`, `profiles/`,
77
77
  `consistency.yaml`) wins when present. `docassert init` copies the defaults in so
78
- you can customize them.
78
+ you can customize them — including the **doc-to-pmo Claude skill** into
79
+ `.claude/skills/`, so Claude Code in your repo knows how to convert existing
80
+ Word/PDF documents into testable docassert documents (faithfully — gaps are
81
+ flagged as TODOs, never invented). The skill's source is
82
+ [`skills/doc-to-pmo/SKILL.md`](skills/doc-to-pmo/SKILL.md).
79
83
 
80
84
  ## Commands
81
85
 
@@ -69,6 +69,7 @@ docassert/_data/schema/runbook.schema.json
69
69
  docassert/_data/schema/status-report.schema.json
70
70
  docassert/_data/schema/test-cases.schema.json
71
71
  docassert/_data/schema/user-story.schema.json
72
+ docassert/_data/skills/doc-to-pmo/SKILL.md
72
73
  docassert/_data/templates/adr.template.md
73
74
  docassert/_data/templates/benefits-realization.template.md
74
75
  docassert/_data/templates/brd.template.md
@@ -23,6 +23,9 @@ def test_packaged_data_mirrors_root_config():
23
23
  f"{name}/{fn} drifted between the repo root and packaged _data"
24
24
  assert filecmp.cmp(ROOT / "consistency.yaml",
25
25
  config.DATA_DIR / "consistency.yaml", shallow=False)
26
+ assert filecmp.cmp(ROOT / "skills" / "doc-to-pmo" / "SKILL.md",
27
+ config.DATA_DIR / "skills" / "doc-to-pmo" / "SKILL.md",
28
+ shallow=False), "doc-to-pmo skill drifted between root and packaged copy"
26
29
 
27
30
 
28
31
  # ── resolution: packaged default when there's no local config ───────────────
@@ -52,8 +55,19 @@ def test_unknown_kind_raises(monkeypatch, tmp_path):
52
55
  # ── init scaffolds, and is idempotent ──────────────────────────────────────
53
56
  def test_init_scaffolds_defaults(tmp_path):
54
57
  created = config.init(tmp_path)
55
- assert set(created) == {"criteria", "schema", "profiles", "templates", "consistency.yaml"}
58
+ assert set(created) == {"criteria", "schema", "profiles", "templates",
59
+ "consistency.yaml", ".claude/skills"}
56
60
  assert (tmp_path / "criteria" / "charter.criteria.yaml").is_file()
57
61
  assert (tmp_path / "schema" / "project.schema.json").is_file()
58
62
  assert (tmp_path / "consistency.yaml").is_file()
63
+ assert (tmp_path / ".claude" / "skills" / "doc-to-pmo" / "SKILL.md").is_file()
59
64
  assert config.init(tmp_path) == [] # second run creates nothing
65
+
66
+
67
+ def test_init_keeps_existing_skills(tmp_path):
68
+ mine = tmp_path / ".claude" / "skills"
69
+ mine.mkdir(parents=True)
70
+ (mine / "my-skill.md").write_text("mine", encoding="utf-8")
71
+ created = config.init(tmp_path)
72
+ assert ".claude/skills" not in created # existing dir left alone
73
+ assert (mine / "my-skill.md").read_text() == "mine"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes