faf-python-sdk 1.3.0__py3-none-any.whl → 1.4.0__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: faf-python-sdk
3
- Version: 1.3.0
3
+ Version: 1.4.0
4
4
  Summary: Persistent project context for Python — parse, validate, and score `.faf` files. The foundation other Python FAF tools (gemini-faf-mcp, custom MCP servers, CI validators) build on. IANA-registered application/vnd.faf+yaml.
5
5
  Project-URL: Homepage, https://faf.one
6
6
  Project-URL: Documentation, https://github.com/Wolfe-Jam/faf-python-sdk
@@ -41,25 +41,27 @@ The foundation other Python FAF tools build on. If you're building MCP servers,
41
41
  [![FAF](https://mcpaas.live/badge/Wolfe-Jam/faf-python-sdk.svg)](https://builder.faf.one)
42
42
  [![PyPI](https://img.shields.io/pypi/v/faf-python-sdk?style=for-the-badge&logo=pypi&logoColor=white)](https://pypi.org/project/faf-python-sdk/)
43
43
  [![Downloads](https://img.shields.io/pypi/dm/faf-python-sdk?style=for-the-badge&color=blue)](https://pypi.org/project/faf-python-sdk/)
44
- [![Tests](https://img.shields.io/badge/tests-213%20passing-brightgreen?style=for-the-badge)](https://github.com/Wolfe-Jam/faf-python-sdk)
44
+ [![Tests](https://img.shields.io/badge/tests-216%20passing-brightgreen?style=for-the-badge)](https://github.com/Wolfe-Jam/faf-python-sdk)
45
45
  [![IANA](https://img.shields.io/badge/IANA-registered-informational?style=for-the-badge)](https://www.iana.org/assignments/media-types/application/vnd.faf+yaml)
46
46
 
47
47
  **Media Type:** `application/vnd.faf+yaml` (IANA registered)
48
48
 
49
- ## What's New in v1.3.0 — The Interop Edition
49
+ ## What's New in v1.4.0 — The Interop Edition
50
50
 
51
- The SDK can now author AI-context files, not just parse and score them.
51
+ The interop functions get their real names: `author_agents_md` / `author_gemini_md` are public, `render_*` is the impl, `generate_*` is deprecated (removed in 2.0).
52
52
 
53
- `faf_sdk.interop` — `generate_agents_md(faf)` and `generate_gemini_md(faf)`, Python ports of faf-cli's `src/interop/agents.ts` + `gemini.ts`, in parity with the canonical TypeScript. Deterministic BETTER-shaped projection: setup (install→build→dev ordered) · tests · layout · conventions · three-tier guardrails · definition of done · security · commit · stack. Human Context (who/why marketing) is intentionally omitted from AGENTS.md — it belongs in the README / .faf DNA, not agent ops.
53
+ Output is byte-identical — a naming change, not a behaviour change. Existing `from faf_sdk import generate_agents_md` keeps working, now with a `DeprecationWarning`.
54
+
55
+ `faf_sdk.interop` — `author_agents_md(faf)` and `author_gemini_md(faf)`, Python ports of faf-cli's `src/interop/agents.ts` + `gemini.ts`, in parity with the canonical TypeScript. Deterministic BETTER-shaped projection: setup (install→build→dev ordered) · tests · layout · conventions · three-tier guardrails · definition of done · security · commit · stack. Human Context (who/why marketing) is intentionally omitted from AGENTS.md — it belongs in the README / .faf DNA, not agent ops.
54
56
 
55
57
  ```python
56
- from faf_sdk import parse_file, generate_agents_md
58
+ from faf_sdk import parse_file, author_agents_md
57
59
 
58
60
  faf = parse_file("project.faf")
59
- print(generate_agents_md(faf.data.raw)) # takes the raw dict — carries top-level commands / key_files / security
61
+ print(author_agents_md(faf.data.raw)) # takes the raw dict — carries top-level commands / key_files / security
60
62
  ```
61
63
 
62
- Any Python FAF tool that authors an AI-context file wraps this now — never hand-roll a Markdown generator. `gemini-faf-mcp` 2.7.0's `faf_agents` / `faf_gemini` are the reference wrappers.
64
+ Any Python FAF tool that authors an AI-context file wraps this now — never hand-roll one. `gemini-faf-mcp` 2.7.0's `faf_agents` / `faf_gemini` are the reference wrappers.
63
65
 
64
66
  ## What's New in v1.2.0 — The Dart Edition
65
67
 
@@ -1,14 +1,14 @@
1
- faf_sdk/__init__.py,sha256=1ARRF6IEkjcvf0zJwqWQF30TjTGtgrzWi8O3YwigASc,1842
1
+ faf_sdk/__init__.py,sha256=D7XMrdOQ2LwwBVErSosZrnMCbGLppBrTT1f9BcR8dsY,2020
2
2
  faf_sdk/dart_detection.json,sha256=jFtKnyyMVVFsunizteFZ2pLhYC1qC2nCIWQB9SdOqKE,1195
3
3
  faf_sdk/detect.py,sha256=GothQNKChKSEwke74MRy63VyBYLqOzN1j3yzjsSVpJA,6310
4
4
  faf_sdk/discovery.py,sha256=3Jj3lSzPAj9l0_VjJneLAwo1dMXvhneFhcVN4m2ejOw,8643
5
- faf_sdk/interop.py,sha256=fgIm13pLZIxSrjJiq7ZXXvR5ViWezuGUxhzCbsz_eZQ,13465
5
+ faf_sdk/interop.py,sha256=GWGjBEMAYhoDs7lUpZ6sqtE-I5qCcSwQ2QYLJcjXgvA,14776
6
6
  faf_sdk/mk4.py,sha256=dA8o3YB0W19Mt_bqcR67HAw4S08zxj6IzEmubTy-pQY,5708
7
7
  faf_sdk/parser.py,sha256=lJJysj52X0Q_aGhl4PMXY2PuMqASFHdVRiSZFDdampk,4925
8
8
  faf_sdk/types.py,sha256=sm1ezSzCc-93bszr4ite31_xZRKjwqf2utlqN6_0QuM,6615
9
9
  faf_sdk/validator.py,sha256=6uneOwar4GYUF52BnAQTu159kE4mh4RWRgG6onVbiG4,5730
10
10
  faf_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- faf_python_sdk-1.3.0.dist-info/METADATA,sha256=L_RFAhO35YJ9RRSGyl5M8IIdFBU6rndw5bnKmUJmBpk,8784
12
- faf_python_sdk-1.3.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
13
- faf_python_sdk-1.3.0.dist-info/licenses/LICENSE,sha256=ARScF5tFhbQnYO2V5QAuCwhDHcxKdOWTOV81Pxx_j7U,1065
14
- faf_python_sdk-1.3.0.dist-info/RECORD,,
11
+ faf_python_sdk-1.4.0.dist-info/METADATA,sha256=n7nME8V10mhLGXYYvt7lVeEp21V_CMpOAzAbcBT3X6M,9021
12
+ faf_python_sdk-1.4.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
13
+ faf_python_sdk-1.4.0.dist-info/licenses/LICENSE,sha256=ARScF5tFhbQnYO2V5QAuCwhDHcxKdOWTOV81Pxx_j7U,1065
14
+ faf_python_sdk-1.4.0.dist-info/RECORD,,
faf_sdk/__init__.py CHANGED
@@ -25,7 +25,15 @@ from .validator import validate, ValidationResult
25
25
  from .mk4 import score_faf, Mk4Result, SlotState, LicenseTier
26
26
  from .discovery import find_faf_file, find_project_root, load_fafignore
27
27
  from .detect import detect_dart_project, DartProject
28
- from .interop import generate_agents_md, generate_gemini_md, faf_meta_tag
28
+ from .interop import (
29
+ author_agents_md,
30
+ author_gemini_md,
31
+ render_agents_md,
32
+ render_gemini_md,
33
+ generate_agents_md, # deprecated alias — removed in 2.0
34
+ generate_gemini_md, # deprecated alias — removed in 2.0
35
+ faf_meta_tag,
36
+ )
29
37
  from .types import (
30
38
  FafData,
31
39
  ProjectInfo,
@@ -36,7 +44,7 @@ from .types import (
36
44
  AIScoring
37
45
  )
38
46
 
39
- __version__ = "1.3.0"
47
+ __version__ = "1.4.0"
40
48
  __all__ = [
41
49
  # Parser
42
50
  "parse",
@@ -58,9 +66,9 @@ __all__ = [
58
66
  # Detection (Dart/Flutter — A+B hybrid, parity with faf-cli)
59
67
  "detect_dart_project",
60
68
  "DartProject",
61
- # Interop — AGENTS.md / GEMINI.md generators (parity with faf-cli src/interop)
62
- "generate_agents_md",
63
- "generate_gemini_md",
69
+ # Interop — AGENTS.md / GEMINI.md authoring (parity with faf-cli src/interop)
70
+ "author_agents_md",
71
+ "author_gemini_md",
64
72
  "faf_meta_tag",
65
73
  # Types
66
74
  "FafData",
faf_sdk/interop.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- AI-context file generators — AGENTS.md and GEMINI.md from .faf data.
2
+ AI-context file authoring — AGENTS.md and GEMINI.md from .faf data.
3
3
 
4
4
  Python port of faf-cli's `src/interop/agents.ts` + `gemini.ts`, kept in
5
5
  parity with the canonical TypeScript. Deterministic projection from curated
@@ -10,13 +10,23 @@ not agent ops.
10
10
  Both take the raw parsed .faf dict (`FafFile.data.raw`) — the .faf format
11
11
  carries top-level `commands` / `key_files` / `security` that the typed model
12
12
  doesn't surface.
13
+
14
+ Naming: the impl functions are ``render_agents_md`` / ``render_gemini_md``
15
+ (pure ``dict -> str`` projection, pairs with the writers). The public API
16
+ name is ``author_agents_md`` / ``author_gemini_md`` — the surface consumers
17
+ import, in the "faf authors" voice used on every documented surface.
18
+ ``generate_*`` is a deprecated alias, removed in 2.0.
13
19
  """
14
20
 
15
21
  from __future__ import annotations
16
22
 
23
+ import warnings
17
24
  from typing import Any
18
25
 
19
- __all__ = ["generate_agents_md", "generate_gemini_md", "faf_meta_tag", "title_label", "slot_label"]
26
+ __all__ = [
27
+ "author_agents_md", "author_gemini_md",
28
+ "faf_meta_tag", "title_label", "slot_label",
29
+ ]
20
30
 
21
31
  # --- shared helpers ----------------------------------------------------------
22
32
 
@@ -90,7 +100,7 @@ def slot_label(path: str) -> str:
90
100
 
91
101
 
92
102
  def faf_meta_tag(faf: dict) -> str:
93
- """The two-line `<!-- faf: ... -->` metastamp every faf-generated file opens with."""
103
+ """The two-line `<!-- faf: ... -->` metastamp every faf-authored file opens with."""
94
104
  proj = faf.get("project") or {}
95
105
  name = str(proj.get("name") or "").strip()
96
106
  lang = str(proj.get("main_language") or "").strip()
@@ -102,7 +112,7 @@ def faf_meta_tag(faf: dict) -> str:
102
112
  return f"{line1}\n{line2}"
103
113
 
104
114
 
105
- # --- command classification (shared by both generators) ---------------------
115
+ # --- command classification (shared by both) --------------------------------
106
116
 
107
117
  def _classify_commands(faf: dict) -> dict:
108
118
  commands = faf.get("commands") or {}
@@ -146,8 +156,11 @@ def _key_files(faf: dict) -> list:
146
156
 
147
157
  # --- AGENTS.md -------------------------------------------------------------
148
158
 
149
- def generate_agents_md(faf: dict) -> str:
150
- """Author a BETTER-shaped AGENTS.md from raw .faf data. Deterministic."""
159
+ def render_agents_md(faf: dict) -> str:
160
+ """Author a BETTER-shaped AGENTS.md from raw .faf data. Deterministic.
161
+
162
+ Public alias: :func:`author_agents_md`.
163
+ """
151
164
  lines: list[str] = []
152
165
 
153
166
  def push(s: str = "") -> None:
@@ -187,9 +200,9 @@ def generate_agents_md(faf: dict) -> str:
187
200
  push(orientation)
188
201
  push()
189
202
  push(
190
- "> Authored by faf — refresh with `faf export --agents` or the "
191
- "`faf_agents` MCP tool. The managed block is regenerated each time; "
192
- "hand-written content outside it is preserved."
203
+ "> Authored by faf — do not edit the managed block; refresh with "
204
+ "`faf export --agents` or the `faf_agents` MCP tool. Hand-written "
205
+ "content outside it is preserved."
193
206
  )
194
207
  push()
195
208
 
@@ -344,8 +357,11 @@ def generate_agents_md(faf: dict) -> str:
344
357
 
345
358
  # --- GEMINI.md ------------------------------------------------------------
346
359
 
347
- def generate_gemini_md(faf: dict) -> str:
348
- """GEMINI.md — Gemini CLI's own convention (hierarchical, @file-importable)."""
360
+ def render_gemini_md(faf: dict) -> str:
361
+ """GEMINI.md — Gemini CLI's own convention (hierarchical, @file-importable).
362
+
363
+ Public alias: :func:`author_gemini_md`.
364
+ """
349
365
  lines: list[str] = []
350
366
  proj = faf.get("project") or {}
351
367
  cmds = _classify_commands(faf)
@@ -401,3 +417,31 @@ def generate_gemini_md(faf: dict) -> str:
401
417
  "",
402
418
  ]
403
419
  return "\n".join(lines)
420
+
421
+
422
+ # --- public + deprecated names --------------------------------------------
423
+
424
+ #: Public API name for :func:`render_agents_md` — "faf authors" voice.
425
+ author_agents_md = render_agents_md
426
+ #: Public API name for :func:`render_gemini_md`.
427
+ author_gemini_md = render_gemini_md
428
+
429
+
430
+ def generate_agents_md(faf: dict) -> str:
431
+ """Deprecated alias for :func:`author_agents_md`. Removed in 2.0."""
432
+ warnings.warn(
433
+ "generate_agents_md is deprecated; use author_agents_md",
434
+ DeprecationWarning,
435
+ stacklevel=2,
436
+ )
437
+ return render_agents_md(faf)
438
+
439
+
440
+ def generate_gemini_md(faf: dict) -> str:
441
+ """Deprecated alias for :func:`author_gemini_md`. Removed in 2.0."""
442
+ warnings.warn(
443
+ "generate_gemini_md is deprecated; use author_gemini_md",
444
+ DeprecationWarning,
445
+ stacklevel=2,
446
+ )
447
+ return render_gemini_md(faf)