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.
- {sourcecode-0.19.0 → sourcecode-0.21.0}/PKG-INFO +92 -9
- {sourcecode-0.19.0 → sourcecode-0.21.0}/README.md +91 -8
- {sourcecode-0.19.0 → sourcecode-0.21.0}/docs/schema.md +2 -2
- {sourcecode-0.19.0 → sourcecode-0.21.0}/pyproject.toml +1 -1
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/cli.py +117 -18
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/dependency_analyzer.py +157 -2
- sourcecode-0.21.0/src/sourcecode/prepare_context.py +486 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/semantic_analyzer.py +2 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/serializer.py +18 -11
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_dependency_analyzer_node_python.py +2 -2
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_dependencies.py +1 -1
- sourcecode-0.19.0/src/sourcecode/prepare_context.py +0 -197
- {sourcecode-0.19.0 → sourcecode-0.21.0}/.gitignore +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/.ruff.toml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/__init__.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/conftest.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/lcov.info +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_architecture_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_architecture_summary.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_classifier.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_cli.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_code_notes_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_coverage_parser.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_cross_consistency.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_dependency_schema.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_python.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_detectors_base.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_graph_schema.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_detection.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_docs.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_lqn.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_metrics.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_multistack.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_semantics.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_integration_universal.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_packaging.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_real_projects.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_redactor.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_scanner.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_schema.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_schema_normalization.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_semantic_analyzer_node.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_semantic_analyzer_python.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_semantic_import_resolution.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_semantic_schema.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.21.0}/tests/test_summarizer.py +0 -0
- {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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
**`--
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
**`--
|
|
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
|
|
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.
|
|
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.
|
|
648
|
+
"sourcecode_version": "0.21.0",
|
|
649
649
|
"analyzed_path": "/abs/path/to/project"
|
|
650
650
|
},
|
|
651
651
|
"file_tree": {
|
|
@@ -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(
|
|
635
|
-
|
|
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
|
-
"""
|
|
638
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
"
|
|
653
|
-
"
|
|
654
|
-
|
|
655
|
-
"
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
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))
|