sourcecode 0.19.0__tar.gz → 0.21.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 (110) hide show
  1. {sourcecode-0.19.0 → sourcecode-0.21.0}/PKG-INFO +92 -9
  2. {sourcecode-0.19.0 → sourcecode-0.21.0}/README.md +91 -8
  3. {sourcecode-0.19.0 → sourcecode-0.21.0}/docs/schema.md +2 -2
  4. {sourcecode-0.19.0 → sourcecode-0.21.0}/pyproject.toml +1 -1
  5. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/cli.py +117 -18
  7. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/dependency_analyzer.py +157 -2
  8. sourcecode-0.21.0/src/sourcecode/prepare_context.py +486 -0
  9. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/semantic_analyzer.py +2 -0
  10. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/serializer.py +18 -11
  11. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_dependency_analyzer_node_python.py +2 -2
  12. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_dependencies.py +1 -1
  13. sourcecode-0.19.0/src/sourcecode/prepare_context.py +0 -197
  14. {sourcecode-0.19.0 → sourcecode-0.21.0}/.gitignore +0 -0
  15. {sourcecode-0.19.0 → sourcecode-0.21.0}/.ruff.toml +0 -0
  16. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/architecture_analyzer.py +0 -0
  17. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/architecture_summary.py +0 -0
  18. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/classifier.py +0 -0
  19. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  20. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/coverage_parser.py +0 -0
  21. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/__init__.py +0 -0
  22. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/base.py +0 -0
  23. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/dart.py +0 -0
  24. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/dotnet.py +0 -0
  25. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/elixir.py +0 -0
  26. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/go.py +0 -0
  27. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/heuristic.py +0 -0
  28. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/java.py +0 -0
  29. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  30. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/nodejs.py +0 -0
  31. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/parsers.py +0 -0
  32. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/php.py +0 -0
  33. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/project.py +0 -0
  34. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/python.py +0 -0
  35. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/ruby.py +0 -0
  36. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/rust.py +0 -0
  37. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/systems.py +0 -0
  38. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/terraform.py +0 -0
  39. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/tooling.py +0 -0
  40. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/doc_analyzer.py +0 -0
  41. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/env_analyzer.py +0 -0
  42. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/git_analyzer.py +0 -0
  43. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/graph_analyzer.py +0 -0
  44. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/metrics_analyzer.py +0 -0
  45. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/redactor.py +0 -0
  46. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/scanner.py +0 -0
  47. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/schema.py +0 -0
  48. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/summarizer.py +0 -0
  49. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/tree_utils.py +0 -0
  50. {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/workspace.py +0 -0
  51. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/__init__.py +0 -0
  52. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/conftest.py +0 -0
  53. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/coverage.xml +0 -0
  54. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  55. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
  56. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  57. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/go_service/go.mod +0 -0
  58. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/jacoco.xml +0 -0
  59. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/lcov.info +0 -0
  60. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  61. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/nextjs_app/package.json +0 -0
  62. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  63. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  64. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  65. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  66. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  67. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  68. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_architecture_analyzer.py +0 -0
  69. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_architecture_summary.py +0 -0
  70. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_classifier.py +0 -0
  71. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_cli.py +0 -0
  72. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_code_notes_analyzer.py +0 -0
  73. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_coverage_parser.py +0 -0
  74. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_cross_consistency.py +0 -0
  75. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
  76. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_dependency_schema.py +0 -0
  77. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_go_rust_java.py +0 -0
  78. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_nodejs.py +0 -0
  79. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_php_ruby_dart.py +0 -0
  80. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_python.py +0 -0
  81. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_universal_managed.py +0 -0
  82. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_universal_systems.py +0 -0
  83. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detectors_base.py +0 -0
  84. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_doc_analyzer_jsdom.py +0 -0
  85. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_doc_analyzer_python.py +0 -0
  86. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_graph_analyzer_polyglot.py +0 -0
  87. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_graph_analyzer_python_node.py +0 -0
  88. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_graph_schema.py +0 -0
  89. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration.py +0 -0
  90. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_detection.py +0 -0
  91. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_docs.py +0 -0
  92. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_graph_modules.py +0 -0
  93. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_lqn.py +0 -0
  94. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_metrics.py +0 -0
  95. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_multistack.py +0 -0
  96. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_semantics.py +0 -0
  97. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_universal.py +0 -0
  98. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_metrics_analyzer.py +0 -0
  99. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_packaging.py +0 -0
  100. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_real_projects.py +0 -0
  101. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_redactor.py +0 -0
  102. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_scanner.py +0 -0
  103. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_schema.py +0 -0
  104. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_schema_normalization.py +0 -0
  105. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_semantic_analyzer_node.py +0 -0
  106. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_semantic_analyzer_python.py +0 -0
  107. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_semantic_import_resolution.py +0 -0
  108. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_semantic_schema.py +0 -0
  109. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_summarizer.py +0 -0
  110. {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_workspace_analyzer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 0.19.0
3
+ Version: 0.21.0
4
4
  Summary: Genera un mapa de contexto estructurado de proyectos de software para agentes IA
5
5
  License: MIT
6
6
  Requires-Python: >=3.9
@@ -81,7 +81,7 @@ sourcecode --version
81
81
 
82
82
  ## What It Detects
83
83
 
84
- - Stacks: Node.js, Python, Go, Rust, Java, PHP, Ruby, and Dart.
84
+ - Stacks: Node.js, Python, Go, Rust, Java (Maven `pom.xml` and Gradle `build.gradle`/`build.gradle.kts`), PHP, Ruby, and Dart.
85
85
  - Frameworks associated with each stack when enough signals are present.
86
86
  - `project_type`: `webapp`, `api`, `library`, `cli`, `fullstack`, `monorepo`, or `unknown`.
87
87
  - Relevant `entry_points`, such as `main.py`, `cmd/api/main.go`, or `app/page.tsx`.
@@ -111,6 +111,8 @@ sourcecode --version
111
111
  | `--env-map` | off | Map all environment variables referenced in source code: key name, required/optional status, inferred type (`string`, `int`, `bool`, `url`, `path`, `enum`), functional category (`database`, `auth`, `cache`, `storage`, `service`, `observability`, `feature_flag`, `server`, `general`), default value when present, and source file locations. Supplements with descriptions from `.env.example`, `.env.sample`, and similar reference files. |
112
112
  | `--code-notes` | off | Extract inline code annotations — `TODO`, `FIXME`, `HACK`, `NOTE`, `DEPRECATED`, `WARNING`, `XXX`, `BUG`, `OPTIMIZE` — with file path, line number, annotation text, and the nearest enclosing function or class. Also detects Architecture Decision Records (ADRs) in `docs/decisions/`, `docs/adr/`, `adr/`, and similar directories, extracting title, status, and summary. |
113
113
  | `--depth INTEGER` | `4` | Maximum file tree depth. Range: 1–20. |
114
+ | `--no-tree` | off | Suppress `file_tree`, `file_paths` (and `file_tree_depth1` in `--compact`) from the output. Ideal with `--dependencies` on large projects to get dependency data without a multi-thousand-line file tree. |
115
+ | `--agent` | off | Agent mode: auto-selects `--compact --dependencies --env-map --code-notes` and adds `--no-tree` automatically for Java/Gradle projects or large repositories. Prints selected flags to stderr. Can be combined with other flags (e.g. `--agent --git-context`). |
114
116
  | `--no-redact` | off | Disable secret redaction (enabled by default). |
115
117
  | `--version` | — | Show version and exit. |
116
118
 
@@ -123,8 +125,8 @@ The full schema (`SourceMap`) includes the following fields:
123
125
  | Field | Type | Description |
124
126
  |-------|------|-------------|
125
127
  | `metadata` | object | Schema version, timestamp, `sourcecode` version, and analyzed path. |
126
- | `file_tree` | object | Repository tree where `null` represents a file and `{}` represents a directory. |
127
- | `file_paths` | array | Flat list of all project paths derived from `file_tree`, with forward-slash separators. Always present; respects `--depth`. |
128
+ | `file_tree` | object | Repository tree where `null` represents a file and `{}` represents a directory. Suppressed when `--no-tree` is active. |
129
+ | `file_paths` | array | Flat list of all project paths derived from `file_tree`, with forward-slash separators. Respects `--depth`. Suppressed when `--no-tree` is active. |
128
130
  | `project_summary` | string\|null | Deterministic natural-language description of the project. Includes: manifest/README description when available, detected architecture pattern (`layered`, `mvc`, `hexagonal`, `fullstack`), business domain names inferred from directory structure, entry points (when no domains are detected), and dependency count. Present when stacks are detected. |
129
131
  | `architecture_summary` | string\|null | Static summary of the main execution flow, orchestrated modules, and output produced by the project. Present when enough structural evidence is available. |
130
132
  | `stacks` | array | Stack detections with confidence, frameworks, manifests, `primary`, `root`, `workspace`, and `signals`. |
@@ -223,7 +225,7 @@ ADR detection looks for Markdown files in `docs/decisions/`, `docs/adr/`, `adr/`
223
225
 
224
226
  ## Compact Mode
225
227
 
226
- `--compact` returns a reduced JSON view optimized for LLM prompts (~500-700 tokens). It excludes the full `dependencies` list, `docs`, and `module_graph`, while retaining the fields most useful for project orientation. When optional flags are also active, their summaries are included: `dependency_summary` (with `--dependencies`), `env_summary` (with `--env-map`), and `code_notes_summary` (with `--code-notes`).
228
+ `--compact` returns a reduced JSON view optimized for LLM prompts. It excludes the full `dependencies` list, `docs`, and `module_graph`, while retaining the fields most useful for project orientation. When optional flags are also active, their summaries are included: `dependency_summary` + `key_dependencies` (with `--dependencies`), `env_summary` (with `--env-map`), and `code_notes_summary` (with `--code-notes`). Adding `--no-tree` further removes `file_tree_depth1`, bringing the output to ~500-800 tokens depending on how many flags are active.
227
229
 
228
230
  Real output from a Python FastAPI project:
229
231
 
@@ -266,7 +268,7 @@ Real output from a Python FastAPI project:
266
268
  }
267
269
  ```
268
270
 
269
- When `--compact --dependencies` is used, `dependency_summary` is populated instead of `null`.
271
+ When `--compact --dependencies` is used, `dependency_summary` is populated and `key_dependencies` lists the top-15 direct dependencies with resolved versions. Add `--no-tree` to drop `file_tree_depth1` for the smallest possible context footprint.
270
272
 
271
273
  ## Docs Mode
272
274
 
@@ -444,15 +446,27 @@ In a monorepo, each stack includes its own `root` and `workspace`, and one of th
444
446
 
445
447
  Different modes optimize for different tradeoffs between context size and depth of information.
446
448
 
447
- **`--compact` — minimal context (~500-700 tokens)**
449
+ **`--agent` — zero-config mode for AI pipelines**
450
+
451
+ Best for: running `sourcecode` from inside an agent without knowing the project in advance. Auto-selects the right flag combination based on detected stack and project size.
452
+
453
+ ```bash
454
+ sourcecode --agent .
455
+ sourcecode --agent --git-context . # add git context on top of auto-selected flags
456
+ ```
457
+
458
+ On a Java/Gradle project the output is: `--compact --dependencies --env-map --code-notes --no-tree` (~800 tokens). On a Node/Python project: same without `--no-tree` (~900 tokens including depth-1 tree). Selected flags are always printed to stderr so the agent can log them.
459
+
460
+ **`--compact` — minimal context**
448
461
 
449
462
  Best for: initial orientation, deciding what to explore next, fast handoffs between agents.
450
463
 
451
- Includes: `project_summary` (instant project description), `architecture_summary` (execution-oriented static summary), `stacks`, `entry_points`, `file_tree_depth1`, and `dependency_summary` when `--dependencies` was also requested.
464
+ Includes: `project_summary`, `architecture_summary`, `stacks`, `entry_points`, `file_tree_depth1`, and — when the respective flags are active — `dependency_summary` + `key_dependencies`, `env_summary`, `code_notes_summary`.
452
465
 
453
466
  ```bash
454
467
  sourcecode --compact .
455
- sourcecode --compact --dependencies .
468
+ sourcecode --compact --dependencies . # + key dependencies with versions
469
+ sourcecode --compact --dependencies --no-tree . # smallest footprint: no file tree
456
470
  ```
457
471
 
458
472
  **Full output — deep analysis**
@@ -622,6 +636,75 @@ Combine flags for a comprehensive project handoff:
622
636
  sourcecode --compact --env-map --code-notes --git-context .
623
637
  ```
624
638
 
639
+ ## `prepare-context` — Task-aware context for LLMs
640
+
641
+ `prepare-context` is a subcommand that builds a focused, task-specific context optimized for LLM reasoning. Instead of a full project dump, it returns only the data an LLM needs for a specific goal.
642
+
643
+ > **Note:** Because `sourcecode` has a positional `PATH` argument, you must provide it explicitly before the subcommand:
644
+ > ```bash
645
+ > sourcecode . prepare-context <task> # current directory
646
+ > sourcecode /my/project prepare-context <task>
647
+ > ```
648
+
649
+ ### Available tasks
650
+
651
+ | Task | Goal | Output |
652
+ |------|------|--------|
653
+ | `explain` | Onboard an LLM to the project | `project_summary`, `architecture_summary`, `relevant_files`, `key_dependencies` |
654
+ | `fix-bug` | Identify likely bug locations | `relevant_files` (ranked by risk), `suspected_areas`, `code_notes_summary` |
655
+ | `refactor` | Surface improvement opportunities | `relevant_files`, `improvement_opportunities`, `architecture_summary` |
656
+ | `generate-tests` | Find untested areas | `test_gaps`, `relevant_files` (source without tests), `key_dependencies` |
657
+
658
+ ### Usage
659
+
660
+ ```bash
661
+ # List tasks with descriptions
662
+ sourcecode . prepare-context --task-help
663
+
664
+ # Explain the project
665
+ sourcecode . prepare-context explain
666
+
667
+ # Find bug areas, with a ready-to-paste LLM prompt
668
+ sourcecode . prepare-context fix-bug --llm-prompt
669
+
670
+ # Find untested files in a specific project
671
+ sourcecode . prepare-context generate-tests --path /my/project
672
+
673
+ # Preview what will be analyzed (no analysis run)
674
+ sourcecode . prepare-context refactor --dry-run
675
+ ```
676
+
677
+ ### Output format
678
+
679
+ ```json
680
+ {
681
+ "task": "fix-bug",
682
+ "goal": "Identify the most likely files and areas where a bug may be located.",
683
+ "project_summary": "CLI en Python (Typer). Entry points: src/cli.py. 4 dependencias.",
684
+ "architecture_summary": null,
685
+ "relevant_files": [
686
+ { "path": "src/handler.py", "role": "source", "score": 2.0, "reason": "matches 'handler'" },
687
+ { "path": "src/cli.py", "role": "entrypoint", "score": 3.0, "reason": "entry point" }
688
+ ],
689
+ "suspected_areas": ["src/handler.py (2 annotations)", "src/parser.py (1 annotation)"],
690
+ "code_notes_summary": { "total": 5, "by_kind": { "FIXME": 3, "BUG": 2 }, "top_files": ["src/handler.py"] }
691
+ }
692
+ ```
693
+
694
+ ### `--llm-prompt`
695
+
696
+ Add `--llm-prompt` to include a ready-to-use prompt that you can paste directly into any LLM:
697
+
698
+ ```bash
699
+ sourcecode . prepare-context explain --llm-prompt | jq -r '.llm_prompt'
700
+ ```
701
+
702
+ The prompt is task-specific and includes the project context, relevant files, and concrete instructions for the LLM.
703
+
704
+ ### Task auto-selection with `--agent`
705
+
706
+ For zero-config usage, `--agent` on the main command automatically selects the right flags for the project type. For task-aware context, use `prepare-context` explicitly with the task that matches your goal.
707
+
625
708
  ## Development
626
709
 
627
710
  Editable install with development dependencies:
@@ -65,7 +65,7 @@ sourcecode --version
65
65
 
66
66
  ## What It Detects
67
67
 
68
- - Stacks: Node.js, Python, Go, Rust, Java, PHP, Ruby, and Dart.
68
+ - Stacks: Node.js, Python, Go, Rust, Java (Maven `pom.xml` and Gradle `build.gradle`/`build.gradle.kts`), PHP, Ruby, and Dart.
69
69
  - Frameworks associated with each stack when enough signals are present.
70
70
  - `project_type`: `webapp`, `api`, `library`, `cli`, `fullstack`, `monorepo`, or `unknown`.
71
71
  - Relevant `entry_points`, such as `main.py`, `cmd/api/main.go`, or `app/page.tsx`.
@@ -95,6 +95,8 @@ sourcecode --version
95
95
  | `--env-map` | off | Map all environment variables referenced in source code: key name, required/optional status, inferred type (`string`, `int`, `bool`, `url`, `path`, `enum`), functional category (`database`, `auth`, `cache`, `storage`, `service`, `observability`, `feature_flag`, `server`, `general`), default value when present, and source file locations. Supplements with descriptions from `.env.example`, `.env.sample`, and similar reference files. |
96
96
  | `--code-notes` | off | Extract inline code annotations — `TODO`, `FIXME`, `HACK`, `NOTE`, `DEPRECATED`, `WARNING`, `XXX`, `BUG`, `OPTIMIZE` — with file path, line number, annotation text, and the nearest enclosing function or class. Also detects Architecture Decision Records (ADRs) in `docs/decisions/`, `docs/adr/`, `adr/`, and similar directories, extracting title, status, and summary. |
97
97
  | `--depth INTEGER` | `4` | Maximum file tree depth. Range: 1–20. |
98
+ | `--no-tree` | off | Suppress `file_tree`, `file_paths` (and `file_tree_depth1` in `--compact`) from the output. Ideal with `--dependencies` on large projects to get dependency data without a multi-thousand-line file tree. |
99
+ | `--agent` | off | Agent mode: auto-selects `--compact --dependencies --env-map --code-notes` and adds `--no-tree` automatically for Java/Gradle projects or large repositories. Prints selected flags to stderr. Can be combined with other flags (e.g. `--agent --git-context`). |
98
100
  | `--no-redact` | off | Disable secret redaction (enabled by default). |
99
101
  | `--version` | — | Show version and exit. |
100
102
 
@@ -107,8 +109,8 @@ The full schema (`SourceMap`) includes the following fields:
107
109
  | Field | Type | Description |
108
110
  |-------|------|-------------|
109
111
  | `metadata` | object | Schema version, timestamp, `sourcecode` version, and analyzed path. |
110
- | `file_tree` | object | Repository tree where `null` represents a file and `{}` represents a directory. |
111
- | `file_paths` | array | Flat list of all project paths derived from `file_tree`, with forward-slash separators. Always present; respects `--depth`. |
112
+ | `file_tree` | object | Repository tree where `null` represents a file and `{}` represents a directory. Suppressed when `--no-tree` is active. |
113
+ | `file_paths` | array | Flat list of all project paths derived from `file_tree`, with forward-slash separators. Respects `--depth`. Suppressed when `--no-tree` is active. |
112
114
  | `project_summary` | string\|null | Deterministic natural-language description of the project. Includes: manifest/README description when available, detected architecture pattern (`layered`, `mvc`, `hexagonal`, `fullstack`), business domain names inferred from directory structure, entry points (when no domains are detected), and dependency count. Present when stacks are detected. |
113
115
  | `architecture_summary` | string\|null | Static summary of the main execution flow, orchestrated modules, and output produced by the project. Present when enough structural evidence is available. |
114
116
  | `stacks` | array | Stack detections with confidence, frameworks, manifests, `primary`, `root`, `workspace`, and `signals`. |
@@ -207,7 +209,7 @@ ADR detection looks for Markdown files in `docs/decisions/`, `docs/adr/`, `adr/`
207
209
 
208
210
  ## Compact Mode
209
211
 
210
- `--compact` returns a reduced JSON view optimized for LLM prompts (~500-700 tokens). It excludes the full `dependencies` list, `docs`, and `module_graph`, while retaining the fields most useful for project orientation. When optional flags are also active, their summaries are included: `dependency_summary` (with `--dependencies`), `env_summary` (with `--env-map`), and `code_notes_summary` (with `--code-notes`).
212
+ `--compact` returns a reduced JSON view optimized for LLM prompts. It excludes the full `dependencies` list, `docs`, and `module_graph`, while retaining the fields most useful for project orientation. When optional flags are also active, their summaries are included: `dependency_summary` + `key_dependencies` (with `--dependencies`), `env_summary` (with `--env-map`), and `code_notes_summary` (with `--code-notes`). Adding `--no-tree` further removes `file_tree_depth1`, bringing the output to ~500-800 tokens depending on how many flags are active.
211
213
 
212
214
  Real output from a Python FastAPI project:
213
215
 
@@ -250,7 +252,7 @@ Real output from a Python FastAPI project:
250
252
  }
