specsmith 0.2.1.dev42__tar.gz → 0.2.2.dev44__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 (102) hide show
  1. {specsmith-0.2.1.dev42/src/specsmith.egg-info → specsmith-0.2.2.dev44}/PKG-INFO +1 -1
  2. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/pyproject.toml +1 -1
  3. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/__init__.py +1 -1
  4. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/cli.py +14 -3
  5. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/scaffolder.py +1 -1
  6. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/upgrader.py +132 -24
  7. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44/src/specsmith.egg-info}/PKG-INFO +1 -1
  8. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith.egg-info/SOURCES.txt +1 -1
  9. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/LICENSE +0 -0
  10. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/README.md +0 -0
  11. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/setup.cfg +0 -0
  12. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/__main__.py +0 -0
  13. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/architect.py +0 -0
  14. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/auditor.py +0 -0
  15. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/commands/__init__.py +0 -0
  16. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/compressor.py +0 -0
  17. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/config.py +0 -0
  18. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/credit_analyzer.py +0 -0
  19. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/credits.py +0 -0
  20. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/differ.py +0 -0
  21. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/doctor.py +0 -0
  22. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/executor.py +0 -0
  23. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/exporter.py +0 -0
  24. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/importer.py +0 -0
  25. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/integrations/__init__.py +0 -0
  26. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/integrations/aider.py +0 -0
  27. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/integrations/base.py +0 -0
  28. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/integrations/claude_code.py +0 -0
  29. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/integrations/copilot.py +0 -0
  30. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/integrations/cursor.py +0 -0
  31. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/integrations/gemini.py +0 -0
  32. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/integrations/warp.py +0 -0
  33. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/integrations/windsurf.py +0 -0
  34. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/ledger.py +0 -0
  35. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/plugins.py +0 -0
  36. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/releaser.py +0 -0
  37. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/requirements.py +0 -0
  38. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/session.py +0 -0
  39. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/agents.md.j2 +0 -0
  40. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
  41. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
  42. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/community/contributing.md.j2 +0 -0
  43. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
  44. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
  45. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/community/license-MIT.j2 +0 -0
  46. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
  47. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/community/security.md.j2 +0 -0
  48. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
  49. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
  50. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
  51. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
  52. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
  53. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/docs/workflow.md.j2 +0 -0
  54. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/editorconfig.j2 +0 -0
  55. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/gitattributes.j2 +0 -0
  56. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/gitignore.j2 +0 -0
  57. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/go/go.mod.j2 +0 -0
  58. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/go/main.go.j2 +0 -0
  59. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
  60. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
  61. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/governance/roles.md.j2 +0 -0
  62. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/governance/rules.md.j2 +0 -0
  63. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/governance/verification.md.j2 +0 -0
  64. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/governance/workflow.md.j2 +0 -0
  65. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/js/package.json.j2 +0 -0
  66. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/ledger.md.j2 +0 -0
  67. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/python/cli.py.j2 +0 -0
  68. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/python/init.py.j2 +0 -0
  69. {specsmith-0.2.1.dev42/src/specsmith/templates → specsmith-0.2.2.dev44/src/specsmith/templates/python}/pyproject.toml.j2 +0 -0
  70. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/readme.md.j2 +0 -0
  71. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
  72. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/rust/main.rs.j2 +0 -0
  73. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
  74. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
  75. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
  76. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
  77. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
  78. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
  79. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
  80. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/tools.py +0 -0
  81. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/updater.py +0 -0
  82. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/validator.py +0 -0
  83. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/vcs/__init__.py +0 -0
  84. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/vcs/base.py +0 -0
  85. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/vcs/bitbucket.py +0 -0
  86. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/vcs/github.py +0 -0
  87. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/vcs/gitlab.py +0 -0
  88. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith/vcs_commands.py +0 -0
  89. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith.egg-info/dependency_links.txt +0 -0
  90. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith.egg-info/entry_points.txt +0 -0
  91. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith.egg-info/requires.txt +0 -0
  92. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/src/specsmith.egg-info/top_level.txt +0 -0
  93. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/tests/test_auditor.py +0 -0
  94. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/tests/test_cli.py +0 -0
  95. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/tests/test_compressor.py +0 -0
  96. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/tests/test_importer.py +0 -0
  97. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/tests/test_integrations.py +0 -0
  98. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/tests/test_scaffolder.py +0 -0
  99. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/tests/test_smoke.py +0 -0
  100. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/tests/test_tools.py +0 -0
  101. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/tests/test_validator.py +0 -0
  102. {specsmith-0.2.1.dev42 → specsmith-0.2.2.dev44}/tests/test_vcs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.2.1.dev42