251
253
  ```
252
254
 
253
- When `--compact --dependencies` is used, `dependency_summary` is populated instead of `null`.
255
+ When `--compact --dependencies` is used, `dependency_summary` is populated and `key_dependencies` lists the top-15 direct dependencies with resolved versions. Add `--no-tree` to drop `file_tree_depth1` for the smallest possible context footprint.
254
256
 
255
257
  ## Docs Mode
256
258
 
@@ -428,15 +430,27 @@ In a monorepo, each stack includes its own `root` and `workspace`, and one of th
428
430
 
429
431
  Different modes optimize for different tradeoffs between context size and depth of information.
430
432
 
431
- **`--compact` — minimal context (~500-700 tokens)**
433
+ **`--agent` — zero-config mode for AI pipelines**
434
+
435
+ Best for: running `sourcecode` from inside an agent without knowing the project in advance. Auto-selects the right flag combination based on detected stack and project size.
436
+
437
+ ```bash
438
+ sourcecode --agent .
439
+ sourcecode --agent --git-context . # add git context on top of auto-selected flags
440
+ ```
441
+
442
+ On a Java/Gradle project the output is: `--compact --dependencies --env-map --code-notes --no-tree` (~800 tokens). On a Node/Python project: same without `--no-tree` (~900 tokens including depth-1 tree). Selected flags are always printed to stderr so the agent can log them.
443
+
444
+ **`--compact` — minimal context**
432
445
 
433
446
  Best for: initial orientation, deciding what to explore next, fast handoffs between agents.
434
447
 
435
- Includes: `project_summary` (instant project description), `architecture_summary` (execution-oriented static summary), `stacks`, `entry_points`, `file_tree_depth1`, and `dependency_summary` when `--dependencies` was also requested.
448
+ Includes: `project_summary`, `architecture_summary`, `stacks`, `entry_points`, `file_tree_depth1`, and — when the respective flags are active — `dependency_summary` + `key_dependencies`, `env_summary`, `code_notes_summary`.
436
449
 
437
450
  ```bash
438
451
  sourcecode --compact .
439
- sourcecode --compact --dependencies .
452
+ sourcecode --compact --dependencies . # + key dependencies with versions
453
+ sourcecode --compact --dependencies --no-tree . # smallest footprint: no file tree
440
454
  ```
441
455
 
442
456
  **Full output — deep analysis**
@@ -606,6 +620,75 @@ Combine flags for a comprehensive project handoff:
606
620
  sourcecode --compact --env-map --code-notes --git-context .
607
621
  ```
608
622
 
623
+ ## `prepare-context` — Task-aware context for LLMs
624
+
625
+ `prepare-context` is a subcommand that builds a focused, task-specific context optimized for LLM reasoning. Instead of a full project dump, it returns only the data an LLM needs for a specific goal.
626
+
627
+ > **Note:** Because `sourcecode` has a positional `PATH` argument, you must provide it explicitly before the subcommand:
628
+ > ```bash
629
+ > sourcecode . prepare-context <task> # current directory
630
+ > sourcecode /my/project prepare-context <task>
631
+ > ```
632
+
633
+ ### Available tasks
634
+
635
+ | Task | Goal | Output |
636
+ |------|------|--------|
637
+ | `explain` | Onboard an LLM to the project | `project_summary`, `architecture_summary`, `relevant_files`, `key_dependencies` |
638
+ | `fix-bug` | Identify likely bug locations | `relevant_files` (ranked by risk), `suspected_areas`, `code_notes_summary` |
639
+ | `refactor` | Surface improvement opportunities | `relevant_files`, `improvement_opportunities`, `architecture_summary` |
640
+ | `generate-tests` | Find untested areas | `test_gaps`, `relevant_files` (source without tests), `key_dependencies` |
641
+
642
+ ### Usage
643
+
644
+ ```bash
645
+ # List tasks with descriptions
646
+ sourcecode . prepare-context --task-help
647
+
648
+ # Explain the project
649
+ sourcecode . prepare-context explain
650
+
651
+ # Find bug areas, with a ready-to-paste LLM prompt
652
+ sourcecode . prepare-context fix-bug --llm-prompt
653
+
654
+ # Find untested files in a specific project
655
+ sourcecode . prepare-context generate-tests --path /my/project
656
+
657
+ # Preview what will be analyzed (no analysis run)
658
+ sourcecode . prepare-context refactor --dry-run
659
+ ```
660
+
661
+ ### Output format
662
+
663
+ ```json
664
+ {
665
+ "task": "fix-bug",
666
+ "goal": "Identify the most likely files and areas where a bug may be located.",
667
+ "project_summary": "CLI en Python (Typer). Entry points: src/cli.py. 4 dependencias.",
668
+ "architecture_summary": null,
669
+ "relevant_files": [
670
+ { "path": "src/handler.py", "role": "source", "score": 2.0, "reason": "matches 'handler'" },
671
+ { "path": "src/cli.py", "role": "entrypoint", "score": 3.0, "reason": "entry point" }
672
+ ],
673
+ "suspected_areas": ["src/handler.py (2 annotations)", "src/parser.py (1 annotation)"],
674
+ "code_notes_summary": { "total": 5, "by_kind": { "FIXME": 3, "BUG": 2 }, "top_files": ["src/handler.py"] }
675
+ }
676
+ ```
677
+
678
+ ### `--llm-prompt`
679
+
680
+ Add `--llm-prompt` to include a ready-to-use prompt that you can paste directly into any LLM:
681
+
682
+ ```bash
683
+ sourcecode . prepare-context explain --llm-prompt | jq -r '.llm_prompt'
684
+ ```
685
+
686
+ The prompt is task-specific and includes the project context, relevant files, and concrete instructions for the LLM.
687
+
688
+ ### Task auto-selection with `--agent`
689
+
690
+ For zero-config usage, `--agent` on the main command automatically selects the right flags for the project type. For task-aware context, use `prepare-context` explicitly with the task that matches your goal.
691
+
609
692
  ## Development