3
+ Version: 0.2.2.dev44
4
4
  Summary: Forge governed project scaffolds from the Agentic AI Development Workflow Specification.
5
5
  Author: BitConcepts
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "specsmith"
7
- version = "0.2.1.dev42"
7
+ version = "0.2.2.dev44"
8
8
  description = "Forge governed project scaffolds from the Agentic AI Development Workflow Specification."
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -8,4 +8,4 @@ from importlib.metadata import version as _pkg_version
8
8
  try:
9
9
  __version__: str = _pkg_version("specsmith")
10
10
  except PackageNotFoundError: # running from source without install
11
- __version__ = "0.2.0"
11
+ __version__ = "0.2.1"
@@ -291,12 +291,23 @@ def compress(project_dir: str, threshold: int, keep_recent: int) -> None:
291
291
  default=".",
292
292
  help="Project root directory.",
293
293
  )
294
- def upgrade(spec_version: str | None, project_dir: str) -> None:
295
- """Update governance files to match a newer spec version."""
294
+ @click.option(
295
+ "--full",
296
+ is_flag=True,
297
+ default=False,
298
+ help="Full sync: also regenerate exec shims, CI, agent files, create missing community files.",
299
+ )
300
+ def upgrade(spec_version: str | None, project_dir: str, full: bool) -> None:
301
+ """Update governance files to match a newer spec version.
302
+
303
+ With --full: also regenerates exec shims (PID tracking), CI configs,
304
+ agent integrations, and creates missing community files. Safe: never
305
+ overwrites AGENTS.md, LEDGER.md, or user documentation.
306
+ """
296
307
  from specsmith.upgrader import run_upgrade
297
308
 
298
309
  root = Path(project_dir).resolve()
299
- result = run_upgrade(root, target_version=spec_version)
310
+ result = run_upgrade(root, target_version=spec_version, full=full)
300
311
  console.print(result.message)
301
312
 
302
313
  if result.updated_files:
@@ -144,7 +144,7 @@ def _build_file_map(config: ProjectConfig) -> list[tuple[str, str]]:
144
144
  ProjectType.BACKEND_FRONTEND,
145
145
  ProjectType.BACKEND_FRONTEND_TRAY,
146
146
  ):
147
- files.append(("pyproject.toml.j2", "pyproject.toml"))
147
+ files.append(("python/pyproject.toml.j2", "pyproject.toml"))
148
148
  files.append(("python/init.py.j2", f"src/{config.package_name}/__init__.py"))
149
149
  if config.type == ProjectType.CLI_PYTHON:
150
150
  files.append(("python/cli.py.j2", f"src/{config.package_name}/cli.py"))
@@ -47,16 +47,42 @@ _LEGACY_RENAMES: list[tuple[str, str]] = [
47
47
  ]
48
48
 
49
49
 
50
+ def _get_env_and_ctx(
51
+ config: ProjectConfig,
52
+ ) -> tuple[Environment, dict[str, object]]:
53
+ """Create Jinja env and template context from config."""
54
+ from specsmith.tools import get_tools
55
+
56
+ env = Environment(
57
+ loader=PackageLoader("specsmith", "templates"),
58
+ autoescape=select_autoescape([]),
59
+ keep_trailing_newline=True,
60
+ trim_blocks=True,
61
+ lstrip_blocks=True,
62
+ )
63
+ ctx: dict[str, object] = {
64
+ "project": config,
65
+ "today": date.today().isoformat(),
66
+ "package_name": config.package_name,
67
+ "tools": get_tools(config),
68
+ }
69
+ return env, ctx
70
+
71
+
50
72
  def run_upgrade(
51
73
  root: Path,
52
74
  *,
53
75
  target_version: str | None = None,
76
+ full: bool = False,
54
77
  ) -> UpgradeResult:
55
78
  """Upgrade governance files to a newer spec version.
56
79
 
57
80
  Args:
58
81
  root: Project root directory.
59
82
  target_version: Target spec version. If None, uses the current specsmith version.
83
+ full: If True, also regenerate exec shims, agent integrations, CI configs,
84
+ and create missing community/RTD files. Safe: never overwrites
85
+ AGENTS.md, LEDGER.md, REQUIREMENTS.md, TEST_SPEC.md, or user docs.
60
86
 
61
87
  Returns:
62
88
  UpgradeResult with details of the operation.
@@ -79,41 +105,22 @@ def run_upgrade(
79
105
  new_version = target_version or __version__
80
106
  old_version = config.spec_version
81
107
 
82
- if old_version == new_version:
108
+ # For --full, allow syncing even when version matches
109
+ if old_version == new_version and not full:
83
110
  return UpgradeResult(message=f"Already at spec version {new_version}. Nothing to upgrade.")
84
111
 
85
- # Update config
86
112
  config.spec_version = new_version
87
-
88
- env = Environment(
89
- loader=PackageLoader("specsmith", "templates"),
90
- autoescape=select_autoescape([]),
91
- keep_trailing_newline=True,
92
- trim_blocks=True,
93
- lstrip_blocks=True,
94
- )
95
-
96
- from specsmith.tools import get_tools
97
-
98
- ctx = {
99
- "project": config,
100
- "today": date.today().isoformat(),
101
- "package_name": config.package_name,
102
- "tools": get_tools(config),
103
- }
113
+ env, ctx = _get_env_and_ctx(config)
104
114
 
105
115
  result = UpgradeResult()
106
116
 
107
117
  # Migrate legacy lowercase filenames to uppercase
108
118
  _migrate_legacy_filenames(root, result)
109
119
 
120
+ # Regenerate governance templates (always overwritten — they're spec-managed)
110
121
  for template_name, output_rel in _GOVERNANCE_TEMPLATES:
111
122
  output_path = root / output_rel
112
-
113
- if not output_path.exists():
114
- result.skipped_files.append(output_rel)
115
- continue
116
-
123
+ output_path.parent.mkdir(parents=True, exist_ok=True)
117
124
  tmpl = env.get_template(template_name)
118
125
  content = tmpl.render(**ctx)
119
126
  output_path.write_text(content, encoding="utf-8")
@@ -133,6 +140,10 @@ def run_upgrade(
133
140
  save_budget(root, CreditBudget())
134
141
  result.updated_files.append(".specsmith/credit-budget.json")
135
142
 
143
+ # Full sync: regenerate shims, CI, agent files, create missing community files
144
+ if full:
145
+ result.updated_files.extend(_sync_full(root, config, env, ctx))
146
+
136
147
  result.message = (
137
148
  f"Upgraded from {old_version} to {new_version}. "
138
149
  f"{len(result.updated_files)} files updated, {len(result.skipped_files)} skipped."
@@ -141,6 +152,103 @@ def run_upgrade(
141
152
  return result
142
153
 
143
154
 
155
+ # Files that are NEVER overwritten by --full sync (user-owned content)
156
+ _USER_OWNED: set[str] = {
157
+ "AGENTS.md",
158
+ "LEDGER.md",
159
+ "README.md",
160
+ "docs/REQUIREMENTS.md",
161
+ "docs/TEST_SPEC.md",
162
+ "docs/ARCHITECTURE.md",
163
+ "docs/WORKFLOW.md",
164
+ }
165
+
166
+
167
+ def _sync_full(
168
+ root: Path,
169
+ config: ProjectConfig,
170
+ env: Environment,
171
+ ctx: dict[str, object],
172
+ ) -> list[str]:
173
+ """Full sync: regenerate infrastructure files, create missing community files.
174
+
175
+ Safe rules:
176
+ - User-owned docs (AGENTS.md, LEDGER.md, etc.) are NEVER touched
177
+ - Exec shims are ALWAYS regenerated (they carry security/abort logic)
178
+ - CI configs are regenerated (tool-aware, reflects current specsmith version)
179
+ - Agent integrations are regenerated
180
+ - Community/RTD files are created only if missing
181
+ """
182
+ synced: list[str] = []
183
+
184
+ from specsmith.scaffolder import _build_community_files
185
+
186
+ # 1. Exec shims — always regenerate (carries PID tracking / abort fixes)
187
+ shim_templates = [
188
+ ("scripts/exec.cmd.j2", "scripts/exec.cmd"),
189
+ ("scripts/exec.sh.j2", "scripts/exec.sh"),
190
+ ("scripts/setup.cmd.j2", "scripts/setup.cmd"),
191
+ ("scripts/setup.sh.j2", "scripts/setup.sh"),
192
+ ("scripts/run.cmd.j2", "scripts/run.cmd"),
193
+ ("scripts/run.sh.j2", "scripts/run.sh"),
194
+ ]
195
+ for tmpl_name, output_rel in shim_templates:
196
+ out = root / output_rel
197
+ out.parent.mkdir(parents=True, exist_ok=True)
198
+ tmpl = env.get_template(tmpl_name)
199
+ out.write_text(tmpl.render(**ctx), encoding="utf-8")
200
+ synced.append(output_rel)
201
+
202
+ # 2. Agent integrations — regenerate
203
+ for integration_name in config.integrations:
204
+ if integration_name == "agents-md":
205
+ continue
206
+ try:
207
+ from specsmith.integrations import get_adapter
208
+
209
+ adapter = get_adapter(integration_name)
210
+ files = adapter.generate(config, root)
211
+ for f in files:
212
+ synced.append(str(f.relative_to(root)))
213
+ except ValueError:
214
+ pass
215
+
216
+ # 3. VCS CI configs — regenerate
217
+ if config.vcs_platform:
218
+ try:
219
+ from specsmith.vcs import get_platform
220
+
221
+ platform = get_platform(config.vcs_platform)
222
+ files = platform.generate_all(config, root)
223
+ for f in files:
224
+ synced.append(str(f.relative_to(root)))
225
+ except ValueError:
226
+ pass
227
+
228
+ # 4. Community files — create only if missing
229
+ for tmpl_name, output_rel in _build_community_files(config):
230
+ out = root / output_rel
231
+ if not out.exists():
232
+ out.parent.mkdir(parents=True, exist_ok=True)
233
+ tmpl = env.get_template(tmpl_name)
234
+ out.write_text(tmpl.render(**ctx), encoding="utf-8")
235
+ synced.append(f"{output_rel} (created)")
236
+
237
+ # 5. Config files — create only if missing (.editorconfig, .gitattributes)
238
+ config_templates = [
239
+ ("editorconfig.j2", ".editorconfig"),
240
+ ("gitattributes.j2", ".gitattributes"),
241
+ ]
242
+ for tmpl_name, output_rel in config_templates:
243
+ out = root / output_rel
244
+ if not out.exists():
245
+ tmpl = env.get_template(tmpl_name)
246
+ out.write_text(tmpl.render(**ctx), encoding="utf-8")
247
+ synced.append(f"{output_rel} (created)")
248
+
249
+ return synced
250
+
251
+
144
252
  def _migrate_legacy_filenames(root: Path, result: UpgradeResult) -> None:
145
253
  """Rename legacy lowercase governance files to uppercase.
146
254
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.2.1.dev42
3
+ Version: 0.2.2.dev44
4
4
  Summary: Forge governed project scaffolds from the Agentic AI Development Workflow Specification.
5
5
  Author: BitConcepts
6
6
  License: MIT
@@ -47,7 +47,6 @@ src/specsmith/templates/editorconfig.j2
47
47
  src/specsmith/templates/gitattributes.j2
48
48
  src/specsmith/templates/gitignore.j2
49
49
  src/specsmith/templates/ledger.md.j2
50
- src/specsmith/templates/pyproject.toml.j2
51
50
  src/specsmith/templates/readme.md.j2
52
51
  src/specsmith/templates/community/bug_report.md.j2
53
52
  src/specsmith/templates/community/code_of_conduct.md.j2
@@ -74,6 +73,7 @@ src/specsmith/templates/governance/workflow.md.j2
74
73
  src/specsmith/templates/js/package.json.j2
75
74
  src/specsmith/templates/python/cli.py.j2
76
75
  src/specsmith/templates/python/init.py.j2
76
+ src/specsmith/templates/python/pyproject.toml.j2
77
77
  src/specsmith/templates/rust/Cargo.toml.j2
78
78
  src/specsmith/templates/rust/main.rs.j2
79
79
  src/specsmith/templates/scripts/exec.cmd.j2
File without changes