610
693
 
611
694
  Editable install with development dependencies:
@@ -81,7 +81,7 @@ Campos:
81
81
  {
82
82
  "schema_version": "1.0",
83
83
  "generated_at": "2026-04-07T19:41:05.686277+00:00",
84
- "sourcecode_version": "0.19.0",
84
+ "sourcecode_version": "0.21.0",
85
85
  "analyzed_path": "/abs/path/to/project"
86
86
  }
87
87
  ```
@@ -645,7 +645,7 @@ Ejemplo de salida para un monorepo con web Node.js y API Python con `--dependenc
645
645
  "metadata": {
646
646
  "schema_version": "1.0",
647
647
  "generated_at": "2026-04-07T19:41:05.686277+00:00",
648
- "sourcecode_version": "0.19.0",
648
+ "sourcecode_version": "0.21.0",
649
649
  "analyzed_path": "/abs/path/to/project"
650
650
  },
651
651
  "file_tree": {
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "0.19.0"
7
+ version = "0.21.0"
8
8
  description = "Genera un mapa de contexto estructurado de proyectos de software para agentes IA"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """sourcecode — Genera mapas de contexto estructurado para agentes IA."""
2
2
 
3
- __version__ = "0.19.0"
3
+ __version__ = "0.21.0"
@@ -75,6 +75,11 @@ def main(
75
75
  "--graph-edges",
76
76
  help="Tipos de arista para `--graph-modules` separados por comas: imports,calls,contains,extends",
77
77
  ),
78
+ no_tree: bool = typer.Option(
79
+ False,
80
+ "--no-tree",
81
+ help="Suprimir file_tree y file_paths del output (ideal con --dependencies en proyectos grandes)",
82
+ ),
78
83
  no_redact: bool = typer.Option(
79
84
  False,
80
85
  "--no-redact",
@@ -151,8 +156,17 @@ def main(
151
156
  "--code-notes",
152
157
  help="Extraer anotaciones TODO/FIXME/HACK/NOTE/DEPRECATED/WARNING/BUG/XXX/OPTIMIZE con ubicacion y simbolo envolvente, y detectar ADRs en docs/decisions/, docs/adr/ y similares",
153
158
  ),
159
+ agent: bool = typer.Option(
160
+ False,
161
+ "--agent",
162
+ help="Modo agente: selecciona automaticamente --compact --dependencies --env-map --code-notes y activa --no-tree en proyectos Java/Gradle o grandes",
163
+ ),
154
164
  ) -> None:
155
165
  """Genera un mapa de contexto estructurado del proyecto en formato JSON o YAML."""
166
+ # When a subcommand (e.g. prepare-context) is invoked, skip the main analysis.
167
+ if ctx.invoked_subcommand is not None:
168
+ return
169
+
156
170
  # Validar formato
157
171
  if format not in FORMAT_CHOICES:
158
172
  typer.echo(
@@ -221,6 +235,16 @@ def main(
221
235
  _java_min_depth = 8
222
236
  effective_depth = max(depth, _java_min_depth) if _is_java and depth < _java_min_depth else depth
223
237
 
238
+ # --agent: auto-select flags based on project characteristics
239
+ if agent:
240
+ compact = True
241
+ if _is_java:
242
+ no_tree = True
243
+ _agent_flags = ["--compact", "--dependencies", "--env-map", "--code-notes"]
244
+ if no_tree:
245
+ _agent_flags.append("--no-tree")
246
+ typer.echo(f"[agent] {' '.join(_agent_flags)}", err=True)
247
+
224
248
  scanner = FileScanner(target, max_depth=effective_depth)
225
249
  raw_tree = scanner.scan_tree()
226
250
 
@@ -594,7 +618,7 @@ def main(
594
618
 
595
619
  # 4. Serializar (con o sin modo compact)
596
620
  if compact:
597
- data = compact_view(sm)
621
+ data = compact_view(sm, no_tree=no_tree)
598
622
  # Aplicar redaccion sobre el dict del compact view
599
623
  if not no_redact:
600
624
  data = redact_dict(data)
@@ -602,6 +626,9 @@ def main(
602
626
  else:
603
627
  # Redactar sobre el dict serializado (SEC-01, SEC-03)
604
628
  raw_dict = asdict(sm)
629
+ if no_tree:
630
+ raw_dict.pop("file_tree", None)
631
+ raw_dict.pop("file_paths", None)
605
632
  if not no_redact:
606
633
  raw_dict = redact_dict(raw_dict)
607
634
 
@@ -631,31 +658,103 @@ def main(
631
658
 
632
659
  @app.command("prepare-context")
633
660
  def prepare_context_cmd(
634
- task: str = typer.Argument(..., help="Descripción de la tarea"),
635
- path: Path = typer.Option(".", "--path", "-p", help="Directorio del proyecto"),
661
+ task: Optional[str] = typer.Argument(
662
+ None,
663
+ help="Task: explain | fix-bug | refactor | generate-tests",
664
+ ),
665
+ path: Path = typer.Option(
666
+ Path("."),
667
+ "--path", "-p",
668
+ help="Project directory to analyze (default: current directory)",
669
+ ),
670
+ llm_prompt: bool = typer.Option(
671
+ False,
672
+ "--llm-prompt",
673
+ help="Append a ready-to-use LLM prompt to the output",
674
+ ),
675
+ task_help: bool = typer.Option(
676
+ False,
677
+ "--task-help",
678
+ help="List available tasks with descriptions and exit",
679
+ ),
680
+ dry_run: bool = typer.Option(
681
+ False,
682
+ "--dry-run",
683
+ help="Show what would be analyzed without running it",
684
+ ),
636
685
  ) -> None:
637
- """Prepara contexto mínimo optimizado para que un LLM modifique el código."""
638
- from dataclasses import asdict
686
+ """Prepare task-aware context optimized for LLM reasoning.
687
+
688
+ \b
689
+ Note: PATH must be provided before the subcommand (default: '.'):
690
+ sourcecode . prepare-context explain
691
+ sourcecode . prepare-context fix-bug --path /my/project
692
+ sourcecode . prepare-context generate-tests --llm-prompt
693
+ sourcecode . prepare-context --task-help
694
+ """
695
+ from sourcecode.prepare_context import TASKS, TaskContextBuilder
696
+
697
+ if task_help:
698
+ typer.echo("Available tasks:\n")
699
+ for name, spec in TASKS.items():
700
+ typer.echo(f" {name:<20} {spec.description}")
701
+ typer.echo(f" {'':20} Output: {spec.output_hint}\n")
702
+ raise typer.Exit()
639
703
 
640
- from sourcecode.prepare_context import ContextBuilder
704
+ if task is None:
705
+ typer.echo(
706
+ f"Error: task is required. Available: {', '.join(TASKS)}\n"
707
+ "Use --task-help for descriptions.",
708
+ err=True,
709
+ )
710
+ raise typer.Exit(code=1)
641
711
 
642
- target = path.resolve()
712
+ if task not in TASKS:
713
+ typer.echo(
714
+ f"Error: unknown task '{task}'. Available: {', '.join(TASKS)}",
715
+ err=True,
716
+ )
717
+ raise typer.Exit(code=1)
643
718
 
719
+ target = path.resolve()
644
720
  if not target.exists() or not target.is_dir():
645
721
  typer.echo(f"Error: '{target}' no es un directorio válido.", err=True)
646
722
  raise typer.Exit(code=1)
647
723
 
648
- builder = ContextBuilder(target)
649
- result = builder.prepare(task)
650
-
651
- out = {
652
- "task": result.task,
653
- "entry_points": result.entry_points,
654
- "relevant_files": [asdict(f) for f in result.relevant_files],
655
- "call_flow": result.call_flow,
656
- "snippets": [asdict(s) for s in result.snippets],
657
- "tests": result.tests,
658
- "notes": result.notes,
724
+ if dry_run:
725
+ spec = TASKS[task]
726
+ typer.echo(f"task: {task}")
727
+ typer.echo(f"goal: {spec.goal}")
728
+ typer.echo(f"path: {target}")
729
+ typer.echo(f"analyzers: dependencies={'yes' if spec.enable_dependencies else 'no'}"
730
+ f", code_notes={'yes' if spec.enable_code_notes else 'no'}")
731
+ typer.echo(f"output: {spec.output_hint}")
732
+ raise typer.Exit()
733
+
734
+ from dataclasses import asdict
735
+
736
+ builder = TaskContextBuilder(target)
737
+ output = builder.build(task)
738
+
739
+ out: dict[str, Any] = {
740
+ "task": output.task,
741
+ "goal": output.goal,
742
+ "project_summary": output.project_summary,
743
+ "architecture_summary": output.architecture_summary,
744
+ "relevant_files": [asdict(f) for f in output.relevant_files],
745
+ "key_dependencies": output.key_dependencies,
659
746
  }
747
+ if output.suspected_areas:
748
+ out["suspected_areas"] = output.suspected_areas
749
+ if output.improvement_opportunities:
750
+ out["improvement_opportunities"] = output.improvement_opportunities
751
+ if output.test_gaps:
752
+ out["test_gaps"] = output.test_gaps
753
+ if output.code_notes_summary:
754
+ out["code_notes_summary"] = output.code_notes_summary
755
+ if output.limitations:
756
+ out["limitations"] = output.limitations
757
+ if llm_prompt:
758
+ out["llm_prompt"] = builder.render_prompt(output)
660
759
 
661
760
  typer.echo(json.dumps(out, indent=2, ensure_ascii=False))