Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc14f01e14 | ||
|
|
1ee0c6d21d | ||
|
|
9fda6d6e12 | ||
|
|
56c0c6a7ca | ||
|
|
74f7f93a75 | ||
|
|
0ff402a11d | ||
|
|
51d536b7ba | ||
|
|
403c444a3e | ||
|
|
a78abf06d0 | ||
|
|
52f54655d2 | ||
|
|
4f9450a71d | ||
|
|
1afab4a2a7 | ||
|
|
3439f35038 | ||
|
|
c85e772d2f | ||
|
|
1436074819 | ||
|
|
11a6cee981 | ||
|
|
d5f11462e9 |
@@ -147,7 +147,7 @@ class OpportunityManagementController extends Controller
|
||||
Inertia::share('publicationPreview', app(OpportunityCanonicalContract::class)->publicProjection($values['canonical'] ?? []));
|
||||
$classification = $id ? DB::table('audit_events')->where('source_system', 'opportunity-origin-review')->where('after_data->opportunity_id', $id)->orderByDesc('occurred_at')->orderByDesc('id')->value('after_data') : null;
|
||||
|
||||
return Inertia::render('management/opportunity-draft', ['resourcesInstalled' => app(OpportunityResources::class)->installed(), 'record' => $record, 'values' => $values, 'etag' => $record ? $service->etag($record) : null, 'readOnly' => str_ends_with($request->path(), '/view') || ($record && ! $access->canEdit($request->user(), $record)), 'closedVersion' => $record ? $service->closed($record) : false, 'classification' => $classification ? json_decode($classification, true)['classification'] : 'undetermined', 'sectors' => Sector::choices()->orderBy('name')->get(['id', 'name', 'slug']), 'categories' => OpportunityManagement::CATEGORIES,
|
||||
return Inertia::render('management/opportunity-draft', ['proactiveHistory' => app(\App\Services\ProactiveInvestment::class)->history($record), 'proactiveOptions' => app(\App\Services\ProactiveInvestment::class)->options($record), 'resourcesInstalled' => app(OpportunityResources::class)->installed(), 'record' => $record, 'values' => $values, 'etag' => $record ? $service->etag($record) : null, 'readOnly' => str_ends_with($request->path(), '/view') || ($record && ! $access->canEdit($request->user(), $record)), 'closedVersion' => $record ? $service->closed($record) : false, 'classification' => $classification ? json_decode($classification, true)['classification'] : 'undetermined', 'sectors' => Sector::choices()->orderBy('name')->get(['id', 'name', 'slug']), 'categories' => OpportunityManagement::CATEGORIES,
|
||||
'maturityCatalogue' => ['version' => OpportunityMaturity::VERSION, 'stages' => OpportunityMaturity::STAGES, 'legacyVersion' => OpportunityMaturity::LEGACY, 'legacyLabels' => OpportunityMaturity::LEGACY_LABELS],
|
||||
'territoryPath' => app(InvestmentGeography::class)->path($values['primary_territory_id'] ?? null, true),
|
||||
'history' => $id ? DB::table('audit_events')->where('source_system', 'opportunity-management')->where('after_data->record_id', $id)->orderByDesc('occurred_at')->get(['id', 'action', 'actor_user_id', 'occurred_at']) : []]);
|
||||
|
||||
@@ -35,6 +35,7 @@ class Opportunity extends Model
|
||||
{
|
||||
$data = parent::toArray();
|
||||
if (isset($data['description'])) $data['description'] = \App\Services\OpportunityPublicText::description($this, $data['description']);
|
||||
if ($this->exists && ($proactive = app(\App\Services\ProactiveInvestment::class)->publicData($this))) $data['proactive'] = $proactive;
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class InvestmentCatalogue
|
||||
/** @return array<string,mixed> */
|
||||
public function filters(Request $request): array
|
||||
{
|
||||
$filters = $request->validate(['q' => ['nullable', 'string', 'max:120'], 'sector' => ['nullable', 'string', 'max:80'],
|
||||
$filters = $request->validate(['perspective' => ['nullable', 'in:exists,needs,ideas,opportunities'],'q' => ['nullable', 'string', 'max:120'], 'sector' => ['nullable', 'string', 'max:80'],
|
||||
'preparation' => ['nullable', \Illuminate\Validation\Rule::in(array_column(OpportunityMaturity::searchOptions(), 'value'))],
|
||||
'opportunity_id' => ['nullable', 'integer', 'min:1'],
|
||||
'province_id' => ['nullable', 'uuid'], 'district_id' => ['nullable', 'uuid'], 'admin_post_id' => ['nullable', 'uuid'], 'locality_id' => ['nullable', 'uuid'],
|
||||
@@ -63,6 +63,8 @@ class InvestmentCatalogue
|
||||
public function query(array $filters): Builder
|
||||
{
|
||||
$query = Opportunity::published()->with('sector:id,name,slug');
|
||||
if (in_array($filters['perspective'] ?? '', ['exists','needs','ideas'], true)) $query->where('workflow_context->promotional_summary->projection->proactive->group', $filters['perspective']);
|
||||
elseif (($filters['perspective'] ?? '') === 'opportunities') $query->whereNull('workflow_context->promotional_summary->projection->proactive');
|
||||
$associated = $this->publicAssociatedIds($filters);
|
||||
if (($filters['territory_basis'] ?? 'all') === 'direct') {
|
||||
$query->where(fn ($q) => $q->whereNotNull('opportunities.primary_territory_id')->orWhereExists(fn ($l) => $l->selectRaw('1')->from('opportunity_locations')->whereColumn('opportunity_id', 'opportunities.id')));
|
||||
|
||||
@@ -46,6 +46,10 @@ final class InvestmentComplements
|
||||
} else {
|
||||
$reference = app(InvestorContext::class)->reference($origin);
|
||||
abort_unless($reference['kind'] === 'opportunity', 422);
|
||||
// The context resolver has already checked the actor's private scope.
|
||||
// A private preparation is valid dossier input, not a public offer
|
||||
// from which this public-complement catalogue can infer services.
|
||||
if (($reference['visibility'] ?? 'public') === 'private') return [];
|
||||
$principal = Opportunity::published()->findOrFail($reference['id']);
|
||||
$text = $principal->summary;
|
||||
$basis = 'Resumo cadastrado da oportunidade '.$principal->reference;
|
||||
|
||||
@@ -159,6 +159,8 @@ final class InvestorContext
|
||||
$fields['sector_id'] = (string) $o->sector_id;
|
||||
$fields['sector'] = $o->sector->name;
|
||||
}
|
||||
$proactive = $published ? app(ProactiveInvestment::class)->publicData($o) : ($draft['proactive'] ?? null);
|
||||
if ($proactive) $zoneAnalysis = ['proactive' => $proactive, 'source_key' => $key, 'source_version' => $version, 'private_source' => !$published];
|
||||
// Text labels do not establish a canonical territorial correspondence.
|
||||
if ($o->province) {
|
||||
$fields['province'] = $o->province;
|
||||
|
||||
@@ -21,7 +21,7 @@ class OpportunityManagement
|
||||
|
||||
public const MATURITY_FIELDS = ['maturity_level', 'maturity_label', 'maturity_stage', 'maturity_catalogue_version'];
|
||||
|
||||
public const PRIVATE_DRAFT_FIELDS = [...self::MATURITY_FIELDS, 'real_estate', 'canonical'];
|
||||
public const PRIVATE_DRAFT_FIELDS = [...self::MATURITY_FIELDS, 'real_estate', 'canonical', 'proactive'];
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
public function values(Opportunity $record): array
|
||||
@@ -63,7 +63,7 @@ class OpportunityManagement
|
||||
abort_if(array_key_exists('organization_id', $input) && $input['organization_id'] !== $existingRecord->organization_id, 403, 'A organização não pode ser alterada por edição.');
|
||||
}
|
||||
} elseif ($profileCreation) {
|
||||
abort_unless($access->canCreate($actor, $input['organization_id'] ?? null, $input['opportunity_category'] ?? ''), 403);
|
||||
abort_unless(($access->canCreate($actor, $input['organization_id'] ?? null, $input['opportunity_category'] ?? '') || (isset($input['proactive']) && empty($input['organization_id']) && !$access->has($actor, 'auditor') && $access->internalAssignment($actor, $input['opportunity_category'] ?? '') !== null)), 403);
|
||||
} else {
|
||||
abort_unless($access->legacyWriteAllowed($actor), 403, 'O papel v1 não usa a criação legada para contornar o seu âmbito.');
|
||||
}
|
||||
@@ -92,6 +92,7 @@ class OpportunityManagement
|
||||
'opportunity_category' => ['nullable', Rule::in(self::CATEGORIES)],
|
||||
'real_estate' => ['sometimes', 'array'],
|
||||
'canonical' => ['sometimes', 'array'],
|
||||
'proactive' => ['sometimes', 'array'],
|
||||
'estimated_investment_amount' => ['nullable', 'regex:/^\d{1,16}(\.\d{1,2})?$/'],
|
||||
'estimated_investment_currency' => ['nullable', 'in:MZN,USD,EUR,ZAR'],
|
||||
'reason' => ['required', 'string', 'min:20', 'max:1000'],
|
||||
@@ -127,6 +128,7 @@ class OpportunityManagement
|
||||
$this->check($record, $data['etag']);
|
||||
abort_if($record->trashed() || $record->status === 'archived', 409, 'Restaure antes de editar.');
|
||||
}
|
||||
if (array_key_exists('proactive', $data)) $data['proactive'] = app(ProactiveInvestment::class)->draft($data['proactive'], $record);
|
||||
$before = $record->getAttributes();
|
||||
$previousCanonical = $record->exists ? ($this->values($record)['canonical'] ?? []) : [];
|
||||
$changes = array_intersect_key($data, array_flip([...self::FIELDS, ...self::PRIVATE_DRAFT_FIELDS]));
|
||||
@@ -170,7 +172,7 @@ class OpportunityManagement
|
||||
$record->management_version = 1;
|
||||
$record->estimated_investment_currency = null;
|
||||
if ($profileCreation) {
|
||||
abort_unless($access->canCreate($actor, $data['organization_id'] ?? null, $data['opportunity_category'] ?? ''), 403);
|
||||
abort_unless(($access->canCreate($actor, $data['organization_id'] ?? null, $data['opportunity_category'] ?? '') || (isset($data['proactive']) && empty($data['organization_id']) && !$access->has($actor, 'auditor') && $access->internalAssignment($actor, $data['opportunity_category'] ?? '') !== null)), 403);
|
||||
$record->owner_user_id = $actor->id;
|
||||
$record->organization_id = $data['organization_id'] ?? null;
|
||||
$record->workflow_context = ['policy_version' => PortalProfileAccess::VERSION, 'contributors' => [$actor->id]];
|
||||
@@ -187,12 +189,12 @@ class OpportunityManagement
|
||||
$record->management_draft = json_encode([...$previous, ...$changes], JSON_THROW_ON_ERROR);
|
||||
} else {
|
||||
foreach ($changes as $key => $value) {
|
||||
if (in_array($key, ['real_estate', 'canonical', 'maturity_stage', 'maturity_catalogue_version'], true) || (($changes['maturity_catalogue_version'] ?? null) === OpportunityMaturity::VERSION && in_array($key, ['maturity_level', 'maturity_label'], true))) {
|
||||
if (in_array($key, ['real_estate', 'canonical', 'proactive', 'maturity_stage', 'maturity_catalogue_version'], true) || (($changes['maturity_catalogue_version'] ?? null) === OpportunityMaturity::VERSION && in_array($key, ['maturity_level', 'maturity_label'], true))) {
|
||||
continue;
|
||||
}
|
||||
$record->{$key} = $value;
|
||||
}
|
||||
if (isset($changes['maturity_catalogue_version']) || array_key_exists('real_estate', $changes) || array_key_exists('canonical', $changes)) {
|
||||
if (isset($changes['maturity_catalogue_version']) || array_key_exists('real_estate', $changes) || array_key_exists('canonical', $changes) || array_key_exists('proactive', $changes)) {
|
||||
// The existing draft JSON holds the versioned catalogue; legacy columns stay intact.
|
||||
$previous = $record->management_draft ? json_decode($record->management_draft, true, 512, JSON_THROW_ON_ERROR) : [];
|
||||
$record->management_draft = json_encode([...$previous, ...array_intersect_key($changes, array_flip(self::PRIVATE_DRAFT_FIELDS))], JSON_THROW_ON_ERROR);
|
||||
@@ -225,6 +227,7 @@ class OpportunityManagement
|
||||
$record = Opportunity::withTrashed()->whereKey($id)->lockForUpdate()->firstOrFail();
|
||||
abort_if($record->owner_user_id !== null, 403, 'A v1 exige pedido e decisão de arquivo; não concede exclusão ou restauro ao Promotor.');
|
||||
$this->check($record, $data['etag']);
|
||||
if (array_key_exists('proactive', $data)) $data['proactive'] = app(ProactiveInvestment::class)->draft($data['proactive'], $record);
|
||||
$before = $record->getAttributes();
|
||||
if ($data['action'] === 'restore') {
|
||||
abort_unless($record->trashed() || $record->status === 'archived', 409, 'Registo não está eliminado/arquivado.');
|
||||
|
||||
@@ -48,7 +48,7 @@ final class OpportunityPromotion
|
||||
'limitations' => '', 'territory_ids' => $existing ? DB::table('opportunity_locations')->where('opportunity_id', $record->id)->pluck('geo_location_id')->all() : [],
|
||||
'sector_id' => $record->sector_id];
|
||||
return ['record' => ['id' => $record->id, 'reference' => $record->reference], 'etag' => app(OpportunityManagement::class)->etag($record),
|
||||
'initial' => $form, 'publicNow' => $existing && $record->status === 'published',
|
||||
'proactiveRelations' => app(ProactiveInvestment::class)->publicationRelations($record), 'proactiveKind' => app(OpportunityManagement::class)->values($record)['proactive']['kind'] ?? null, 'proactiveEnabled' => isset(app(OpportunityManagement::class)->values($record)['proactive']), 'proactiveEvidence' => array_values(array_filter(app(OpportunityManagement::class)->values($record)['proactive']['evidence'] ?? [], fn ($e) => $e['access'] === 'public')), 'proactiveOptions' => app(ProactiveInvestment::class)->options(), 'initial' => [...$form, ...($saved['input']['proactive_public'] ?? null ? ['proactive_public' => $saved['input']['proactive_public']] : [])], 'publicNow' => $existing && $record->status === 'published',
|
||||
'reauthenticationRequired' => ! app(PortalProfileAccess::class)->mfa($actor),
|
||||
'sectors' => \App\Models\Sector::catalog()->orderBy('name')->get(['id', 'name']),
|
||||
'territories' => app(InvestmentGeography::class)->publicReferences()->orderBy('name')->get(['id', 'name', 'location_type']),
|
||||
@@ -63,6 +63,7 @@ final class OpportunityPromotion
|
||||
'title' => 'required_if:action,disclose|nullable|string|max:255', 'summary' => 'required_if:action,disclose|nullable|string|max:499',
|
||||
'description' => 'nullable|string|max:6000', 'limitations' => 'nullable|string|max:2500',
|
||||
'source_reference' => 'nullable|string|max:2000', 'edition' => 'nullable|string|max:150', 'source_date' => 'nullable|date_format:Y-m-d',
|
||||
'proactive_public' => 'sometimes|array', 'proactive_reviewed' => 'sometimes|boolean',
|
||||
'sector_id' => ['nullable', 'integer', Rule::in(\App\Models\Sector::catalog()->pluck('id')->all())],
|
||||
'territory_ids' => 'sometimes|array|max:30', 'territory_ids.*' => 'required|uuid|distinct',
|
||||
])->validate();
|
||||
@@ -83,6 +84,7 @@ final class OpportunityPromotion
|
||||
$projection = ['title' => $text('title'), 'summary' => $text('summary'), 'description' => $body,
|
||||
'sector_id' => $data['sector_id'] ?? null, 'maturity_label' => 'Em preparação', 'notice' => self::NOTICE,
|
||||
'territories' => array_map(fn ($p) => ['id' => end($p)->id, 'label' => implode(' / ', array_column($p, 'name'))], $paths)];
|
||||
if ($data['action'] === 'disclose' && ($proactive = app(ProactiveInvestment::class)->publication($record, $data))) { $projection['proactive'] = $proactive; $projection['description'] .= "\n\n".implode("\n", [$proactive['group'] === 'ideas' ? 'Ideia em preparação' : ($proactive['group'] === 'needs' ? 'Necessidade — '.$proactive['state'] : 'O que existe'), 'Necessidade: '.$proactive['need'], 'Proposta: '.$proactive['proposal'], 'Fundamento: '.$proactive['basis'], 'Limitações: '.$proactive['limitations'], 'Próximo passo: '.$proactive['next_action'], ProactiveInvestment::NOTICE]); }
|
||||
if ($data['action'] === 'disclose') abort_unless($projection['title'] !== '' && $projection['summary'] !== '', 422, 'Indique título e resumo em texto simples.');
|
||||
if ($data['action'] === 'withdraw') $projection = [...$projection, ...$record->only(['title', 'summary', 'description', 'sector_id', 'maturity_label'])];
|
||||
$payload = ['actor_id' => $actor->id, 'record_id' => $record->id, 'etag' => $data['etag'], 'action' => $data['action'],
|
||||
|
||||
@@ -245,7 +245,9 @@ class PortalProfileAccess
|
||||
|
||||
return $this->canView($actor, $record) && $this->promoterRecordScope($actor, $record) && ! $record->trashed()
|
||||
&& in_array($this->state($record), ['draft', 'needs_information'], true)
|
||||
&& $this->scoped($actor, 'promoter', $record->organization_id, $newType ?? $record->opportunity_category)
|
||||
&& ($this->scoped($actor, 'promoter', $record->organization_id, $newType ?? $record->opportunity_category)
|
||||
|| ($record->organization_id === null && isset(app(OpportunityManagement::class)->values($record)['proactive'])
|
||||
&& $this->internalAssignment($actor, $newType ?? $record->opportunity_category) !== null))
|
||||
&& $this->operational($actor, 'edit', $record->id);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Opportunity;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
/** Analysis in the existing opportunity draft; publication and private preparation remain separate. */
|
||||
final class ProactiveInvestment
|
||||
{
|
||||
public const VERSION = 1;
|
||||
public const NOTICE = 'A ausência de registo não comprova ausência de oferta. Proximidade não comprova contrato, participação, energia acessível, terra disponível ou benefício fiscal. Necessidade confirmada não comprova viabilidade comercial; hipótese de fornecimento não é encomenda.';
|
||||
public const GROUPS = ['exists' => 'O que existe', 'needs' => 'Necessidades identificadas', 'ideas' => 'Ideias de investimento'];
|
||||
|
||||
public function draft(array $input, ?Opportunity $record = null): array
|
||||
{
|
||||
$d = Validator::make(['proactive' => $input], [
|
||||
'proactive' => 'required|array:version,kind,evidence,need,idea,relations', 'proactive.version' => 'required|integer|in:1',
|
||||
'proactive.kind' => 'required|in:exists,needs,ideas', 'proactive.evidence' => 'present|array|max:60',
|
||||
'proactive.evidence.*' => 'array:id,category,purpose,statement,interpretation,source,locator,period,scope,coverage,verified_on,access,document_id',
|
||||
'proactive.evidence.*.id' => 'required|uuid|distinct',
|
||||
'proactive.evidence.*.category' => 'required|in:activity,resource,infrastructure,supply,demand',
|
||||
'proactive.evidence.*.purpose' => 'required|in:local,methodology',
|
||||
'proactive.evidence.*.access' => 'required|in:internal,public',
|
||||
'proactive.evidence.*.document_id' => 'nullable|uuid',
|
||||
'proactive.evidence.*.verified_on' => 'nullable|date_format:Y-m-d|before_or_equal:today',
|
||||
...collect(['statement','interpretation','source','locator','period','scope','coverage'])->mapWithKeys(fn ($k) => ['proactive.evidence.*.'.$k => 'present|nullable|string|max:4000'])->all(),
|
||||
'proactive.need' => 'required|array:state,problem,observed_supply,observed_demand,type,clients,evidence_ids,limitations,missing,confirmation',
|
||||
'proactive.need.state' => 'required|in:hypothesis,confirmed',
|
||||
'proactive.need.type' => 'nullable|in:quantity,quality,logistics,processing,coordination,support',
|
||||
...collect(['problem','observed_supply','observed_demand','clients','limitations','missing','confirmation'])->mapWithKeys(fn ($k) => ['proactive.need.'.$k => 'present|nullable|string|max:6000'])->all(),
|
||||
'proactive.need.evidence_ids' => 'present|array|max:60', 'proactive.need.evidence_ids.*' => 'uuid|distinct',
|
||||
'proactive.idea' => 'required|array:solution,activity,chain_id,stage,coverage,mode,resources,assumptions,conditions,pending,next_action',
|
||||
'proactive.idea.chain_id' => ['nullable','uuid',Rule::exists('value_chains','id')->whereNull('deleted_at')],
|
||||
'proactive.idea.mode' => 'nullable|in:create,expand,associate',
|
||||
...collect(['solution','activity','stage','coverage','resources','assumptions','conditions','pending','next_action'])->mapWithKeys(fn ($k) => ['proactive.idea.'.$k => 'present|nullable|string|max:6000'])->all(),
|
||||
'proactive.relations' => 'present|array|max:40',
|
||||
'proactive.relations.*' => 'array:id,kind,target_id,relation,reference,evidence_ids',
|
||||
'proactive.relations.*.id' => 'required|uuid|distinct',
|
||||
'proactive.relations.*.kind' => 'required|in:project,cluster,corridor,park,chain',
|
||||
'proactive.relations.*.target_id' => 'required|uuid',
|
||||
'proactive.relations.*.relation' => 'required|in:documented,hypothesis,proximity',
|
||||
'proactive.relations.*.reference' => 'required|string|max:4000',
|
||||
'proactive.relations.*.evidence_ids' => 'present|array|max:60', 'proactive.relations.*.evidence_ids.*' => 'uuid|distinct',
|
||||
])->validate()['proactive'];
|
||||
$ids = array_column($d['evidence'], 'id');
|
||||
foreach ([$d['need'], ...$d['relations']] as $row) {
|
||||
if (array_diff($row['evidence_ids'], $ids)) $this->fail('evidence', 'Seleccione apenas evidências desta análise.');
|
||||
}
|
||||
$seen = [];
|
||||
foreach ($d['evidence'] as $e) {
|
||||
$key = mb_strtolower(trim(($e['source'] ?? '').'|'.($e['locator'] ?? '').'|'.($e['statement'] ?? '')));
|
||||
if (trim($key, '| ') !== '' && isset($seen[$key])) $this->fail('evidence', 'A mesma evidência já foi registada; edite a entrada existente.');
|
||||
$seen[$key] = true;
|
||||
if (! empty($e['document_id'])) $this->document($record, $e['document_id'], $e['access'] === 'public');
|
||||
}
|
||||
$seen = [];
|
||||
foreach ($d['relations'] as $row) {
|
||||
$target = app(OpportunityClassification::class)->targets($row['kind'])->where('id', $row['target_id'])->exists();
|
||||
if (! $target) $this->fail('relations', 'Referência existente indisponível; não foi criada outra empresa, zona ou estrutura.');
|
||||
$key = $row['kind'].'|'.$row['target_id'];
|
||||
if (isset($seen[$key])) $this->fail('relations', 'A referência já está nesta análise; reúna o fundamento na entrada existente.');
|
||||
$seen[$key] = true;
|
||||
if ($row['relation'] === 'documented' && ! $row['evidence_ids']) $this->fail('relations', 'Relação documentada exige evidência seleccionada; mantenha hipótese ou proximidade quando não demonstrada.');
|
||||
}
|
||||
if ($d['kind'] !== 'exists' && $d['need']['state'] === 'confirmed') {
|
||||
foreach (['problem','observed_supply','observed_demand','type','clients','confirmation'] as $field) {
|
||||
if (trim($d['need'][$field] ?? '') === '') $this->fail('need.'.$field, 'Confirmação exige observação e fundamento concretos; pode guardar como hipótese.');
|
||||
}
|
||||
if (! $d['need']['evidence_ids']) $this->fail('need.evidence_ids', 'Uma hipótese não é confirmada sem evidência seleccionada.');
|
||||
foreach ($d['evidence'] as $e) {
|
||||
if (! in_array($e['id'], $d['need']['evidence_ids'], true)) continue;
|
||||
if ($e['purpose'] !== 'local') $this->fail('need.evidence_ids', 'Uma referência metodológica internacional não confirma oferta ou procura local. Preserve a hipótese e recolha evidência local.');
|
||||
foreach (['statement','source','locator','period','scope','coverage','verified_on'] as $field) {
|
||||
if (trim($e[$field] ?? '') === '') $this->fail('evidence', 'Evidência da necessidade confirmada: faltam facto, fonte, localizador, período, abrangência, cobertura ou data de verificação.');
|
||||
}
|
||||
}
|
||||
}
|
||||
return $d;
|
||||
}
|
||||
|
||||
private function document(?Opportunity $record, string $id, bool $public): void
|
||||
{
|
||||
$row = $record?->exists ? DB::table('opportunity_documents as link')->join('documents as d','d.id','=','link.document_id')
|
||||
->where('link.opportunity_id', $record->id)->where('d.id', $id)->whereNull('link.deleted_at')->first(['d.data_classification','d.status','d.malware_scan_status','d.sha256','d.malware_scanned_sha256','d.rights_status','link.payload','link.deleted_at']) : null;
|
||||
if (! $row) $this->fail('evidence', 'Documento não associado à ficha neste âmbito; reutilize o gestor documental existente.');
|
||||
if ($public && ($row->data_classification !== 'public' || $row->status !== 'active' || $row->malware_scan_status !== 'clean' || $row->sha256 !== $row->malware_scanned_sha256 || $row->rights_status === 'restricted' || data_get(json_decode($row->payload, true), 'visibility') !== 'public')) {
|
||||
$this->fail('evidence', 'Documento interno, restrito ou sem disponibilização pública: preserve a evidência interna, sem a divulgar.');
|
||||
}
|
||||
}
|
||||
|
||||
/** No private field is copied into the public summary automatically. */
|
||||
public function publication(Opportunity $record, array $input): ?array
|
||||
{
|
||||
$private = app(OpportunityManagement::class)->values($record)['proactive'] ?? null;
|
||||
if (! $private) {
|
||||
if (isset($input['proactive_public'])) $this->fail('publication', 'Prepare a análise antes de divulgar esta síntese.');
|
||||
return null;
|
||||
}
|
||||
$d = Validator::make($input, [
|
||||
'proactive_reviewed' => 'required|accepted',
|
||||
'proactive_public' => 'required|array:group,state,need,proposal,basis,limitations,next_action,evidence_ids,chain_id,stage,resources,assumptions,conditions,relation_ids',
|
||||
'proactive_public.group' => 'required|in:exists,needs,ideas',
|
||||
'proactive_public.resources'=>'nullable|string|max:2500', 'proactive_public.assumptions'=>'nullable|string|max:2500', 'proactive_public.conditions'=>'nullable|string|max:2500',
|
||||
'proactive_public.relation_ids'=>'sometimes|array|max:40', 'proactive_public.relation_ids.*'=>'uuid|distinct',
|
||||
'proactive_public.state' => 'required|in:hypothesis,confirmed', 'proactive_public.chain_id' => 'nullable|uuid', 'proactive_public.stage' => 'nullable|string|max:1000',
|
||||
'proactive_public.need'=>'required_unless:proactive_public.group,exists|nullable|string|max:2500', 'proactive_public.proposal'=>'required_if:proactive_public.group,ideas|nullable|string|max:2500',
|
||||
...collect(['basis','limitations','next_action'])->mapWithKeys(fn ($k) => ['proactive_public.'.$k => 'required|string|max:2500'])->all(),
|
||||
'proactive_public.evidence_ids' => 'present|array|max:60', 'proactive_public.evidence_ids.*' => 'uuid|distinct',
|
||||
])->validate()['proactive_public'];
|
||||
$d += ['need'=>'','proposal'=>''];
|
||||
if ($d['group'] !== $private['kind']) $this->fail('publication', 'O grupo público deve corresponder à análise guardada.');
|
||||
$proofs = [];
|
||||
foreach ($d['evidence_ids'] as $id) {
|
||||
$e = collect($private['evidence'])->firstWhere('id', $id);
|
||||
if (! $e || $e['access'] !== 'public') $this->fail('publication', 'Não pode divulgar evidência interna nem a sua fonte indirectamente. Redija uma síntese independente ou seleccione evidência pública autorizada.');
|
||||
if (! empty($e['document_id'])) $this->document($record, $e['document_id'], true);
|
||||
$proofs[] = array_intersect_key($e, array_flip(['id','category','purpose','statement','source','locator','period','scope','coverage','verified_on']));
|
||||
}
|
||||
if ($d['group'] !== 'exists' && $d['state'] === 'confirmed' && ($private['need']['state'] !== 'confirmed' || array_diff($private['need']['evidence_ids'], $d['evidence_ids']))) $this->fail('publication', 'Confirmação pública exige a necessidade confirmada e o fundamento público seleccionado; pode divulgar uma hipótese com limitações explícitas.');
|
||||
if (!empty($d['chain_id']) && !app(OpportunityClassification::class)->targets('chain')->where('id', $d['chain_id'])->exists()) $this->fail('publication', 'Cadeia de valor pública indisponível.');
|
||||
$relations=[];
|
||||
foreach ($d['relation_ids'] ?? [] as $id) {
|
||||
$r=collect($private['relations'])->firstWhere('id',$id);
|
||||
if (!$r || array_diff($r['evidence_ids'],$d['evidence_ids'])) $this->fail('publication','A relação exige o fundamento público seleccionado; nenhuma referência interna é copiada.');
|
||||
$target=app(OpportunityClassification::class)->targets($r['kind'])->where('id',$r['target_id'])->first(['id',OpportunityClassification::TARGETS[$r['kind']][1].' as name']);
|
||||
if (!$target) $this->fail('publication','Referência pública da relação indisponível.');
|
||||
$relations[]=['kind'=>$r['kind'],'target_id'=>$r['target_id'],'label'=>$target->name,'relationship'=>$r['relation'],'evidence_ids'=>$r['evidence_ids'],'basis'=>$d['basis']];
|
||||
}
|
||||
// Catch literal reuse of private statements, interpretations, references and document identities.
|
||||
$publicText = mb_strtolower(implode(' ', [...array_filter($input, 'is_scalar'), ...array_filter($d, 'is_scalar')]));
|
||||
foreach ($private['evidence'] as $e) {
|
||||
if ($e['access'] === 'public') continue;
|
||||
foreach (['statement','interpretation','source','locator','document_id'] as $key) {
|
||||
$value = trim($e[$key] ?? '');
|
||||
if (mb_strlen($value) >= 10 && str_contains($publicText, mb_strtolower($value))) $this->fail('publication', 'O resumo contém informação de evidência interna. Reveja a síntese e a divulgação indirecta antes de publicar.');
|
||||
}
|
||||
}
|
||||
return [...array_map(fn ($v) => is_string($v) ? trim(strip_tags($v)) : $v, $d),
|
||||
'version' => self::VERSION, 'relations'=>$relations, 'evidence' => $proofs, 'notice' => self::NOTICE,
|
||||
'availability_confirmed' => false, 'economic_validation' => false];
|
||||
}
|
||||
|
||||
public function publicData(Opportunity $record): ?array
|
||||
{
|
||||
$p = data_get($record->workflow_context, 'promotional_summary.projection.proactive');
|
||||
return is_array($p) && Opportunity::published()->whereKey($record->id)->exists() ? $p : null;
|
||||
}
|
||||
|
||||
public function publicationRelations(Opportunity $record): array
|
||||
{
|
||||
return collect(app(OpportunityManagement::class)->values($record)['proactive']['relations'] ?? [])->map(function($r){
|
||||
$label=app(OpportunityClassification::class)->targets($r['kind'])->where('id',$r['target_id'])->value(OpportunityClassification::TARGETS[$r['kind']][1]);
|
||||
return $label?['id'=>$r['id'],'label'=>$label,'relationship'=>$r['relation']]:null;
|
||||
})->filter()->values()->all();
|
||||
}
|
||||
|
||||
public function history(?Opportunity $record): array
|
||||
{
|
||||
if (!$record) return [];
|
||||
return DB::table('audit_events')->where('source_system', 'opportunity-management')->where('after_data->record_id', $record->id)->orderByDesc('occurred_at')->orderByRaw("(after_data->>'version')::integer DESC")->limit(30)->get()->map(function ($event) {
|
||||
$entry=json_decode($event->after_data,true);$snapshot=json_decode(Crypt::decryptString($entry['snapshot']),true);
|
||||
$draft=json_decode($snapshot['management_draft'] ?? '{}',true);$need=$draft['proactive']['need'] ?? null;
|
||||
return $need ? ['at'=>$event->occurred_at,'version'=>$entry['version'],'state'=>$need['state'],'problem'=>$need['problem'],'confirmation'=>$need['confirmation'],'evidence_ids'=>$need['evidence_ids']] : null;
|
||||
})->filter()->values()->all();
|
||||
}
|
||||
|
||||
public function options(?Opportunity $record = null): array
|
||||
{
|
||||
return ['documents' => $record ? DB::table('opportunity_documents as l')->join('documents as d','d.id','=','l.document_id')->where('l.opportunity_id',$record->id)->whereNull('l.deleted_at')->whereNull('d.deleted_at')->get(['d.id','d.file_name as title'])->all() : [], 'groups' => self::GROUPS, 'references' => collect(['project','cluster','corridor','park','chain'])->mapWithKeys(fn ($kind) => [$kind => app(OpportunityClassification::class)->targets($kind)->orderBy(OpportunityClassification::TARGETS[$kind][1])->limit(300)->get(['id', OpportunityClassification::TARGETS[$kind][1].' as name'])])->all()];
|
||||
}
|
||||
|
||||
private function fail(string $key, string $message): never
|
||||
{
|
||||
throw ValidationException::withMessages(['proactive.'.$key => $message]);
|
||||
}
|
||||
}
|
||||
@@ -1051,3 +1051,381 @@ A opção «Preparar cumulações dos tratamentosL7 registados» reutiliza coope
|
||||
Entrega agrupada preparada com os sete casos novos compatíveis;incompatibilidade e informação insuficiente acompanham o mesmo candidato como estados demonstrados. Não houve instalação nesta passagem. A futura entrega requer main compatível,capacidade do servidor medida novamente ebackup/restauro fresco,mantendo a versão activa até a nova ficar pronta. Recibo:`docs/investmoz/simulations/irpc-l7-combinations-qa-20261026.json`;provas:`outputs/irpc-l7-combinations/`. Reprodução só do delta:`node --test tests/frontend/irpc-special-combinations.test.mjs`;`php tools/irpc-special-combinations-qa.php routes`;`php tools/irpc-special-combinations-qa.php test`;`tsc --noEmit`;build com `INVESTMOZ_QA_BUILD=1`. **L7 parcial;colecta simulada distinta do saldo finalL8.**
|
||||
|
||||
Conferência de compatibilidade:main `a7434cd2` incorporado na candidata,com apresentação/catálogo e linhas não fiscais da matriz preservados. Recuperada a adenda históricaQA13 que tinha desaparecido do manual no main;isto é perda documental,não perda do cálculo13. Só tipos/build de integração foram conferidos novamente;provas fiscais aceites conservadas. A revisão servida não foi consultada nesta passagemQA.
|
||||
|
||||
## 26/10/2026 — Cumulações L7 entregues pelo Git
|
||||
|
||||
**Instalado `f8d57bddf96b4610604a013fcc5bdd703c7dc6d5`.** A anteriora7434cd2,que já incluía632dc069,fica preservada. Main/candidata compatíveis;apresentação ecatálogo sectorial entregues entretanto mantidos. A notaQA anterior é histórica:não há pendência de instalação deste incremento.
|
||||
|
||||
Medição inicial:5.06GiB,com inodes suficientes,mas sem margem para o backup fresco mais o mínimo5GiB do instalador. Recuperados0.21GiB somente da cache versionada de compilaçãoNode em`/tmp/node-compile-cache`,sem gestores de pacotes ou ficheiros abertos. Fontes,node_modules,releases,backups,logs,originais eSGF mantidos;permissões/proprietário da pasta preservados. Nova capacidade:5.26GiB e21374782inodes. Backup fresco`2026-10-26T14:20:47Z`:174tabelas/369ficheiros econfiguração;restauro isolado sem rede/55441 com174checksums iguais. Após o backup restavam5.10GiB,acima do mínimo5GiB de compilação;a guarda de um segundo backup não é requisito para repetir o backup acabado de executar. Nenhum limiar foi reduzido.
|
||||
|
||||
Só depois destas guardas,integraçãoGit sem forçar histórico;release anterior activa até a nova estar pronta. Compilação,tipos econtrolos automáticos do procedimento passaram:1054testesfrontend,API59testes/317asserções,preservação1teste/3106asserções. Reutilizadas as provasQA12testes/API133/UI/relatórios,não repetidas por iniciativa desta entrega. Conferidos4ficheiros fiscais do delta,68protegidos,31originais,369persistentes/configuração e174tabelas;172tabelas de negócio mantidas,cache/sessões reconciliadas com eventos operacionais/acessos públicos. Schema,roles/grants epermissões iguais;sem migrações/importações/escrita privada sintética. Revisão/manifest servidos,15marcadores,4assets eHTTP200 do simulador conferidos.
|
||||
|
||||
O recorte mantém a diferençaCBF16 de25MZN aplicada uma vez,com15recuperados já incluídos nos75deduzidos;depois aplica16% à base cooperativa integralmente elegível. No caso combinado,colecta496,80MZN;com despesa autónoma qualificada,512,80+35=547,80MZN. Valores são colecta simulada,não saldo finalL8. IncompatibilidadeCBF4/13,excepções sem correspondência e informação em falta permanecem explícitas;nenhum benefício é escolhido ouapagado automaticamente.
|
||||
|
||||
Após a instalação ficaram4.14GiB livres. Antes de outra compilação,voltar a resolver capacidade contra o mínimo existente e o backup dessa execução;esta entrega foi concluída e não autoriza apagar releases,backups ou provas. SaldoL7 e primeiro incrementoL8 são discriminados na secção seguinte. Recibo:`docs/investmoz/simulations/irpc-l7-combinations-delivery-20261026.json`;provas:`outputs/irpc-l7-combinations-delivery-20261026/`. **L7 parcial;L8 conserva saldo final.**
|
||||
|
||||
## 26/10/2026 — Saldo consolidado de L7 e primeiro incremento delimitado de L8
|
||||
|
||||
**L7 parcial,com a entrega de cumulaçõesf8d57bdd registada acima.** Deixam de estar pendentes de instalação a combinaçãoCIRPC12+CBF16 no recorte qualificado,a separação do imposto autónomo61(4) e os estados de incompatibilidade/falta/excepção não correspondida demonstrados. Isso não implementa todas as cumulações nem os tratamentos abaixo. Fontes oficiais e provas aceites permanecem válidas;documento em falta limita só o caso/campo que dele dependa.
|
||||
|
||||
| CódigoL7 ainda por implementar | Exemplo e condição concreta de retoma |
|
||||
| --- | --- |
|
||||
| Outras origens/segregações de despesas autónomas | Despesa100 com apenas60 correspondidos em36g ou encargo fora do resultado:ligar origem/parcela e incidência61(4),sem segundo acréscimo. |
|
||||
| Cooperativas mistas/retidas e demais entidades9–14 | Base agrária com serviços não abrangidos ou rendimentos sujeitos a retenção:segregar proveitos/custos/base e aplicar o artigo específico;não reduzir tudo a16%. |
|
||||
| ExtensõesCBF16 e outras combinações | Activo anterior a2025,usado/reabilitado/reavaliado,método/período fora da cobertura,ou excepção expressa à não cumulação:ligar regra temporal/base/método e disposição,ordem e limites à parcela;reutilizar activos/quotas,sem reescrever o passado. |
|
||||
| Mais-valias61-A e operações54–56/41-A | Ganho já incluído no resultado ou transferência de activo/perda:implementar apuramento e reconciliação próprios,sem dupla incidência ou compensação presumida. |
|
||||
| CBF17–19 e direito potencial15 | Formação/investimento com activos e despesas elegíveis/excluídos:implementar base,limite,janela temporal e compatibilidade. Direito/origem do crédito emL7;utilização anual e saldo emL8. |
|
||||
| Regimes sectoriais/territoriais e benefícios específicos | EstatutoZEE ou projecto de infra-estruturas:aplicar disposição/período efectivos e excepção quando prevista;endereço/sector não concede benefício. |
|
||||
| TransporteL7M20/M22 | Efeito calculado sem campo/edição correspondente:identificar exemplar,instrução,campo e representação;conservar o cálculo exacto independente. |
|
||||
|
||||
**Documentos por caso,distintos de código:**natureza/parcela/período;estatuto/reconhecimento exigido ou norma de excepção;saldos anteriores e distinção de exclusão temporária/permanente;disposição/ordem/limites da combinação;exemplar/edição/campo/representação. Não pedir nova validação genérica da autenticidade de fontes aceites,nem repetir pesquisas anteriores sem informação nova. Não preencher campo,código,taxa ou saldo por presunção.
|
||||
|
||||
### L8 — primeiro percurso a implementar em QA:colecta→pagamentos comprovados→saldo simulado
|
||||
|
||||
**Delimitado,não implementado ou instalado nesta passagem.** Recorte inicial:IRPC de residente no regime geral,ano civil2026,MZN,com colecta corrente determinada e suportes que permitem reconciliar o fecho. Parte de uma execuçãoL6 válida ou deL7 válida quando os efeitos aplicáveis estejam qualificados;guarda chave/versão/NUIT/período e valores de origem. Não soma colectaL6 com colectaL7 nem a colecta ordinária com uma colecta combinada que já a inclua. Não usa uma versãoL6 para ignorar um efeitoL7 positivo ou pendente que afecte o mesmo fecho. Um caso ordinário independente não espera pela implementação de outro benefício ou por um campoM20/M22 desconhecido.
|
||||
|
||||
**Dados reutilizados e qualificações novas apenas onde necessárias:**
|
||||
|
||||
1. **Colecta:**reutilizar a execução e as condições existentes,distinguindo colecta ordinária,imposto autónomo e colecta combinada. O primeiro fecho completo limita-se aos casos com ausência documentada de tributação autónoma/mais-valias que exija liquidação própria. Se existir imposto autónomo positivo,a parcela ordinária pode ser apresentada,mas não como saldo total até corresponder a articulação;não o apagar ou compensar por pressuposto.
|
||||
2. **Retenções sofridas:**reutilizarL5 apenas quando `direction=received`,natureza `on_account`,origem efectiva,documento/prova e montante sofrido reconciliados,mesmo sujeito/NUIT/período e rendimento incluído na base apropriada. Retenção entregue pela empresa por pagamento a terceiros,retenção definitiva,mera projecção,guia sem pagamento ou montante ainda não comprovado não são crédito próprio. EmL7cooperativa,a declaração de ausência de rendimentos retidos não pode coexistir silenciosamente com retenção recebida positiva;esse caso exige a segregação própria,sem bloquear o regime normal independente.
|
||||
3. **Pagamentos por conta efectuados:**registar/reutilizar comprovativo,identificador,data,exercício,sujeito e montanteMZN;reconciliar parcelas e pagamentos sem dupla utilização. Neste primeiro incremento,não calcular automaticamente a obrigaçãoPPC a partir do exercício anterior,nem transformar tesouraria prevista em pagamento efectuado.
|
||||
4. **Outros créditos/PEC:**reutilizar a informação existente e distinguir valor conhecido,ausência declarada e falta de informação. O primeiro percurso completo exige ausência documentada dePEC e créditos por dupla tributação/investimento/outros créditos ainda sem limite/ordem correspondidos. Presença positiva mantém a parcela/fecho dependente indeterminado;não usar zero. CBF15 potencialL7 não é automaticamente crédito anual utilizável. PEC não se transforma em montante reembolsável nem recebe transporte de3/5anos por presunção.
|
||||
5. **Identidade/duplicação:**contrapartes e documentos existentes são reutilizados;qualificar beneficiário e NUIT do próprio sujeito. Deduplicar por origem/documento/comprovativo e controlar afectações parciais;um comprovativo não pode aparecer integralmente em retenções ePPC,ou em dois exercícios. Preservar valores declarados e histórico,sem consumo de saldo oficial.
|
||||
|
||||
**Resultado e sequência a demonstrar:**colecta válida→deduções admissíveis e respectivas ausências→retenções efectivamente sofridas por conta→PPC comprovados→saldo aritmético→aplicação das regras de cobrança/reembolso do recorte→montante simulado a pagar ou recuperar. Mostrar a decomposição e o sinal;zero só com entradas completas ou ausência documentada. Informação em falta não transforma a colecta em saldo final. Como a base nasce do plano,o resultado continua uma simulação identificada,não autoliquidação submetida,pagamento efectuado ou reembolso deferido/recebido.
|
||||
|
||||
**Fontes já disponíveis para o cotejo dirigido de implementação:**CIRPC63/67,natureza das retenções com as alteraçõesLei12/2025;RegulamentoDecreto9/2008 art21(2–5),ordem/limites das deduções,eart27(1–2/6),pagamentos e reembolso. O exemplar aceite prevê no27(6) um mínimo de100MZN;esse parâmetro e a fronteira devem ser ligados à versão/período aplicáveis antes de activar o consumidor,não inferidos de um rótulo de formulário. O cotejo de aplicabilidade/alterações desta regra é trabalho de implementação da fonte aceite,não pedido de certificação genérica nem reabertura dos cálculosL6/L7. Arts64–66/PEC e créditos específicos mantêm as suas regras próprias;juros/multas/calendário,geração de guias,submissão e processamento de reembolso seguem incrementos próprios.
|
||||
|
||||
| Critério de aceitação a executar,sem prova reivindicada agora | Exemplo sintético proposto |
|
||||
| --- | --- |
|
||||
| Saldo positivo com pagamentos/retencões válidos | Colecta1408−retenção sofrida300−PPC500=608MZN de saldo aritmético;qualificar valor a pagar segundo a regra aplicável. |
|
||||
| Saldo negativo | Colecta1408−retenção1000−PPC600=−192MZN;identificar192 a recuperar no recorte,se a regra permitir,sem afirmar reembolso recebido. |
|
||||
| Zero e fronteiras do mínimo | Colecta1408−408−1000=0;demonstrar os lados inferior/igual/superior do mínimo do parâmetro versionado,sem arredondamento novo. |
|
||||
| Ausência vs informação em falta | Ausência documentada de retenções/PPC/outros créditos permite saldo com parcelas zero justificadas;suporte ou natureza por determinar mantém só o fecho dependente indeterminado. |
|
||||
| Reutilização e dupla dedução | Seleccionar retenção recebida e comprovativo existentes,recusar pagamento a terceiros/retenção definitiva/duplicado e demonstrar conservação dos originais e cenários anteriores. |
|
||||
| Cálculo→gravação→recuperação→relatório | Novo livro/snapshotL8 ligado à chave da colecta e às provas seleccionadas;resultado13/14 eL5 anteriores imutáveis;mudança da fonte invalida a fotografia corrente sem recalcular históricos. Relatório/exportação apresenta colecta,abatimentos,saldo e lacunas concordantes. |
|
||||
|
||||
Só serão demonstradas estas novas regras/efeitos,emQA isolada e com as guardas existentes. Fracções continuam exactas;representação/campos oficiais sem correspondência ficam identificados e não bloqueiam cálculo independente. Pagamentos noutra moeda,períodos especiais,PEC/créditos positivos,liquidação autónoma e demais situações ficam no saldo concreto deL8,com condição de retoma por regra,origem,limite,período e prova. A documentação deste recorte não é novo cálculo executável.
|
||||
|
||||
### Esforço global:referência inicial não é previsão actual
|
||||
|
||||
As240–416horas deL8–L14 permanecem identificadas como referência inicial de planeamento,não saldo actual nem prazo assumido. Antes de estimar o conjunto:reconciliar por lote o que já está implementado/reutilizável e o que falta em código;descontar provas aceites sem as repetir;separar espera documental;incluir resíduosL1–L7,integrações/entregas eL15–L16,SISA/encargos imobiliários. Campos de entrada,fontes inventariadas ou percentagens isoladas não provam percurso executável completo. Contar apenas o delta necessário e não somar duas vezes componentes partilhados. Esta passagem entregaL7 e delimitaL8;gere uma estimativa reconciliada futura,sem converter os intervalos iniciais numa promessa global. **L7 parcial;saldo finalL8 ainda não implementado nesta entrega.**
|
||||
|
||||
## 26/10/2026 — L8: primeiro saldo anual simulado demonstrado em QA
|
||||
|
||||
**QA concluído em `11a6cee9`; ainda sem instalação.** `f8d57bdd` permanece a entrega comunicada no portal. Este incremento reutiliza a colecta corrente de L6 ou o total ordinário L7 aplicável, sem somar ambos nem contornar um tratamento pendente. Recorte: sujeito residente no regime geral, ano civil de 2026, MZN, sem PEC/créditos positivos ou imposto autónomo que exijam liquidação própria. L6 operacional no âmbito demonstrado; L7 mantém o saldo parcial já discriminado. Não há nova pesquisa ou reabertura das provas aceites.
|
||||
|
||||
**Percurso executável:** «Preparar saldo anual L8» reutiliza NUIT, exercício e chave/versão da colecta sem substituir edições deliberadas. Selecciona os comprovativos L5 recebidos, efectivos, por conta e reconciliados; confirma o próprio beneficiário e a inclusão do rendimento na base do exercício. Retenções entregues pela empresa por pagamentos a terceiros, definitivas ou projectadas não são abatimentos próprios. PPC exige recibo, emitente, data, titular, exercício, moeda, montante comprovado, parcela utilizada e confirmação do pagamento efectivo; não usa previsões do plano nem calcula a obrigação PPC. A reutilização não apaga provas ou consome saldos oficiais.
|
||||
|
||||
Conhecido, ausência declarada com suporte e informação em falta são estados distintos. Ausência contraditória, titular/exercício divergente, prova em falta ou origem desactualizada mantêm o saldo dependente indeterminado. A identidade normalizada do emitente/comprovativo detecta repetição mesmo com data alterada; a mesma prova não pode ser retenção e PPC. Controla limites do comprovativo e da afectação L5, incluindo parcelas em outros contextos do mesmo dossier. São simulações alternativas, sem reserva central ou consumo de crédito fiscal entre dossiers independentes.
|
||||
|
||||
| Caso demonstrado | Resultado L8 simulado |
|
||||
| --- | --- |
|
||||
| Colecta 1 408 − retenção sofrida 300 − PPC 500 | **608 MZN a pagar**. |
|
||||
| Colecta 1 408 − retenção sofrida 1 000 − PPC 600 | Saldo aritmético −192: **192 MZN a recuperar**, sem afirmar reembolso recebido. |
|
||||
| Colecta 1 408 − retenção 408 − PPC 1 000 | Saldo zero, com parcelas completas. |
|
||||
| Ausência declarada de retenções/PPC, PEC ausente e outros créditos conhecidos zero | 1 408 MZN a pagar; estados conhecidos/ausentes conservados. |
|
||||
| PPC por comprovar, prova repetida ou PEC positivo ainda sem regra própria | Saldo a pagar/recuperar indeterminado; entradas e subtotais conhecidos conservados. |
|
||||
| Fronteiras do mínimo: saldos ±99,99 e ±100 | Aritmética exacta; abaixo de 100 MZN sem cobrança/reembolso neste recorte; em 100 aplica pagar/recuperar. Sem arredondamento ou transporte de crédito inventado. |
|
||||
| Colecta anual L7 acelerada aceite de 1 996,80, sem abatimentos declarados | Reutilizada uma vez: saldo simulado 1 996,80, sem somar a referência L6 nem recalcular o benefício. |
|
||||
|
||||
**Fontes e limites:** CIRPC arts. 63/67, Lei 34/2007 e natureza da retenção na redacção aplicável da Lei 12/2025; Regulamento Decreto 9/2008 arts. 21(2–5) e 27(1–2/6). O mínimo de 100 MZN do art. 27(6) está ligado ao recorte ordinário de 2026; as alterações IRPC do acervo de 2025 não substituem essa regra. Exemplares, páginas e hashes constam do recibo, com aceitação oficial anterior preservada. Não generalizar este parâmetro a períodos/regimes não correspondidos. PEC positivo, crédito de investimento, dupla tributação e outros créditos não recebem abatimento, limite, transporte ou reembolso presumidos. Um crédito potencial L7 não passa automaticamente a crédito utilizável L8.
|
||||
|
||||
**Gravação e recuperação:** livro opcional `irpcAnnual` no snapshot existente, por contexto, sujeito e exercício; ligado à execução da colecta e às provas L5 seleccionadas. Guarda o input e o resultado simulado, acrescenta o resultado anterior ao histórico sem o recalcular, e invalida o resultado corrente quando mudam as fontes/entradas. HTML e dossier financeiro recuperam colecta, provas/parcelas, estados, saldo, lacunas e limites concordantes. Sem preparação L8, os relatórios anteriores não ganham linhas L8. Plano, originais, livros e históricos L5–L7 permanecem imutáveis. O saldo não é declaração submetida, pagamento efectuado ou reembolso recebido.
|
||||
|
||||
**Provas novas:** 19 testes frontend dirigidos; API privada QA, 1 teste/170 asserções, sete casos com cálculo → gravação → recuperação → HTML/dossier; base isolada `simulator_fiscal_delta_20261021_test`, loopback 55441, guarda de identidade e transacção com rollback. Interface real: preparar, preencher só dados em falta, seleccionar prova, impedir repetição, pagar/recuperar/zero/ausência/indeterminação, guardar/recarregar/recuperar/exportar, sem erros de página. Wayfinder `--with-form`, TypeScript e build QA passaram. Comparação de 2 832 ficheiros anteriores: só três pontos de integração alterados, mais os cinco ficheiros novos do incremento; motores L5/L6/L7, fontes, fixtures, schema, configuração e permissões preservados; 31 originais iguais. Não se repetiram suites aceites de L3, ISPC, câmbio ou L5–L7. SGF TEMPO separado.
|
||||
|
||||
### Saldo concreto L8 após este incremento
|
||||
|
||||
| Código ainda por implementar | Condição concreta de retoma |
|
||||
| --- | --- |
|
||||
| PEC e créditos positivos: investimento, dupla tributação e outros créditos próprios | Correspondência do crédito, titular/exercício, montante efectivamente disponível, ordem, limite e transporte aplicáveis; prova de cada saldo. Não presumir reembolsabilidade ou prazo de 3/5 anos. |
|
||||
| Liquidação de imposto autónomo/61-A e articulação com o saldo anual | Segregar a parcela autónoma e corresponder quais abatimentos podem incidir sobre ela; não a ignorar nem compensar automaticamente com prejuízo/PPC. |
|
||||
| Períodos especiais e comprovativos noutra moeda | Corresponder exercício/data de afectação e regra cambial fiscal do pagamento; reutilizar periodização/câmbio existentes sem confirmar pressupostos por omissão. |
|
||||
| Cálculo da obrigação PPC/PEC, calendários, juros/multas e guias | Regra, parâmetros, factos e vencimentos próprios por período. O registo de PPC efectuado já demonstrado não calcula a obrigação. |
|
||||
| Transporte oficial M20/M22, submissão e processamento de reembolso | Edição/campo, representação de fracções e fluxo de recepção correspondidos; sem preencher campos provisórios como oficiais. |
|
||||
|
||||
**Esclarecimentos documentais aguardados:** permanecem as dúvidas concretas L5/L6/L7 já registadas, sem nova pesquisa repetida. Exemplo: cooperativa com rendimentos mistos/retidos requer segregação antes de utilizar retenção positiva; excepção de cumulação exige disposição, período e limites correspondidos; campo M20/M22 divergente requer edição/campo exactos. Cada falta só bloqueia o seu caso. Ausência de documento num cenário não bloqueia o saldo normal independente acima.
|
||||
|
||||
**Próxima entrega:** compatibilidade conferida com `origin/main` em `f8d57bdd`, sem incorporar runtime do checkout raiz. Nenhum acesso ou operação no servidor nesta passagem. Os 4,14 GiB são o valor comunicado, não medição nova; antes de instalar, medir espaço/inodes, confirmar capacidade para backup/restauro fresco e compilação isolada, mantendo a versão activa até a nova estar pronta. Recibo: `docs/investmoz/simulations/irpc-l8-first-qa-20261026.json`; provas: `outputs/irpc-l8-settlement/`. Reprodução só do delta: `node --test tests/frontend/irpc-annual-settlement.test.mjs`; `php tools/irpc-annual-settlement-qa.php routes`; `php tools/irpc-annual-settlement-qa.php test`; `tsc --noEmit`; build com `INVESTMOZ_QA_BUILD=1`. **L8 parcial, QA pronto, sem instalação.** A referência inicial de 240–416 horas L8–L14 não é previsão actual; permanece necessária a reconciliação do trabalho reutilizado, resíduos e L15–L16 antes de assumir prazo global.
|
||||
|
||||
## 27/10/2026 — entrega L8 preparada; instalação adiada por capacidade
|
||||
|
||||
**Candidato `14360748` pronto; não instalado.** A conferência SSH autenticada de 27/10, 06:05 UTC (08:05 em Moçambique), confirmou `f8d57bdd` como revisão activa e `main` remoto. Compatibilidade por ancestralidade, pacote QA e 168 ficheiros do destino conferidos: 134 ficheiros protegidos, três integrações anteriores e 31 originais. O delta executável continua limitado a cinco ficheiros L8; os 19 testes, API/170 asserções, interface, recuperação/relatórios, tipos e build aceites foram reutilizados, sem nova ronda.
|
||||
|
||||
**Impedimento concreto:** partição `/dev/md2`, montada em `/`, com 4 402 343 936 bytes livres (**4,10 GiB**) e 21 340 182 inodes disponíveis. Inodes suficientes face à referência da release (31 259 entradas). O instalador existente exige **5 GiB livres após o backup**; com a referência observada do backup anterior de 175 917 490 bytes, faltam pelo menos **1,07 GiB adicionais antes do backup**. É uma estimativa mínima de capacidade, a medir novamente; não uma autorização para reduzir o limiar. Caches regeneráveis de Composer/Node somam cerca de 0,12 GiB e não cobrem a diferença. Diagnóstico apenas por leitura, sem limpeza de caches, releases, backups, provas, dependências ou ficheiros SGF TEMPO.
|
||||
|
||||
**Decisão expressa do utilizador: «Manter a entrega preparada por agora».** Não foram executados backup/restauro frescos, integração no `main` nem instalação. A versão activa foi preservada e a sessão SSH encerrada. Na retoma, seleccionar o ramo candidato `codex/irpc-l8-settlement-qa-20261026`, voltar a conferir `main` e revisão servida, medir capacidade/espaço/inodes, executar backup/restauro fresco e compilação isolada, mantendo o activo até a nova release estar pronta. Só depois conferir a revisão servida e o delta L8. As notas desta espera ficam no ramo documental `codex/irpc-l8-delivery-capacity-20261027`; não mudam o código candidato. L8 parcial, PEC/créditos próprios separados e saldo L7 preservado. Recibo: `docs/investmoz/simulations/irpc-l8-delivery-capacity-20261027.json`; provas e auxiliares preparados: `outputs/irpc-l8-first-delivery-20261027/` no checkout raiz.
|
||||
## 27/10/2026 — identidade proactiva: primeiro incremento demonstrado em QA
|
||||
|
||||
**QA concluído em `3439f350`; sem instalação, publicação real ou análise económica validada.** Partida no `main` remoto `f8d57bdd`, conferido novamente antes da entrega. Ramo separado `codex/proactive-investment-first-qa-20261027`, worktree `C:/laragon/www/portal-investidor-proactive-qa-20261027`. A referência local `fa02c70` e o ramo `codex/proactive-investment-scope-20261027` não foram encontrados no repositório consultado; o âmbito expresso da Tempo foi suficiente e não se criou dependência desse commit. **L8 `14360748` mantém-se preparado, sem instalação e sem integração nesta candidata.** A capacidade do servidor continua fora deste trabalho local. Sem SSH, instalação, limpeza do servidor ou intervenção no SGF TEMPO nesta passagem.
|
||||
|
||||
### Diagnóstico dirigido e decisões de implementação
|
||||
|
||||
| Componente existente | Reutilização e lacuna concreta tratada |
|
||||
| --- | --- |
|
||||
| `geo_locations`, `sectors`, `value_chains`, `projects`, `economic_clusters`, `development_corridors`, `investment_zones` | Mesmos identificadores, hierarquia, sectores e referências públicas já disponíveis; selectores e catálogo existentes. Não se criaram mestres territoriais, empresas, projectos ou estruturas para completar campos em falta. |
|
||||
| `investment_gaps` e `investment_specific_needs` | Mantidos nos seus âmbitos de lacuna de cluster/cadeia e necessidade de manifestação. O schema público exige contexto de cluster/cadeia/capacidade no primeiro e submissão/opções no segundo. Não se inventam esses valores para guardar uma hipótese territorial inicial. A análise editorial é uma parte versionada do rascunho existente, não outro catálogo ou cadastro de lacunas económicas validadas. |
|
||||
| `Opportunity`, `OpportunityManagement`, `management_draft`, `audit_events` | Acrescentado só o bloco opcional `proactive`: evidências, necessidade, ideia e relações. Reutilizados identidade, chave de criação, etag, rascunho, auditoria cifrada e versões. Criação repetida não duplica a ficha; versão antiga não sobrescreve edição concorrente. |
|
||||
| Editor de oportunidades e designação interna da equipa | Lacuna confirmada: a preparação inicial exigia organização promotora até quando desconhecida. Permitida a preparação/edição de análise proactiva sem promotor real apenas no âmbito da designação interna existente. Organização real fica nula; operador e responsável continuam identificados. Sem novo papel, aprovador, grant activo ou permissão universal. Os restantes percursos mantêm as condições anteriores; actores não designados e operadores de outro âmbito são recusados. |
|
||||
| `portal_resources`, `documents`, `opportunity_documents` e gestor documental existente | Referência ao documento já associado, fonte, exemplar, localizador, período, abrangência, cobertura e verificação. Não copia o binário nem altera direitos, classificação ou scan. Documento interno/restrito ou fora do âmbito não passa a público pelo formulário da análise. Listas de empresas, hotéis e restaurantes continuam inicialmente internas. |
|
||||
| `OpportunityPromotion` e catálogo/ficha existentes | Síntese expressamente pública, prévia e confirmação no fluxo já autorizado, com MFA normal. Nenhum texto interno é preenchido automaticamente. Estado da necessidade e estado da publicação são independentes. Consulta anónima só da versão publicada. |
|
||||
| `InvestorContext`, escolhas por oportunidade, `desk_cases`, `InvestorPath` e simulador | A origem, versão, território, sector, cadeia/etapa, relações públicas seleccionadas, pressupostos e limites seguem no contexto cifrado do dossier existente. Selecções múltiplas conservam uma fotografia por ideia; o consumidor/simulador recebe só a escolha em tratamento. Título e outras edições deliberadas são preservados. Sem regra fiscal nova ou benefício inferido da localização. |
|
||||
|
||||
### Implementado e demonstrado
|
||||
|
||||
- **Evidência:** actividades, recursos, infra-estruturas, oferta e procura; facto separado da interpretação. Finalidade local ou metodológica, acesso interno ou público autorizado e documento associado opcionais. Duplicação de evidência ou da mesma referência na análise é recusada. Informação em falta permanece em falta.
|
||||
- **Necessidade:** problema, oferta/procura observadas, quantidade/qualidade/logística/transformação/coordenação/apoio, clientes/beneficiários, fontes, limites e pendências. Pode guardar como hipótese. Confirmação exige os campos/fundamento e evidências locais seleccionadas com proveniência/cobertura/período/verificação; referência internacional, por si só, não confirma procura local. Histórico mostra hipótese e confirmação anteriores sem recalcular nem apagar os originais.
|
||||
- **Ideia:** solução, actividade, cadeia existente/etapa, abrangência, recursos, criar/expandir/associar, pressupostos, condições, pendências e próxima acção. Relações com estruturas existentes mantêm a qualificação documentada, hipotética ou proximidade. Nenhuma relação cria contrato, energia acessível, terra disponível, participação ou benefício fiscal.
|
||||
- **Aplicabilidade:** “O que existe” mostra evidências e contexto; “Necessidade” acrescenta a lacuna; “Ideia” acrescenta a solução. Campos anteriores ficam conservados quando ocultos. Não se exigem montante, promotor, coordenadas ou uma oportunidade previamente publicada para iniciar a preparação da equipa.
|
||||
- **Divulgação:** grupos “O que existe”, “Necessidades identificadas” e “Ideias de investimento” no catálogo existente; a consulta de oportunidades cadastradas conserva a verificação de disponibilidade na respectiva ficha. Uma ideia não é convertida em oportunidade com participação disponível. Textos públicos são redigidos separadamente, com revisão expressa da exposição directa/indirecta. Evidências internas e cópias literais detectadas são bloqueadas; uma confirmação pública depende do fundamento público seleccionado. Relações divulgadas transportam apenas referência pública, qualificação e base pública, sem copiar a referência privada.
|
||||
- **Continuidade:** criar → guardar → recuperar → editar → prévia/publicação em QA → consulta anónima → autenticação → dossier → recarregar/retomar sessão. Login e MFA Fortify normais demonstrados com contas sintéticas QA. O mesmo contexto chega ao dossier, sem substituir o título deliberado do investidor. Relatório existente mostra origem, estado, fundamento, evidências, relações, pressupostos, limites e próximo passo por ideia; sem preparação proactiva não acrescenta linhas.
|
||||
|
||||
### Referências metodológicas do Ruanda — dependência resolvida
|
||||
|
||||
O responsável forneceu os dois caminhos após a procura dirigida inicial. Exemplares acessíveis, originais preservados e hashes conferidos antes/depois. **Não foram importados ou publicados no portal.** Texto integral extraído e imagens de leitura ficam apenas nas provas privadas/ignoradas; o pacote entrega rastreabilidade e paráfrases metodológicas, sem os originais ou a reprodução integral dos diapositivos.
|
||||
|
||||
| Exemplar e passagem utilizada | Aplicação delimitada |
|
||||
| --- | --- |
|
||||
| `20070627_Rwanda_5d0cc43d-c990-4cf1-8ee9-ada71094918f.pdf`, 31 páginas, capa “Creating a Competitive Rwanda”, Michael E. Porter/HBS, Kigali, Junho2007. SHA256 `18b07a9379a1ad0baa33697d57d6237f15a6fec346db44bfee7506bf1fa27dee`. P14, “Improving the Business Environment: The Diamond”; P27, “Role of the Private Sector in Economic Development”, conferidas visualmente. | Perguntar por factores de produção, procura, fornecedores, actividades e serviços de apoio; distinguir relação documentada de acesso/compromisso. Cada afirmação sobre Moçambique precisa de evidência local própria. |
|
||||
| `Rwanda Competitiveness Briefing_Prof Porter_OTF.ppt`, 50 diapositivos na leitura nativa PowerPoint, capa “How Rwanda Competes Today”, RNIC, briefing para Prof. Porter, 20Julho2008. SHA256 `4a9325ad64278cb0ef3c60367a05ee2ed9262e2cd49a48d579061349914aa830`. Slide17, procura turística, fonte/amostra/período visíveis; slide20, constrangimentos por etapa da cadeia do chá; slide24, diagnóstico mineiro, texto em ordem nativa. | Conservar fonte, período, abrangência e cobertura/amostra das observações; estruturar etapas e limitações em vez de presumir uma lacuna. Dados, valores, projecções e instituições estrangeiras não são transferidos para os pilotos nem para regras fiscais. Slide17 conferido visualmente;20/24 lidos em texto nativo, sem alegar conferência visual desses dois. |
|
||||
|
||||
Os caminhos completos e os trechos/limites estão no recibo. O PDF2007 e o briefing2008 são exemplares distintos. Os 91 grupos de texto históricos encontrados numa exploração OLE não foram usados como número de diapositivos; a ordem nativa de 50 é a referência do PPT. A metodologia internacional orienta perguntas e organização; não demonstra procura em Cahora Bassa, Montepuez ou Gurué.
|
||||
|
||||
### Guia curto de utilização em QA
|
||||
|
||||
1. Entre na conta da equipa com a designação existente e abra **Minhas oportunidades → Nova oportunidade → Preparar análise e ideia**. Escolha título, sector e nível territorial conhecidos. O promotor real pode ficar por identificar; não são necessários montante ou coordenadas.
|
||||
2. Acrescente evidências. Separe o facto da interpretação e preencha fonte/exemplar, localizador, período, abrangência, cobertura e data de verificação. Marque referências internacionais como **metodológicas** e listas internas como **internas**. Use o documento já associado quando disponível.
|
||||
3. Mantenha a necessidade como **hipótese** enquanto faltar fundamento local. Para confirmar, explicite problema, observações, tipo, beneficiários, fundamentação e evidências locais. “Confirmada” não significa viabilidade comercial demonstrada. Guarde com motivo e recupere o rascunho; o histórico conserva o fundamento anterior.
|
||||
4. Quando aplicável, escolha **Ideia de investimento** e prepare solução/actividade, cadeia/etapa, recursos, relações e próxima acção. A proximidade fica identificada como proximidade. Escolhas existentes e campos ocultos continuam conservados.
|
||||
5. Abra **Divulgação promocional — Em preparação**. Redija os campos públicos separadamente, seleccione só evidências públicas e relações autorizadas, reveja a exposição directa/indirecta, prepare a prévia e confirme **apenas em QA**. A referência privada da relação e os documentos internos não são copiados. A revisão editorial continua humana no fluxo existente; o controlo literal não é validação semântica de todas as inferências possíveis.
|
||||
6. Consulte sem sessão em `/oportunidades?perspective=ideas` (ou `exists`/`needs`). **Iniciar ou continuar o roteiro deste investimento** utiliza a autenticação e o dossier existentes. Confirme o contexto na prévia antes de guardar; pode continuar um dossier ou criar um novo. Para várias ideias, escolha a que está em tratamento nos consumidores. O simulador recebe o contexto e conserva os seus dados/regras próprios; não calcula sem dados ou pressupostos explícitos.
|
||||
|
||||
**Reprodução técnica só do delta:** `php tools/proactive-investment-qa.php routes` (`--with-form`); `php tools/proactive-investment-qa.php test`; `node --test tests/frontend/proactive-investment.test.mjs`; `tsc --noEmit`; build com `INVESTMOZ_QA_BUILD=1`. Base isolada `proactive_investment_20261027_test`,127.0.0.1:55441, clonada do QA anterior com o mesmo schema/identificadores; guarda de identidade e rollback nos testes. Flags existentes de perfis/contratos especializados/percurso foram configuradas só no bootstrap QA; `.env`, configuração activa e grants activos não mudaram. O servidor HTTP de prova usou127.0.0.1:18760, não a homologação.
|
||||
|
||||
### Provas, preservação e saldo concreto
|
||||
|
||||
**Passaram:**14 testes da API/139asserções;7testes frontend de relatório/isolamento por ideia;Wayfinder,TypeScript ebuildQA;interface real com login/MFA,criação/edição/recuperação,histórico,perguntas aplicáveis,prévia/publicação QA,consulta anónima,contexto após autenticação,recarregar/retomar sessão,relações/pressupostos e ausência de erros de página. Casos Cahora Bassa/energia,Montepuez/mineração eGurué/chá são **inequivocamente sintéticos**,reutilizando distritos e sectores existentes. Não se publicou uma análise económica real nem se validou um mercado.14testes não são nova ronda de L3/ISPC/câmbio/L5–L8.
|
||||
|
||||
**Preservado:**15pontos de integração anteriores e7ficheiros novos de código/testes/guarda;89ficheiros de motores fiscais e31originais fiscais iguais,mais os2originais Ruanda intactos. Sem migrações ou novo catálogo/base territorial/sistema de permissões. Sem escrita na base origem ou activa;fixtures/grants sintéticos apenas no clone QA. A candidataL8 `14360748` conserva exactamente a mesma referência. O checkout raiz recebe somente este registo documental,sem integrar o runtime do ramoQA.
|
||||
|
||||
| Estado | Saldo e condição concreta de retoma |
|
||||
| --- | --- |
|
||||
| Implementado e demonstrado neste incremento | Percurso editorial técnico completo acima, no recorte QA e com os estados/limites visíveis. Pode preparar novos investimentos sem depender de oportunidades publicadas. |
|
||||
| Parcial — conteúdo económico real dos três pilotos | Recolher oferta/procura locais,exemplares,períodos,cobertura e informação de clientes/beneficiários;relacionar recursos/serviços com evidência. Só os casos apoiados por esses dados podem mudar de hipótese. Nenhuma falta bloqueia outra análise independente. |
|
||||
| Dependência documental/comercial | Contrato/encomenda,energia acessível,terra,participação disponível e condições comerciais precisam de prova específica por caso. A qualificação formal da oportunidade continua nos campos/fluxos existentes;este incremento não a presume a partir da localização,lista de empresas ou necessidade. Listas e contactos privados exigem síntese autorizada e revisão editorial no fluxo actual antes de qualquer divulgação. |
|
||||
| Dependência resolvida | Os dois exemplares Ruanda foram localizados/lidos nos trechos identificados;deixam de constar como ficheiros indisponíveis. A sua existência não substitui a evidência local. |
|
||||
| Trabalho futuro,fora do primeiro incremento | Automatizar inventário,indicadores,comparação/priorização e eventual IA;quantificar mercado/custos/rentabilidade só com dados/pressupostos explícitos;eventual correspondência a lacunas mestre de cluster quando os seus campos e fundamento forem conhecidos. Não há novo prazo global ou implantação activa reivindicados. |
|
||||
| Entrega futura no destino | CandidataQA peloGit apenas. Conferir o main vigente e compatibilidade com outros incrementos antes de integrar;capacidade,backup/restauro e instalação são uma execução separada autorizada. A espera de capacidade deL8 não foi contornada. |
|
||||
|
||||
Recibo:`docs/investmoz/unification/proactive-investment-first-qa-20261027.json`;provas:`outputs/proactive-investment-20261027/`. Não há novos cálculos fiscais,submissão AT,publicação na homologação ou alteração do SGF TEMPO.
|
||||
|
||||
## 27/10/2026 — primeiro caso proactivo com fontes reais: Cahora Bassa / apoio metrológico
|
||||
|
||||
**Análise preliminar privada demonstrada em QA, sobre o runtime aceite `3439f350` / candidata `1afab4a2`, sem nova alteração funcional ou instalação.** Caso `CB-METROLOGIA-20261027`, ficha QA `401`, dossier privado QA `894343c7-c33d-452e-a6a5-b6675f77ee23`. O operador é uma conta sintética QA já existente; os factos e referências desta análise são reais e identificados, distintos dos cenários fictícios anteriores. Não se publicou a análise, não se contactou comprador ou prestador e não se transportaram contactos, documentos pessoais ou NUIT das listas. L8 `14360748` conserva a mesma referência e continua separado. Main remoto conferido: `f8d57bdd`; sem SSH, limpeza, instalação ou intervenção no SGF TEMPO.
|
||||
|
||||
### Escolha do piloto e fontes reutilizadas
|
||||
|
||||
| Piloto | Resultado da triagem dirigida |
|
||||
| --- | --- |
|
||||
| **Cahora Bassa — seleccionado** | A lista empresarial fornecida contém referências históricas locais de reparação/manutenção mecânica e eléctrica. O acervo inclui a reprodução histórica da concessão HCB. Foram acrescentados o relatório primário HCB2024, a página institucional de engenharia e, decisivamente, o Plano de Compras HCB2026 publicado pelo IGEPE, que delimita um serviço concreto de calibração. É uma decisão por disponibilidade de fundamento nesta ronda, sem ranking de rentabilidade ou potencial económico. |
|
||||
| Montepuez | Há referências empresariais internas e fontes mineiras localizadas. Não foi escolhido nesta ronda um âmbito primário de aquisição tão directamente utilizável para esta aplicação. Não se conclui que falte actividade ou procura; continua elegível para outro caso documentado. |
|
||||
| Gurué | Há referências históricas internas ligadas ao chá e perfis/fontes públicos localizados. Os constrangimentos antigos encontrados não bastam para atribuir automaticamente uma lacuna actual à cadeia do chá. Não foram transpostos para a proposta de Cahora Bassa. |
|
||||
|
||||
Inventário anterior de606 fontes preservado e consultado; listagem dirigida dos documentos acessíveis no acervo e triagem dos dois workbooks empresariais/cadastro turístico ficam nas provas privadas. Os workbooks têm grãos/períodos/versões distintos e registos repetidos: não se somaram os totais entre eles nem se contou uma denominação repetida como várias empresas. O cadastro de alojamento de3–5estrelas não demonstrou cobertura distrital comparável neste recorte; não demonstra ausência de hotéis ou serviços e não foi usado para inferir procura metrológica.
|
||||
|
||||
| Evidência / exemplar | Âmbito usado e limite |
|
||||
| --- | --- |
|
||||
| HCB, **Relatório e Contas2024**, edição bilingue,63páginas PDF; PDFp9/página impressa14. URL `https://hcbadm.mzbusiness.com/wp-content/uploads/2025/08/Relatorio-e-Contas-2024-Bilingue-VF-1.pdf`. SHA256 `d0fed6af0e40fffd6f7f385152fdbfff2a10cae0b66c9d7a59a0a99658758080`. | Actividade e infra-estruturas existentes da HCB. Página conferida visualmente; não é carteira de contratos disponíveis. Matambo não é atribuída ao distrito de Cahora Bassa. |
|
||||
| HCB, **Plano Anual de Compras2026**,8páginas; PDFp1,2.ª/3.ªlinhas de dados. URL `https://igepe.org.mz/wp-content/uploads/2026/06/HCB-Plano-Anual-de-Aquisicoes-2026.pdf`. SHA256 `cbc93102fea61a712c193d1c1815e7ec19e7d570ee2703c1b1390d4c05e5bd8e`. | Duas entradas de calibração de equipamento de medida e monitorização, concurso limitado, previsões19/02–30/06 e05/05–14/09/2026. Em27/10/2026 os prazos previstos já passaram. Plano não confirma procedimento aberto, adjudicação ou procura ainda insatisfeita. “1” em “Qtde de Itens” não é número de instrumentos; linhas de igual designação não provam dois contratos independentes. Conferência visual da tabela. |
|
||||
| Lista fornecida **Empresas Licenciadas.xlsx**, `Servicos Tempo/Relatorios/novos/docs`, folha`EMPRESAS`; SHA256 `1b5087b464e39e88c42def39655c2391aaaf684b4c832d6a77ff274b98889f00`. | Pistas internas: L19376,D19376,O19376:P19376,U19376:V19376 e L55640,D55640,O55640:P55640,U55640:V55640. Licenças2018/2021, não capacidade actual. Linhas12243/19376/65567 repetem denominação e não são contadas como três empresas. Nenhuma lista/contacto foi copiada para publicação. |
|
||||
| **CAE eBAU.xlsx** fornecido, folha`CAE`, B857/F857 e B859/F859. | Etiquetas de33120 — reparação/manutenção de máquinas/equipamentos e33140 — equipamento eléctrico, lidas no exemplar fornecido. Não comprovam calibração, qualificação, acreditação ou vigência actual de licença; não se declarou uma versão oficial actual do catálogo sem identificação. Hash/caminho no recibo. |
|
||||
| **HCB-TERMOS-DO-CONTRATO-DE-CONCESSAO.pdf** fornecido, página única; BR I Série47,21/11/2007,Decreto57/2007,artigo2. SHA256 `f4afc62f140d197cae3bf395674adce2eba37f0436261d52d7eb554f6230a073`. | Contexto documental histórico da actividade, conferido visualmente. Sem análise da vigência actual ou aplicação de regra ao novo investimento. Direitos de concessão não se tornam direitos do promotor. Original preservado, não importado/publicado. |
|
||||
| Página institucional HCB`https://www.hcb.co.mz/hidroelectricidade`, consultada27/10/2026. | Contexto do complexo e CAPEX Vital; sem data editorial precisa ou progresso actualizado de cada obra. Não comprova contratação adicional. Captura/hash privados; sem copiar projecções para o orçamento da ideia. |
|
||||
|
||||
Os exemplares Ruanda já aceites continuam apenas metodológicos; não se repetiu a sua prova nem se usaram como evidência de procura local. Os cinco originais locais usados permanecem com hashes iguais. Fontes públicas adicionais foram guardadas como cópias privadas de consulta, sem importação, publicação ou alteração de direitos no portal.
|
||||
|
||||
### Actividade, necessidade e ideia estruturada
|
||||
|
||||
**O que existe:** actividade hidroeléctrica e infra-estruturas HCB documentadas; registos históricos locais de actividades de reparação/manutenção. **Necessidade documental:** o comprador planeou serviços de calibração em2026. **Hipótese por verificar:** existe procura residual/recorrente e uma vantagem concreta de apoio local no Songo. Não há evidência de falta de fornecedores, atrasos, preços elevados ou adjudicação disponível; a necessidade comercial mantém o estado **hipótese**, com esse fundamento guardado.
|
||||
|
||||
**Ideia:** estudar associação entre prestador local e laboratório qualificado para apoio metrológico à HCB no Songo: inventário/gestão de instrumentos, preparação, recolha/entrega controlada e acompanhamento documental. Calibração/ensaios só por quem demonstrar competência no âmbito contratado. A associação é uma proposta, não acordo. **Cliente potencial:** HCB, apenas nas unidades e procedimentos em que o serviço se justifique; outros clientes não foram presumidos. Etapa: apoio à manutenção na produção/transporte de electricidade. Sem criar cadeia mestre ou relação canónica para preencher uma correspondência não disponível no clone. Abrangência distrital/proposta no Songo, sem parcela, instalações, energia ou acesso assegurados.
|
||||
|
||||
**Condições:** confirmar requisitos efectivos do comprador e do âmbito metrológico, capacidade, rastreabilidade, segurança/acesso, responsabilidades, regras de associação/transporte e eventual acreditação exigida. Não se impôs certificação específica por interpretação do plano. Recursos de operação, equipa, instrumentos, veículo, instalações e laboratório ainda não estão assegurados. Montante, promotor empresarial, coordenadas exactas, preços, volume, mercado, receitas e rentabilidade permanecem por determinar; sem usar zero ou totais do plano como substitutos.
|
||||
|
||||
### Demonstração deste caso e continuidade
|
||||
|
||||
Criada pela interface existente,guardada,recuperada e conferida na mesma ficha privada. Cinco evidências preservadas;necessidade comercial como hipótese;campos de clientes,oferta,procura,condições e próxima acção recuperados sem alteração. A mesma contaQA preparou um dossier privado pelo percurso existente,confirmou o contexto e recuperou a fotografia da ideia pela API autenticada. O relatório existente produziu as cinco linhas de evidência e os mesmos limites;uma leitura privada de prova reúne essas linhas e as observações do caso. Nenhuma publicação promocional foi preparada ou confirmada. Ficha permanece`draft`,fora da consulta publicada;consulta anónima do dossier recusada.
|
||||
|
||||
Reutilizadas as14provas API/139asserções,7provas frontend,tipos ebuild de`1afab4a2`;não se repetiu a ronda técnica ou fiscal. Feita apenas aplicação e conferência do novo caso real. A primeira leitura da página do dossier antecedeu o fim da gravação do contexto;após recuperação concluída,interface eAPI concordaram. Corrigida a espera no script local de prova,sem mudar código da aplicação ou regravar históricos. Preservação por hash das linhas anteriores no mesmo clone:52fichas,17dossiers,19projectos,1921territórios,12sectores,63documentos;uma ficha e um dossier novos. Sem migrações,importação de empresas,novos grants ou alteração do destino activo.
|
||||
|
||||
**Para consultar ao retomar QA:**usar a contaQA já designada e abrir`/minhas-oportunidades/401/edit`;comparar os campos/fundamentos;abrir o dossier`/investimentos/894343c7-c33d-452e-a6a5-b6675f77ee23`. É um percurso privado,não um link público nem uma nova instalação. Recibo:`docs/investmoz/unification/proactive-real-pilot-qa-20261027.json`;provas privadas:`outputs/proactive-real-pilot-20261027/`. Cookies,credenciais,extractos integrais de listas,originais e ficheiros de diagnóstico não integram o pacote de entrega.
|
||||
|
||||
### Saldo e perguntas concretas de retoma
|
||||
|
||||
| Ponto | Exemplo/pergunta e condição de retoma |
|
||||
| --- | --- |
|
||||
| Procura actual e estado das compras | As entradas terminavam em30/06 e14/09/2026:foram executadas,adjudicadas,canceladas ou reprogramadas? Existe novo ciclo em2027? Retoma da qualificação comercial apenas com estado e necessidade residual/recorrente identificados pelo comprador. |
|
||||
| Âmbito técnico e operacional | Que famílias/instrumentos,quantidades,periodicidade,local de execução e prazo de devolução se aplicam? Que qualificação/rastreabilidade/acreditação é exigida neste âmbito? Obter a especificação antes de dimensionar meios ou afirmar elegibilidade. |
|
||||
| Oferta e associação | Os dois registos internos seleccionados continuam activos,interessados e tecnicamente aptos? Que laboratório pode assumir o âmbito? Verificar capacidade/competência,consentimento e oferta concorrente;cadastro/CAE não basta. Não enviar contactos ou listas automaticamente. |
|
||||
| Vantagem e viabilidade | O apoio no Songo reduz um problema mensurável do cliente face à solução actual? Comparar transporte,prazos,risco,custos e condições;quantificar só quando houver dados. Não comprar equipamento ou criar orçamento com base apenas no plano. |
|
||||
| Divulgação ou uso no activo | Preparar eventual síntese pública separada só quando autorizada/revista;instalação do código não publica nem transporta automaticamente a ficha e o dossierQA. Capacidade,compatibilidade e backup/restauro serão tratados na execução futura aplicável. Nenhuma dependência de capacidade impede esta análise privada. |
|
||||
|
||||
**Estado:**primeira aplicação real demonstrada,análise económica/comercial preliminar. Preparadas perguntas para reunião exploratória com a HCB,sem as enviar. L8eSGF preservados;limites e pendências anteriores não foram eliminados.
|
||||
|
||||
## 27/10/2026 — orientação confirmada: oportunidades geradas pela procura
|
||||
|
||||
**Decisão expressa do responsável:** “a ideia não é gerir concursos mas sim as oportunidades que geram”. O anúncio é uma fonte de procura para preparar oportunidades complementares; não se cria um circuito de concursos, candidaturas ou adjudicações. O percurso técnico aceite em`1afab4a2` continua preparado para entrega independentemente da confirmação comercial do caso. Instalação e capacidade do servidor seguem separadas;sem nova intervenção no destino ou no SGF TEMPO. L8`14360748`preservado.
|
||||
|
||||
**Caso privado QA — evolução da mesma ficha e dossier:**ficha401,versão1→2;dossier`894343c7-c33d-452e-a6a5-b6675f77ee23`,contexto1→2. Sete evidências recuperadas. Modelo centrado em serviço recorrente de apoio metrológico no Songo,associando apoio local e laboratório competente:inventário/calendário,preparação,recolha/entrega controlada e documentação. Cliente potencial inicial:HCB. Outros clientes dependem de identificação própria. Sem contrato,parceria,procura recorrente ou vantagem económica declarados como confirmados. Título e campos deliberados do dossier conservados;fotografia anterior e388eventos de auditoria existentes intactos. Não se criou outra ficha,dossier,empresa,grant ou regra fiscal.
|
||||
|
||||
### O que a nova fonte esclarece
|
||||
|
||||
- **Procura e âmbito:**o anúncio da HCB,de17/08/2026,referência051/2026,identifica quinze famílias de instrumentos e outros a especificar nos TdR;por exemplo,manómetros,balanças,paquímetros/micrómetros,multímetros e instrumentos de análise eléctrica. O PDF tem2páginas,ambas lidas visualmente;SHA256`bb4c33064e5d49504d8a85ac88ad1b847cfa6c69e1016e3ab588ff785b205c1f`;exemplar`https://www.diarioeconomico.co.mz/wp-content/uploads/2026/08/concurso-hcb-tender-document-docu-mo-ambique-2026-1.pdf`. Não contém volumes,gamas,incertezas,periodicidade ou execução. O prazo04/09/2026é histórico,não oportunidade aberta presumida. Não se mapeou automaticamente este procedimento a uma das duas linhas do plano.
|
||||
- **Qualificação:**o anúncio específico pede licença para o serviço,acreditação/credenciação para calibração,três anos de experiência,três referências e equipa qualificada. Isso esclarece aquela contratação;não se converte em condição para preparar a nova oportunidade nem em requisito universal para todo apoio logístico/metrológico futuro. A execução técnica de calibração deve corresponder à competência/âmbito e aos requisitos efectivos do serviço a prestar.
|
||||
- **Possível prestação laboratorial:**a ficha pública IPAC`M0100`,INNOQ–Laboratório de Metrologia,Maputo,anexo17/02/2026,publica capacidades por âmbito:inclui electricidade,pesagem e pressão com gamas,incertezas e condições de local. Fonte`https://www.ipac.pt/pesquisa/ficha_lac.asp?ID=M0100`,consultada27/10/2026. É uma entidade a consultar sobre serviços,sem acordo ou capacidade disponível confirmados. Não se estende a cobertura a todas as famílias da HCB ou a uma instalação no Songo. Os prestadores históricos locais continuam por verificar.
|
||||
|
||||
A consulta pública dirigida não localizou prova identificável de adjudicação/execução ou compromisso para2027. Isso não prova que não houve contrato,que a compra continua aberta ou que existe procura por satisfazer. Rótulos“Em Curso” e campos0,00dos agregadores não são preço,volume ou estado confirmado. Não prolongar a mesma pesquisa sem novo documento ou resposta do cliente. O estado da compra passada é contexto para a procura futura,não o produto a gerir.
|
||||
|
||||
### Preparação da oportunidade e condição de retoma
|
||||
|
||||
| Questão de negócio | Informação concreta a obter e uso |
|
||||
| --- | --- |
|
||||
| Problema do cliente e recorrência | Que problema operacional existe no ciclo dos instrumentos,como é resolvido hoje e que necessidade futura permanece? Identificar instrumentos,quantidades,frequências e horizonte. Compra satisfeita pode cobrir só um ciclo;não autoriza presumir recorrência. |
|
||||
| Âmbito da prestação | Por família/modelo/gama,pontos e incerteza:que trabalho é exigido,onde pode ocorrer e com que prazo? Separar inventário/logística/documentação local da execução técnica da calibração. |
|
||||
| Parceiros e recursos | Confirmar capacidade real,disponibilidade e interesse dos prestadores locais e de laboratório(s). Corresponder âmbito a instrumentos concretos,com responsabilidades,custódia,segurança e condições comerciais;nenhum parceiro é designado automaticamente. |
|
||||
| Valor e receitas | Testar menor custo total,menos tempo fora de serviço ou melhor organização/rastreabilidade,sem os declarar como benefícios já medidos. Serviço por lote ou avença são hipóteses de receita,sem preço ou vontade de pagar conhecidos. |
|
||||
| Vantagem económica | Comparar solução actual e proposta para o mesmo âmbito,volume,qualidade,local e período:serviço laboratorial,transporte/retorno,embalagem/seguro,apoio local e custos incrementais sem duplicação. Medir prazos separadamente;monetizar impacto operacional só com base fornecida. Valores e vantagem permanecem indeterminados. |
|
||||
|
||||
**Resultados úteis previstos pelo responsável:**(1)procura recorrente/problema/interesse demonstrados→corresponder parceiros e dimensionar o serviço;(2)ciclo actual satisfeito,necessidade futura documentada→reformular horizonte;(3)cliente confirma necessidade satisfeita e sem necessidade futura para a solução→arquivar a hipótese com essa conclusão e conservar o dossier;(4)informação insuficiente→manter hipótese privada,sem declarar ausência de procura. Nenhum desses estados impede a entrega técnica do percurso proactivo.
|
||||
|
||||
Perguntas de descoberta e comparação foram preparadas,sem envio a terceiros. A ficha mantém`hypothesis`/`draft`,sem publicação. O contexto foi actualizado pelo mecanismo existente de prévia/confirmação e recuperado com os sete fundamentos;relatório existente reproduz as novas linhas. Sem alteração de código da aplicação,migração,novas entidades ou repetição das provas técnicas/fiscais aceites. Apenas a própria ficha e o seu dossier mudaram;52outrasfichas,17outrosdossiers,19projectos,1921territórios,12sectores,63documentos e históricos anteriores preservados.
|
||||
|
||||
Recibo:`docs/investmoz/unification/proactive-opportunity-model-qa-20261027.json`;análise privada actual:`outputs/proactive-commercial-followup-20261027/opportunity-private-brief.html`. A versão anterior da prova continua conservada. Esta passagem consolida o modelo da oportunidade e o saldo de validação comercial;não instala ou publica uma oportunidade real.
|
||||
|
||||
## 27/10/2026 — hipótese regional: outros clientes e sustentabilidade do apoio metrológico
|
||||
|
||||
**Pedido do responsável:** estudar outros clientes regionais,frequência,custos e capacidade dos parceiros,sem transformar sinais de procura em gestão de concursos. **Dado comercial expresso:** “Ainda não há dados comerciais”. A ficha permanece privada e a entrega técnica do percurso continua independente desta validação. Mantém-se`1afab4a2`como candidata técnica aceite,runtime`3439f350`,sem instalação nesta passagem. L8`14360748`eSGF TEMPO preservados.
|
||||
|
||||
**Resultado delimitado:** há base documental para prospectar três entidades adicionais — Vulcan/Moatize,EDM/Tete–Moatize e Nacala Logistics/segmentoMoatize — mas não há procura,recorrência,preço ou capacidade disponível confirmados para este serviço. Não se afirmou sustentabilidade,mercado dimensionado ou clientes contratados. A mesma ficha401e o dossier`894343c7-c33d-452e-a6a5-b6675f77ee23`foram actualizados da versão/contexto2para3,com11evidências. Origem Cahora Bassa/Energia,localização canónica,título e campos deliberados do dossier conservados;abrangência comercial regional identificada separadamente.
|
||||
|
||||
| Prospecto | Facto e fonte usados | Hipótese comercial e limite |
|
||||
| --- | --- | --- |
|
||||
| Vulcan Mozambique/Moatize | A própria empresa descreve mina,processamento de carvão e equipamentos produtivos em`https://www.vulcaninternational.com/products-services/`,consultado27/10/2026,página sem data editorial identificada. | Verificar instrumentos de processo/manutenção e necessidade de apoio metrológico. Não foi recebido pedido nem inventário;capacidade de produção da mina não é volume de calibração. |
|
||||
| EDM/Tete–Moatize | **Plano de Actividades e Orçamento2025**,PDFp68/página impressa68,Direcção de Transporte:linha3,calibração/reparação de equipamentos de teste;linha7,activos deMoatize/móvelTete;linha17,automaçãoSETete. Fonte`https://cdn.edm.co.mz/website/imprensa/Plano_Actividades_Orcamento_2025.pdf`,86páginas;conferidos visualmente apenas a página68e o detalhe relevante. Hash/cópia privada no recibo. | Serviço de calibração planeado a nível empresarial em2025 e referências regionais não demonstram parcela de procura actual emTete. Identificar unidade compradora,inventário e solução actual. O orçamento não é preço unitário,receita ou mercado regional. Não atribuir activosHCBàEDM ou contá-los duas vezes. |
|
||||
| Nacala Logistics/Moatize | A empresa descreve operação ferroviária atéMoatize e manutenção preventiva em`https://www.nacalalogistics.com/quem-somos/`e`https://www.nacalalogistics.com/faq/`,consultados27/10/2026. Na secção Accionistas,as concessionárias identificam Vulcan Mozambique como accionista. | Verificar instrumentos de manutenção e entidade/centro de compra. A marca agrega concessionárias;não equivale a uma contraparte contratual única. A ligação comVulcan impede assumir diversificação independente;não se somaram volumes ou clientes confirmados. |
|
||||
| Mphanda Nkuwa/GMNK — futuro separado | Descrição institucional em`https://www.gmnk.co.mz/en/about-us/project-description/`,consultada27/10/2026,qualifica o projecto em desenvolvimento. | Sem entrada na procura recorrente de base,receita ou carga de trabalho actual. Retomar apenas com necessidade e horizonte concretos;não inferir encomenda da capacidade projectada ou localização. |
|
||||
|
||||
As páginas institucionais confirmam apenas os factos no seu âmbito;relevância metrológica de mineração/ferrovia e interesse em apoio associado são inferências a testar,identificadas como tal. Fontes,exemplar,data e hashes foram guardados em provas privadas;nenhuma empresa,lista,documento ou relação canónica foi importado/publicado. As referências históricas de parceiros locais e o âmbitoIPAC/INNOQjá demonstrado foram reutilizados,sem repetir a pesquisa nem alargar automaticamente a cobertura técnica.
|
||||
|
||||
### Dados mínimos por cliente e parceiro
|
||||
|
||||
Por **cliente/centro de compra**:instrumentos,famílias/modelos/gamas,pontos e critério de aceitação;quantidade por janela e programa efectivo;prazo fora de serviço;prestador,processo e custo actuais;necessidade ainda não satisfeita;interesse e condições de pagar por lote/missão ou avença. Frequência permanece indeterminada e deve vir do programa do proprietário;sem regra anual por defeito,sem converter prazo de anúncio ou quinze famílias em quantidade/recorrência.
|
||||
|
||||
Por **parceiro**:âmbito de competência e local permitido por instrumento;capacidade efectivamente disponível em cada janela,equipa,meios,prazo e preço. Verificar capacidade actual dos prestadores locais históricos,sem confundir reparação/CAEcom acreditação de calibração. O âmbito publicado doINNOQ–LMemMaputo é pista parcial,não reserva de capacidade nem cobertura de todas as famílias. Famílias não correspondidas continuam separadas das compatíveis.
|
||||
|
||||
### Comparação económica delimitada
|
||||
|
||||
A unidade de comparação é a **missão/lote**:mesmo âmbito,quantidade,qualidade,local e período que a solução actual. A contribuição da missão é a receita acordada menos laboratório,apoio directo,transporte de ida/retorno,embalagem/seguro e outros custos incrementais dessa missão. Custos de transporte partilhado entram uma vez;custos fixos incrementais são deduzidos uma vez no período,sem os duplicar também na contribuição. Para sustentabilidade,avaliar ainda investimento,reposição de meios,fundo de maneio e prazos de recebimento;resultado operacional isolado não basta.
|
||||
|
||||
Comparar atendimento individual noSongo,missões agrupadas Songo–Tete/Moatize com janelas compatíveis e uma organização de apoio emTete/Moatize com deslocação aoSongo. Essas alternativas são hipóteses de funcionamento,não mudança de localização,cotação de rota ou recomendação de investimento já aprovada. Nenhum quilómetro,custo de deslocação,preço,volume,receita,margem,poupança ou ponto de equilíbrio foi inventado. A agregação pode partilhar logística e também criar custos,prazos ou restrições de custódia;isso tem de ser medido.
|
||||
|
||||
**Condição de retoma:** obter inventários/programas e interesse dos prospectos;identificar entidade compradora e concentraçãoVulcan/Nacala;com o mesmo âmbito pedir propostas de laboratório,apoio local e transporte;comparar as alternativas e a solução actual. Sem esses dados,o resultado útil é “carteira regional prospectável,sustentabilidade por demonstrar”. Se os dados posteriores mostrarem procura insuficiente ou serviço já satisfatório,conservar essa conclusão e reformular/arquivar a hipótese. Não repetir pesquisa pública para substituir dados comerciais que o responsável confirmou ainda não existirem. Nenhuma mensagem foi enviada a terceiros.
|
||||
|
||||
**Preservação e prova desta evolução:**guardar→prévia/confirmação do contexto→recuperação no mesmo dossier→linhas do relatório existente,com11evidências e valores comerciais em falta. Apenas ficha401e o seu dossier foram actualizados;52outrasfichas,17outrosdossiers,19projectos,1921territórios,12sectores,63documentos e391eventos anteriores de auditoria intactos. Sem nova entidade,grant,migração,código da aplicação ou ronda das provas técnicas/fiscais aceites. Fonte e contexto anteriores conservados,sem publicar a ficha.
|
||||
|
||||
Recibo:`docs/investmoz/unification/proactive-regional-clients-qa-20261027.json`;estudo privado:`outputs/proactive-regional-clients-20261027/regional-private-brief.html`. A entrega técnica e a eventual instalação continuam separadas do estado comercial desta oportunidade.
|
||||
|
||||
|
||||
## 27/10/2026 — passagem à prospecção e segundo piloto territorial privado
|
||||
|
||||
**Decisão do responsável:** o caso de apoio metrológico está suficientemente estruturado para prospecção. Fica privado e pendente de informação externa; não continuar a aprofundá-lo para concluir a funcionalidade. Nenhum contacto ou proposta comercial foi recebido ou enviado nesta passagem. A ficha401 e o dossier `894343c7-c33d-452e-a6a5-b6675f77ee23` mantêm fonte/contexto3, sem alterações.
|
||||
|
||||
**Ficha curta para a equipa:** `docs/investmoz/unification/prospeccao-apoio-metrologico-20261027.pdf`, PDF preenchível de duas páginas e42campos, com uma página por cliente e outra por parceiro. Cliente: instrumentos/gamas/quantidades, programa efectivo e janelas, requisitos, solução actual, contratação e próxima acção. Parceiro: âmbito, equipa/meios e capacidade disponível, prazo, preços discriminados, impostos/moeda, deslocações/custódia e validade da proposta. Sem resposta, os dados ficam por determinar. Guardar uma cópia por entidade/centro de compra ou parceiro, com evidência/data e responsável.
|
||||
|
||||
**Retoma da viabilidade do Songo:** quando chegarem inventários, programas, interesse e cotações comparáveis, actualizar a comparação já preparada para o mesmo âmbito, volume, qualidade, local e período. Distinguir entidade, utilizador e centro que decide/paga; a ligação Vulcan/Nacala impede presumir compradores independentes. Somar cada missão/transporte partilhado uma vez. Não usar ausência de resposta como ausência de procura ou zero. Necessidade satisfeita pode conduzir a reformulação futura ou arquivo fundamentado, preservando o dossier.
|
||||
|
||||
**Próximo piloto — Gurué:** foi criado, por serviços existentes e apenas na base QA isolada, o caso `GUR-CHA-20261027`, ficha402/fonte1 e dossier `883c8ec3-59a3-4074-b91c-b7d4a5d88ff0`/contexto1. Ideia privada: estudar apoio associado à colheita, qualidade da folha verde e organização das entregas na cadeia do chá. Reutilizados o distrito canónico de Gurué e o sector Agronegócio; nenhum novo mestre, promotor empresarial, montante ou coordenada presumidos.
|
||||
|
||||
Cinco referências distinguem actividade de procura: INE2020–2024, edição2025, PDFp9/Quadro1.1; página do próprio Asian Tea Group sobre Chá de Magoma; IGC2014, PDFp75,78–79/impressas60,63–64; e referências privadas da lista já fornecida, com datas2021–2023 e códigos declarados. INE e produtor documentam actividades; o estudo2014 é histórico e orienta perguntas, sem transportar volumes, preços, capacidades ou intenções para2026. Cadastros antigos não comprovam competência ou disponibilidade actual. Não se presume compra de folha externa, oferta em falta, nova fábrica ou interesse em contratar.
|
||||
|
||||
**Acção delimitada do Gurué:** compreender como se colhe, avalia e entrega hoje; identificar problema mensurável, intervenientes, critérios do processador, quantidades/janelas, solução/custo actuais e quem contrataria/pagaria pelo apoio. Magoma é unidade potencial a consultar; Chazeiras é referência histórica cuja situação actual deve ser confirmada. Beneficiário não equivale a pagador. Necessidade, parceiros, custos e viabilidade permanecem em hipótese, sem bloquear a funcionalidade técnica ou exigir prolongamento de pesquisa pública.
|
||||
|
||||
**Demonstração apenas do delta:** criação→gravação→prévia/confirmação→recuperação→linhas do relatório existente, com5evidências e pressupostos visíveis. Conservados todos os53registos anteriores de oportunidades,18dossiers,19projectos,1921territórios,12sectores,63documentos,394eventos de auditoria,40utilizadores e3organizações. Novos apenas a ficha/dossier/percurso QA e respectivos registos de histórico. Sem alteração de código, schema, permissões ou provas técnicas/fiscais aceites. O formulário foi reaberto e ensaiado com valores sintéticos numa cópia; a versão para a equipa está em branco, com campos interactivos verificados e as duas páginas revistas visualmente.
|
||||
|
||||
**Entrega técnica independente:** `1afab4a2` continua candidata técnica aceite, runtime `3439f350`, sem instalação ou publicação nesta passagem. A capacidade do servidor deve ser novamente medida no procedimento da futura entrega; não se declarou resolvida nem se apagou conteúdo. L8 `14360748`, SGF TEMPO e demais provas preservados. Esta passagem não envia a ficha a terceiros nem publica oportunidades reais.
|
||||
|
||||
Recibo: `docs/investmoz/unification/proactive-handoff-gurue-qa-20261027.json`. Prova privada e nota do piloto: `outputs/proactive-handoff-gurue-20261027/gurue-proof.json` e `gurue-private-brief.html`. Saldo do Songo: recolha externa; saldo do Gurué: descoberta dirigida da necessidade; saldo da instalação: capacidade e procedimento de entrega. Estes três estados permanecem independentes.
|
||||
|
||||
|
||||
## 27/10/2026 — autonomia pela interface e candidata técnica consolidada
|
||||
|
||||
**Âmbito pedido:** reutilizar as provas aceites; demonstrar apenas anexar respostas, rever a ideia privada e encaminhar/actualizar o mesmo dossier pela interface, sem intervenção de código ou SQL na operação da equipa. Songo aguarda respostas externas e Gurué mantém a hipótese agrícola privada; ambos ficaram intactos. Não foram recolhidas respostas comerciais reais nem observada uma sessão de formação com funcionários.
|
||||
|
||||
### Guia curto da equipa
|
||||
|
||||
1. Entrar com o perfil operacional já autorizado e o MFA normal. Em **Minhas oportunidades → Nova oportunidade → Preparar análise e ideia**, indicar título, sector e apenas o território conhecido. Não substituir o promotor real por quem prepara a análise; a preparação interna permite que ainda seja desconhecido.
|
||||
2. Em **Evidências e proveniência**, separar facto e interpretação, identificar fonte/exemplar, trecho, período, abrangência e limitações. Manter **Interna — análise privada**. Guardar o rascunho e aguardar a confirmação do servidor.
|
||||
3. Para uma resposta recebida, abrir **Imagens, documentos e localizações → Documentos**, escolher o original, identificar emissor/versão/data quando conhecidos, página e afirmação fundamentada. Escolher classificação e consulta internas e **Guardar recurso**. O ficheiro fica privado e o seu estado de scan é visível; o download só fica disponível após scan limpo dos mesmos bytes.
|
||||
4. Regressar ao rascunho e escolher esse ficheiro em **Documento existente associado** na evidência correspondente. Rever a oferta/procura observadas, solução, pressupostos, pendências e próxima acção. Uma resposta parcial não confirma procura, preços ou sustentabilidade. Guardar e recuperar a ficha para conferir os dados.
|
||||
5. Usar **Preparar ou continuar investimento com esta ficha**. Se já existir, escolher o dossier e **Preparar neste dossier**; não criar outro para uma nova edição. Criar um dossier apenas para um investimento novo, com o título escolhido e consentimento de reutilização do próprio perfil.
|
||||
6. Confirmar a localização, usar **Rever dados antes de guardar**, conferir divergências e impactos e **Guardar dados do investimento**. O título e as edições deliberadas conservam-se. A referência à resposta acompanha a análise; o original permanece no gestor documental da ficha, acessível pelo link da ficha de origem e seus recursos, sem cópia ou divulgação automática dos bytes.
|
||||
7. Para novas respostas/edições, voltar à mesma ficha, guardar a revisão e continuar o mesmo dossier com nova prévia/confirmação. O dossier recebe a versão actual após confirmação; o estado anterior conserva-se no histórico. Informação em falta continua por determinar, sem zero presumido.
|
||||
8. **Divulgação promocional** é uma acção separada. Nada neste percurso publica o piloto, os anexos ou o dossier. A eventual decisão de publicação real continua independente da demonstração sintética e da instalação técnica.
|
||||
|
||||
### Delta demonstrado e correcção delimitada
|
||||
|
||||
Ensaio com o operador QA existente, login/MFA normais e apenas controlos da interface: nova ficha sintética403, resposta PDF de ensaio anexada e recuperada, ClamAV real limpo, hash do download igual ao original; documento associado à evidência; ideia revista; dossier `5bc28554-a2d1-4e60-9181-93ba0ecede59` criado e depois continuado sem duplicação. Fonte4/contexto2, hipótese e título deliberado preservados. O anexo e os dados são sintéticos; não constituem resposta de clientes ou parceiros reais.
|
||||
|
||||
Foi reproduzido e corrigido um aviso enganador: o pedido de complementos públicos tratava uma análise privada autorizada como referência pública desaparecida. **InvestmentComplements** consulta primeiro a autorização existente e devolve uma lista vazia para essa preparação privada; não a transforma em oferta pública. Origens públicas continuam a produzir os seus complementos; pedidos sem acesso continuam sem obter a fonte privada. Dois testes novos dirigidos,18asserções, passaram em transacção QA. A demonstração privada foi retomada sem o aviso. Não se alteraram permissões, tabelas, frontend ou motores fiscais.
|
||||
|
||||
Todos os54registos anteriores de oportunidades,19dossiers,63documentos,19projectos,1921territórios,12sectores,3organizações e399eventos de auditoria preservados por comparação de hashes. Novos apenas a amostra QA e seus registos. As provas anteriores de criação/edição, publicação expressa, anonimato, histórico, relatório, Wayfinder, TypeScript e build foram reutilizadas; não se repetiram suites fiscais ou a análise económica dos pilotos. Foi conferida a recuperação da referência documental e das novas linhas pelo relatório existente.
|
||||
|
||||
### Candidata para instalação futura
|
||||
|
||||
Runtime desta correcção: `51d536b7`; inclui o percurso técnico `3439f350`/candidata aceite `1afab4a2`, documentação e ficha de prospecção `403c444a`. A comparação com main remoto `f8d57bdd` confirmou ancestralidade, sem alterações entretanto integradas a perder. O delta de runtime face à candidata anterior limita-se à consulta de complementos; frontend, schema e configuração mantêm-se.
|
||||
|
||||
**Não instalado.** Antes da entrega activa, medir novamente espaço/inodes na partição do instalador e dos backups, confrontar com a necessidade efectiva de compilação isolada/backup, conferir o main então actual, executar backup/restauro fresco e manter a versão activa até a nova estar pronta. Depois conferir revisão servida e apenas o delta. A preparação dos pilotos QA não integra dados na base activa nem publica oportunidades. L8 `14360748` permanece separado; SGF TEMPO intocado. Não se fizeram SSH, limpeza, backup ou instalação nesta passagem.
|
||||
|
||||
Recibo: `docs/investmoz/unification/proactive-team-autonomy-qa-20261027.json`. Provas e pacote local: `outputs/proactive-team-autonomy-20261027/`. A verificação comprova que o percurso está disponível aos perfis autorizados através da interface; não declara formação da equipa, viabilidade dos pilotos ou conclusão integral dos requisitos nacionais.
|
||||
|
||||
|
||||
## 27/10/2026 — duas entregas autorizadas: L8 primeiro, percurso proactivo depois
|
||||
|
||||
O responsável autorizou expressamente a execução das duas entregas pelo procedimento existente, sem nova ronda de autorização. A indicação histórica de manter preparado em `c85e772d` foi reconciliada: o commit acrescenta documentação de capacidade, sem mudar o código de L8 `14360748`/runtime `11a6cee9`. A autorização actual permite retomar; não substitui a medição de capacidade nem o backup/restauro frescos.
|
||||
|
||||
**Etapa1:** L8 em `c85e772d`, com a colecta válida, retenções efectivamente sofridas e PPC comprovados no recorte aceite; PEC e créditos próprios continuam separados. **Etapa2:** ramo `codex/sequential-delivery-20261027`, merge de L8 e do percurso proactivo `0ff402a1`, runtime reconciliado `74f7f93a`. A etapa2 só segue após confirmar a revisão efectivamente servida na etapa1.
|
||||
|
||||
O relatório comum tinha um conflito de imports. Foram conservados ambos e as chamadas de linhas anuais e proactivas. Os restantes ficheiros de runtime de cada candidata ficaram idênticos à origem. Verificação apenas da integração partilhada:6linhas anuais e10linhas proactivas recuperadas, entradas intactas e sem inferência cruzada. TypeScript e compilação QA isolada passaram; suites económicas/fiscais aceites não repetidas. Documentação de ambas as linhas conservada, sem importação de fixtures ou escrita em bases.
|
||||
|
||||
**Estado efectivo desta passagem: preparado, sem instalação.** O main remoto permanece `f8d57bdd` e a revisão pública servida foi conferida por HTTP em27/10/2026,10:14UTC, também `f8d57bdd`. A ponte SSH local estava `closed`; a autenticação por chave foi recusada com a chave do servidor registada e conferida. Não havia aqui uma sessão autenticada utilizável. Não foram executados backup/restauro frescos, alteração de main ou instalação. A capacidade antiga de4,10GiB é histórica e não foi apresentada como medição actual.
|
||||
|
||||
Retomar na sessão local com SSH autenticado, usando a autorização já registada: medir espaço/inodes na partição efectiva, comparar com compilação e backup, conferir main e revisão activa, criar e ensaiar backup fresco, instalar L8 e conferir apenas o seu delta. Depois repetir as guardas necessárias para a candidata conjunta e conferir o delta proactivo preservando L8. Manter a versão activa até a nova estar pronta. Excluir fixtures QA dos inputs de instalação; não executar seeders/importações de amostras, não publicar pilotos privados nem usar o pacote QA como cópia da base activa. SGF TEMPO separado.
|
||||
|
||||
Recibo de preparação: `docs/investmoz/unification/sequential-delivery-preparation-20261027.json`. Provas e instrução de passagem: `outputs/sequential-delivery-20261027/`. Os recibos de execução e as duas revisões servidas serão registados apenas depois de execução real na sessão autenticada; este recibo não os substitui.
|
||||
|
||||
|
||||
## 27/10/2026 — L8 e percurso proactivo instalados pela sequência autorizada
|
||||
|
||||
Entrega1: **L8 `c85e772d`**, anterior `f8d57bdd`. Entrega2, apenas após conferir a primeira: **percurso proactivo `9fda6d6e`**, incluindo `56c0c6a7` e preservando L8. As duas revisões foram conferidas no registo do instalador e no recurso público `/build/revision.json`, com hash do manifest e marcadores compilados dos deltas. `c85e772d` conserva o código aceite de `14360748`; o merge proactivo mantém ambos os fornecedores de linhas do relatório. A referência final servida passa a `9fda6d6e`.
|
||||
|
||||
A tentativa proactiva em `56c0c6a7` não foi activada: um teste dependia de um ficheiro de outputs existente apenas no QA local. L8 permaneceu em serviço. A correcção `9fda6d6e` torna esse teste portátil com um exemplar mínimo sintético da projecção pública da API, sem perfis, credenciais ou pilotos reais e sem escrita em outputs. O teste dirigido passou; o código da aplicação é byte a byte idêntico a `56c0c6a7`. Não se transportou a base QA nem se saltou a guarda do instalador. A nova tentativa usou o backup/restauro ainda fresco, com capacidade e fonte activa novamente conferidas.
|
||||
|
||||
A ligação SSH foi restabelecida pelo responsável na janela local, sem credenciais na conversa ou nos recibos. A medição inicial encontrou91,6GiB livres e inodes suficientes; a capacidade foi novamente conferida depois de cada backup. Instalador existente e suas guardas preservados; a versão anterior permaneceu activa até a nova release estar pronta. Os controlos automáticos do instalador foram mantidos, sem nova ronda manual das provas funcionais/económicas aceites.
|
||||
|
||||
**Backup/restauro fresco em cada etapa:** `/var/backups/investmoz-sequential-20261027/l8/backup` e `/var/backups/investmoz-sequential-20261027/proactive/backup`. Em cada uma, dump consistente e369ficheiros persistentes/configuração verificados; restauro das174tabelas num contentor sem rede, porta55441, com contagens/checksums iguais. Recibos `backup-receipt.json`, `restore-receipt.json`, `schema-permissions-before.json`, `schema-permissions-after.json`, `preservation-receipt.json` e `operational-delta-receipt.json` conservados nesses directórios. Hashes exactos no recibo consolidado.
|
||||
|
||||
**Preservação demonstrada:**172tabelas de negócio intactas em cada comparação; apenas cache/sessões operacionais reconciliados individualmente por identidade/timeouts e pedidos públicos de entrega. Schema, papéis, grants, permissões e originais persistentes conservados. Fontes instaladas comparadas aos commits:996ficheiros após L8 e1000após o proactivo. Sem migrations na base activa, importação de amostras QA, seeders ou publicação dos pilotos. O instalador manteve base e storage sintéticos isolados; o storage QA fica fora da árvore servida, e a release usa os mesmos `.env` e storage persistentes por ligação.
|
||||
|
||||
**Âmbito:** L8 continua parcial, com PEC e créditos de regra própria separados; os resultados continuam simulações. Songo permanece privado e pendente de respostas externas; Gurué continua hipótese agrícola privada. Disponibilização técnica não confirma clientes, procura, sustentabilidade ou publicação comercial. L3, ISPC, câmbio, L6/L7 e SGF TEMPO preservados.
|
||||
|
||||
Recibo consolidado: `docs/investmoz/unification/sequential-delivery-installed-20261027.json`. Provas locais: `outputs/l8-proactive-install-20261027/`. Os recibos históricos de preparação/suspensão mantêm-se como histórico e deixam de representar pendência de instalação destas duas candidatas.
|
||||
|
||||
Recibo remoto consolidado: `/var/backups/investmoz-sequential-20261027/installed-receipt.json`;SHA256 `62584b5abb50a05303a24379a0563e8dc147e25e682dc3566bb8edf015ba9d0b`. A fixture sintética portátil é apenas input de teste, sem importação na aplicação e sem dados dos pilotos.
|
||||
|
||||
|
||||
## 27/10/2026 — utilização real do percurso proactivo: exercício preparado, execução por observar
|
||||
|
||||
Reutilizadas a entrega `9fda6d6e` e as provas técnicas aceites. Roteiro no manual existente, secção «avaliação de utilização pela equipa, sem Codex»: análise privada de trabalho → evidências com proveniência → ideia com hipótese/pendências → guardar/recuperar → mesmo dossier → revisão sem duplicação. A equipa utiliza a própria conta autorizada e devolve referências internas, passo, dificuldade concreta e apoio consultado. Estado desta avaliação: **pendente de execução real**, sem resultados de participantes inventados e sem nova aprovação obrigatória da entrega.
|
||||
|
||||
As quatro linhas proactivas existentes (RF-CLU-003, MASTER-471012ab-0010, MASTER-9dee08d0-0067 e MASTER-471012ab-0067) conservam as provas e limitações; esta nota não promove os requisitos globais a concluídos. Não houve testes técnicos, nova instalação, alteração no portal ou contacto externo. Songo/Gurué privados; L8 parcial, PEC/créditos próprios separados. Registo: `docs/investmoz/unification/proactive-team-use-evaluation-20261027.json`. Retoma: tratar apenas os obstáculos observados pela equipa.
|
||||
|
||||
@@ -0,0 +1,789 @@
|
||||
{
|
||||
"status": "L7_combinations_installed",
|
||||
"installed": {
|
||||
"status": "installed",
|
||||
"commit": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"release": "/var/www/investmoz-homologacao/releases/f8d57bddf96b4610604a013fcc5bdd703c7dc6d5-7a31e8ac",
|
||||
"previous_release": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"database_migrations": 0,
|
||||
"content_imports": 0
|
||||
},
|
||||
"previous_installed": "a7434cd27c09df3d8e6c586f9676b67abcde798e",
|
||||
"preserved_fiscal_delivery": "632dc069",
|
||||
"backup": {
|
||||
"stage": "/var/backups/investmoz-irpc-l7-combinations-delivery-20261026/backup",
|
||||
"created_at": "2026-10-26T14:20:47Z",
|
||||
"target": {
|
||||
"database": "teste_investidor",
|
||||
"port": 5432
|
||||
},
|
||||
"tables": 174,
|
||||
"files_verified": 369,
|
||||
"dump_sha256": "2a069fcda7a89368323cda9d5339e76e545b85088de594c1e5a585891dd7b3c3",
|
||||
"files_sha256": "289ebdcb8cf1983f8fcdb237d3fb947d43fbe71a575064cede233368d43b4584",
|
||||
"restore_verified": false
|
||||
},
|
||||
"restore": {
|
||||
"restore_verified": true,
|
||||
"tables_verified": 174,
|
||||
"container_network": "none",
|
||||
"database": "irpc_l7_combinations_restore_20261026",
|
||||
"port": 55441,
|
||||
"source_dump_sha256": "2a069fcda7a89368323cda9d5339e76e545b85088de594c1e5a585891dd7b3c3",
|
||||
"active_database_writes": 0
|
||||
},
|
||||
"backup_restore_verified": true,
|
||||
"capacity_before_recovery": {
|
||||
"checked_at_UTC": "2026-10-26T14:16:50.285126+00:00",
|
||||
"installed": {
|
||||
"status": "installed",
|
||||
"commit": "a7434cd27c09df3d8e6c586f9676b67abcde798e",
|
||||
"release": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"previous_release": "/var/www/investmoz-homologacao/releases/632dc06930d6b4f1b012feb3b4daa3b1cfc53f39-4c020686",
|
||||
"database_migrations": 0,
|
||||
"content_imports": 0
|
||||
},
|
||||
"current_link": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"release_revision": {
|
||||
"commit": "a7434cd27c09df3d8e6c586f9676b67abcde798e",
|
||||
"branch": "main",
|
||||
"built_at": "2026-10-26T14:07:54.031522+00:00",
|
||||
"manifest_sha256": "06af8bbd9ffabeac215cbb0357531f4e4169955461d8cfac380f3776e923e64e"
|
||||
},
|
||||
"service": "MainPID=0\nExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
|
||||
"volumes": [
|
||||
{
|
||||
"path": "/var/www/investmoz-homologacao/releases",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5430136832,
|
||||
"available_inodes": 21367883,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/investmoz-deploy",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5430136832,
|
||||
"available_inodes": 21367883,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/backups",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5430136832,
|
||||
"available_inodes": 21367883,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/tmp",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5430136832,
|
||||
"available_inodes": 21367883,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/docker",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5430136832,
|
||||
"available_inodes": 21367883,
|
||||
"total_inodes": 29089792
|
||||
}
|
||||
],
|
||||
"free_bytes": 5430136832,
|
||||
"existing_pipeline_minimum_bytes": 5368709120,
|
||||
"observed_previous_backup_bytes": 175918494,
|
||||
"same_partition_release_and_backup": true,
|
||||
"space_guard_satisfied": false,
|
||||
"current_release_entry_reference": 31237,
|
||||
"inodes_available_vs_reference": true,
|
||||
"inode_note": "Observed current release footprint for scale;no new arbitrary inode threshold. Capacity rechecked after fresh backup.",
|
||||
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604",
|
||||
"active_writes": 0
|
||||
},
|
||||
"regenerable_Node_cache_recovery": {
|
||||
"at_UTC": "2026-10-26T14:18:26.184720+00:00",
|
||||
"target": "/tmp/node-compile-cache",
|
||||
"kind": "Node versioned compilation cache;source and node_modules retained;regenerable by Node",
|
||||
"files_removed": 6893,
|
||||
"logical_bytes": 206715844,
|
||||
"free_before": 5429366784,
|
||||
"free_after": 5652504576,
|
||||
"recovered_bytes": 223137792,
|
||||
"installed_record_unchanged": true,
|
||||
"directory_owner_permissions_preserved": true,
|
||||
"projects_releases_backups_originals_logs_untouched": true,
|
||||
"active_business_writes": 0
|
||||
},
|
||||
"capacity_before": {
|
||||
"checked_at_UTC": "2026-10-26T14:19:01.971003+00:00",
|
||||
"installed": {
|
||||
"status": "installed",
|
||||
"commit": "a7434cd27c09df3d8e6c586f9676b67abcde798e",
|
||||
"release": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"previous_release": "/var/www/investmoz-homologacao/releases/632dc06930d6b4f1b012feb3b4daa3b1cfc53f39-4c020686",
|
||||
"database_migrations": 0,
|
||||
"content_imports": 0
|
||||
},
|
||||
"current_link": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"release_revision": {
|
||||
"commit": "a7434cd27c09df3d8e6c586f9676b67abcde798e",
|
||||
"branch": "main",
|
||||
"built_at": "2026-10-26T14:07:54.031522+00:00",
|
||||
"manifest_sha256": "06af8bbd9ffabeac215cbb0357531f4e4169955461d8cfac380f3776e923e64e"
|
||||
},
|
||||
"service": "MainPID=0\nExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
|
||||
"volumes": [
|
||||
{
|
||||
"path": "/var/www/investmoz-homologacao/releases",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5652262912,
|
||||
"available_inodes": 21374782,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/investmoz-deploy",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5652262912,
|
||||
"available_inodes": 21374782,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/backups",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5652262912,
|
||||
"available_inodes": 21374782,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/tmp",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5652262912,
|
||||
"available_inodes": 21374782,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/docker",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5652242432,
|
||||
"available_inodes": 21374780,
|
||||
"total_inodes": 29089792
|
||||
}
|
||||
],
|
||||
"free_bytes": 5652262912,
|
||||
"existing_pipeline_minimum_bytes": 5368709120,
|
||||
"observed_previous_backup_bytes": 175918494,
|
||||
"same_partition_release_and_backup": true,
|
||||
"space_guard_satisfied": true,
|
||||
"current_release_entry_reference": 31237,
|
||||
"inodes_available_vs_reference": true,
|
||||
"inode_note": "Observed current release footprint for scale;no new arbitrary inode threshold. Capacity rechecked after fresh backup.",
|
||||
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604",
|
||||
"active_writes": 0
|
||||
},
|
||||
"capacity_after_backup": {
|
||||
"checked_at_UTC": "2026-10-26T14:22:54.407089+00:00",
|
||||
"installed": {
|
||||
"status": "installed",
|
||||
"commit": "a7434cd27c09df3d8e6c586f9676b67abcde798e",
|
||||
"release": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"previous_release": "/var/www/investmoz-homologacao/releases/632dc06930d6b4f1b012feb3b4daa3b1cfc53f39-4c020686",
|
||||
"database_migrations": 0,
|
||||
"content_imports": 0
|
||||
},
|
||||
"current_link": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"release_revision": {
|
||||
"commit": "a7434cd27c09df3d8e6c586f9676b67abcde798e",
|
||||
"branch": "main",
|
||||
"built_at": "2026-10-26T14:07:54.031522+00:00",
|
||||
"manifest_sha256": "06af8bbd9ffabeac215cbb0357531f4e4169955461d8cfac380f3776e923e64e"
|
||||
},
|
||||
"service": "MainPID=0\nExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
|
||||
"volumes": [
|
||||
{
|
||||
"path": "/var/www/investmoz-homologacao/releases",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5472501760,
|
||||
"available_inodes": 21374766,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/investmoz-deploy",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5472501760,
|
||||
"available_inodes": 21374766,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/backups",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5472501760,
|
||||
"available_inodes": 21374766,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/tmp",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5472501760,
|
||||
"available_inodes": 21374766,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/docker",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 5472501760,
|
||||
"available_inodes": 21374766,
|
||||
"total_inodes": 29089792
|
||||
}
|
||||
],
|
||||
"free_bytes": 5472501760,
|
||||
"existing_pipeline_minimum_bytes": 5368709120,
|
||||
"observed_previous_backup_bytes": 175918494,
|
||||
"same_partition_release_and_backup": true,
|
||||
"space_guard_satisfied": false,
|
||||
"current_release_entry_reference": 31237,
|
||||
"inodes_available_vs_reference": true,
|
||||
"inode_note": "Observed current release footprint for scale;no new arbitrary inode threshold. Capacity rechecked after fresh backup.",
|
||||
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604",
|
||||
"active_writes": 0
|
||||
},
|
||||
"post_backup_existing_build_minimum_satisfied": true,
|
||||
"post_backup_next_fresh_backup_guard_not_required_for_already_completed_backup": true,
|
||||
"capacity_after_installation": {
|
||||
"checked_at_UTC": "2026-10-26T14:29:30.537317+00:00",
|
||||
"installed": {
|
||||
"status": "installed",
|
||||
"commit": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"release": "/var/www/investmoz-homologacao/releases/f8d57bddf96b4610604a013fcc5bdd703c7dc6d5-7a31e8ac",
|
||||
"previous_release": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"database_migrations": 0,
|
||||
"content_imports": 0
|
||||
},
|
||||
"current_link": "/var/www/investmoz-homologacao/releases/f8d57bddf96b4610604a013fcc5bdd703c7dc6d5-7a31e8ac",
|
||||
"release_revision": {
|
||||
"commit": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"branch": "main",
|
||||
"built_at": "2026-10-26T14:26:51.629481+00:00",
|
||||
"manifest_sha256": "367be71b25b56a83571d610e211ea11beae2af87989d62ef6cc7b9c54eabf580"
|
||||
},
|
||||
"service": "MainPID=0\nExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
|
||||
"volumes": [
|
||||
{
|
||||
"path": "/var/www/investmoz-homologacao/releases",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 4441751552,
|
||||
"available_inodes": 21342698,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/investmoz-deploy",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 4441751552,
|
||||
"available_inodes": 21342698,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/backups",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 4441751552,
|
||||
"available_inodes": 21342698,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/tmp",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 4441747456,
|
||||
"available_inodes": 21342697,
|
||||
"total_inodes": 29089792
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/docker",
|
||||
"mount": "/dev/md2 / ext4",
|
||||
"device": 2306,
|
||||
"available_bytes": 4441747456,
|
||||
"available_inodes": 21342696,
|
||||
"total_inodes": 29089792
|
||||
}
|
||||
],
|
||||
"free_bytes": 4441751552,
|
||||
"existing_pipeline_minimum_bytes": 5368709120,
|
||||
"observed_previous_backup_bytes": 175918494,
|
||||
"same_partition_release_and_backup": true,
|
||||
"space_guard_satisfied": false,
|
||||
"current_release_entry_reference": 31259,
|
||||
"inodes_available_vs_reference": true,
|
||||
"inode_note": "Observed current release footprint for scale;no new arbitrary inode threshold. Capacity rechecked after fresh backup.",
|
||||
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604",
|
||||
"active_writes": 0
|
||||
},
|
||||
"next_delivery_capacity_adjustment_required": true,
|
||||
"delta": [
|
||||
{
|
||||
"path": "resources/js/lib/irpc-special.ts",
|
||||
"sha256_LF": "aea0e55b9317ca8ebb313a02e5e92c5b0bac805157d67d54f7c30c71068f46e6"
|
||||
},
|
||||
{
|
||||
"path": "resources/js/lib/irpc-normal.ts",
|
||||
"sha256_LF": "bce82366ab4ae41fc5f889d9a68d041604e1c032823e4a9384a1227e170c649b"
|
||||
},
|
||||
{
|
||||
"path": "resources/js/components/simulation-irpc-special.tsx",
|
||||
"sha256_LF": "de77c20af4f07cb2fda31b94cb2c163b627b987d816b43e196590afe59d22fb8"
|
||||
},
|
||||
{
|
||||
"path": "resources/js/lib/irpc-special-combinations.ts",
|
||||
"sha256_LF": "0c80d39930e2a3f598ba2fed6d7e31252bc24211b5a908778367e2451fcbc90c"
|
||||
}
|
||||
],
|
||||
"preservation": {
|
||||
"previous_release_preserved": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"installed": {
|
||||
"status": "installed",
|
||||
"commit": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"release": "/var/www/investmoz-homologacao/releases/f8d57bddf96b4610604a013fcc5bdd703c7dc6d5-7a31e8ac",
|
||||
"previous_release": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"database_migrations": 0,
|
||||
"content_imports": 0
|
||||
},
|
||||
"runtime_files_verified": 4,
|
||||
"preserved_L3_ISPC_FX_runtime_files_verified": 68,
|
||||
"documentary_files_verified": 31,
|
||||
"persistent_files_and_env_verified": 369,
|
||||
"tables_compared": 174,
|
||||
"changed_tables": {
|
||||
"cache": {
|
||||
"before": {
|
||||
"rows": 106,
|
||||
"checksum": "0d909f267cc44165e41d5ac5e966448f"
|
||||
},
|
||||
"after": {
|
||||
"rows": 106,
|
||||
"checksum": "8381b51b093febcc81854e20cb22bec8"
|
||||
}
|
||||
},
|
||||
"sessions": {
|
||||
"before": {
|
||||
"rows": 12,
|
||||
"checksum": "aa6448d95c23f325f4e2004fb48315ce"
|
||||
},
|
||||
"after": {
|
||||
"rows": 13,
|
||||
"checksum": "e64cf16446c054a7e852f4944574dabf"
|
||||
}
|
||||
}
|
||||
},
|
||||
"preserved_counts": {
|
||||
"published_fiches": 29,
|
||||
"relations": 28,
|
||||
"geometries": 408
|
||||
},
|
||||
"migration_count": 0,
|
||||
"content_imports": 0,
|
||||
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
|
||||
"writes_by_verification": 0
|
||||
},
|
||||
"schema_permissions_after": {
|
||||
"schema_sha256": "5045b3e51d2185377aa3d9ac7fa07a44fad3ec620cdfa83ffe31c8884ee1601d",
|
||||
"roles_grants_sha256": "1530c33cb016e67bfdc64891ddfce7f185b13b56b2cd87c012871a685e118109",
|
||||
"filesystem_permissions": {
|
||||
".env": {
|
||||
"mode": 416,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
},
|
||||
"storage": {
|
||||
"mode": 1533,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
},
|
||||
"storage/app": {
|
||||
"mode": 1533,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
},
|
||||
"bootstrap/cache": {
|
||||
"mode": 1528,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
}
|
||||
},
|
||||
"comparison_identity": "postgres;catalogue read only;no passwords collected",
|
||||
"unchanged": true
|
||||
},
|
||||
"operational_delta": {
|
||||
"status": "operational_delta_reconciled",
|
||||
"comparison_identity": "postgres before/after;isolated restored baseline;no RLS visibility inference",
|
||||
"cache": "queue:restart;requestthrottle;identical home-sector cached value with refreshed expiry(HomeController remember10min);no deletedcache",
|
||||
"sessions": "anonymous sessions from delivery user-agent or exactUA/time correlated with nginx public request;deleted sessions individually expired beyond configured lifetime,normal database session garbage collection(config/session lottery2/100)",
|
||||
"delta": {
|
||||
"cache": {
|
||||
"before_rows": 106,
|
||||
"after_rows": 106,
|
||||
"changes": [
|
||||
{
|
||||
"key_sha256": "7f7dd83f47f5bf404d55e6e9f1367948721579970b195680645e356031a070ff",
|
||||
"kind": "updated",
|
||||
"fields": [
|
||||
"value",
|
||||
"expiration"
|
||||
],
|
||||
"key_pattern": "investemoz-cache-illuminate:queue:restart",
|
||||
"is_queue_restart_key": true,
|
||||
"expiration_unchanged": false,
|
||||
"throttle_timer_pair": false,
|
||||
"same_value_home_cache_expiry_refresh": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"sessions": {
|
||||
"before_rows": 12,
|
||||
"after_rows": 14,
|
||||
"changes": [
|
||||
{
|
||||
"key_sha256": "d8e8fff391c7cb6369d141adae95227c9616f39055ffd58b5fda3f0cc6eda2a4",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
},
|
||||
{
|
||||
"key_sha256": "1618c52511f4c5d1fba6bbf74167ce464d7fbe7a121a937cab645415fa7f0878",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"business_tables_to_confirm_separately": 172,
|
||||
"active_data_writes_by_comparison": 0,
|
||||
"restore_network": "none"
|
||||
},
|
||||
"public": {
|
||||
"status": "installed_delta_verified",
|
||||
"served_revision": {
|
||||
"commit": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"branch": "main",
|
||||
"built_at": "2026-10-26T14:26:51.629481+00:00",
|
||||
"manifest_sha256": "367be71b25b56a83571d610e211ea11beae2af87989d62ef6cc7b9c54eabf580"
|
||||
},
|
||||
"manifest_hash_matches": true,
|
||||
"compiled_delta_markers": {
|
||||
"IRPC-normal-adjustments/14": [
|
||||
"assets/project-dossier-JLJx7klI.js"
|
||||
],
|
||||
"Preparar cumulações dos tratamentos L7 registados": [
|
||||
"assets/services-BKUDFoA6.js"
|
||||
],
|
||||
"Combinação incompatível": [
|
||||
"assets/project-dossier-JLJx7klI.js"
|
||||
],
|
||||
"única diferença adicional:": [
|
||||
"assets/project-dossier-JLJx7klI.js"
|
||||
],
|
||||
"IRPC-normal-adjustments/13": [
|
||||
"assets/project-dossier-JLJx7klI.js"
|
||||
],
|
||||
"Preparar CBF16 para início de actividade": [
|
||||
"assets/services-BKUDFoA6.js"
|
||||
],
|
||||
"Preparar CBF16 para cessação e quotas anteriores": [
|
||||
"assets/services-BKUDFoA6.js"
|
||||
],
|
||||
"sem consumo de saldos oficiais": [
|
||||
"assets/project-dossier-JLJx7klI.js"
|
||||
],
|
||||
"Preparar CBF16 com duodécimos": [
|
||||
"assets/services-BKUDFoA6.js"
|
||||
],
|
||||
"CBF16 — duodécimos reutilizados de L6": [
|
||||
"assets/project-dossier-JLJx7klI.js"
|
||||
],
|
||||
"Suporte dos duodécimos CBF16": [
|
||||
"assets/services-BKUDFoA6.js"
|
||||
],
|
||||
"Manter preparação anual CBF16": [
|
||||
"assets/services-BKUDFoA6.js"
|
||||
],
|
||||
"CBF16 por duodécimos — ": [
|
||||
"assets/project-dossier-JLJx7klI.js"
|
||||
],
|
||||
"diferença adicional:": [
|
||||
"assets/project-dossier-JLJx7klI.js"
|
||||
],
|
||||
"IRPC-normal-adjustments/10": [
|
||||
"assets/project-dossier-JLJx7klI.js"
|
||||
]
|
||||
},
|
||||
"assets": [
|
||||
{
|
||||
"file": "assets/project-dossier-document-W46BRNSe.js",
|
||||
"status": 200,
|
||||
"sha256": "80e14fba26e9e81f840ba09eb3f9e24a70404bbe7e6933b490b3085299a6186f"
|
||||
},
|
||||
{
|
||||
"file": "assets/services-BKUDFoA6.js",
|
||||
"status": 200,
|
||||
"sha256": "0ac8c266fcecec0e564619948f4cec28cd2572975aff70acc6997971a67fcfd9"
|
||||
},
|
||||
{
|
||||
"file": "assets/project-dossier-JLJx7klI.js",
|
||||
"status": 200,
|
||||
"sha256": "1016cb33e4476a95e1a06ce17fad4312efc93aef01994a2674e251d00c884f0b"
|
||||
},
|
||||
{
|
||||
"file": "assets/simulation-form-zFZ4YNrB.js",
|
||||
"status": 200,
|
||||
"sha256": "338068b86cce1c3215ee71b1328a6cb2f754b903ed78ff1886f8554df506d2d6"
|
||||
}
|
||||
],
|
||||
"simulator_status": 200,
|
||||
"simulator_entry": "assets/app-BPLj40Iz.js",
|
||||
"synthetic_private_writes": 0,
|
||||
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
|
||||
},
|
||||
"pipeline": {
|
||||
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
|
||||
"installed": {
|
||||
"status": "installed",
|
||||
"commit": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"release": "/var/www/investmoz-homologacao/releases/f8d57bddf96b4610604a013fcc5bdd703c7dc6d5-7a31e8ac",
|
||||
"previous_release": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"database_migrations": 0,
|
||||
"content_imports": 0
|
||||
},
|
||||
"latest_report": {
|
||||
"status": "installed",
|
||||
"commit": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"release": "/var/www/investmoz-homologacao/releases/f8d57bddf96b4610604a013fcc5bdd703c7dc6d5-7a31e8ac",
|
||||
"previous_release": "/var/www/investmoz-homologacao/releases/a7434cd27c09df3d8e6c586f9676b67abcde798e-60070b10",
|
||||
"database_migrations": 0,
|
||||
"content_imports": 0,
|
||||
"requested_commits": [
|
||||
"f8d57bddf96b4610604a013fcc5bdd703c7dc6d5"
|
||||
],
|
||||
"finished_at": "2026-10-26T14:26:54.452008+00:00"
|
||||
},
|
||||
"log_file": "1793024604346159017.log",
|
||||
"summaries": [
|
||||
"OK (1 test, 3106 assertions)",
|
||||
"built in 32.14s",
|
||||
"OK (59 tests, 317 assertions)",
|
||||
"# tests 1054",
|
||||
"# pass 1054",
|
||||
"# fail 0"
|
||||
],
|
||||
"log_bytes": 299642
|
||||
},
|
||||
"accepted_QA_proofs_reused": {
|
||||
"new_frontend_tests": 12,
|
||||
"API_tests": 1,
|
||||
"API_assertions": 133,
|
||||
"QA_database": "simulator_fiscal_delta_20261021_test",
|
||||
"QA_host": "127.0.0.1",
|
||||
"QA_port": 55441,
|
||||
"QA_transaction_rollback": true,
|
||||
"wayfinder_with_form": true,
|
||||
"typescript": true,
|
||||
"build": true,
|
||||
"recovered_HTML_and_financial_dossier": 7,
|
||||
"UI": {
|
||||
"actualComponent": true,
|
||||
"explicitPrepareCancel": true,
|
||||
"assetsPeriodsBenefitsNotEdited": true,
|
||||
"missingOnlyDependentL7": true,
|
||||
"CBF16Additional25ThenCooperative16": true,
|
||||
"prior15AlreadyIncluded": true,
|
||||
"specificGenericIncompatibilityNoAutomaticChoice": true,
|
||||
"unmappedExceptionIndeterminate": true,
|
||||
"autonomous35NotHalved": true,
|
||||
"saveRecoverDownload": true,
|
||||
"accepted13InputPreserved": true,
|
||||
"L8FinalUnknown": true,
|
||||
"errors": []
|
||||
},
|
||||
"accepted13_exact_model_key_history_comparison": true,
|
||||
"accepted_suites_not_rerun": true,
|
||||
"typescript_build_after_main": true
|
||||
},
|
||||
"no_custom_QA_suite_repeated": true,
|
||||
"L7_remaining_code": [
|
||||
"other combinations and express exceptions",
|
||||
"CBF17-19 and potential15 entitlement",
|
||||
"specific sector/territorial regimes",
|
||||
"mixed/withheld cooperativeincome and otherentities",
|
||||
"other autonome expense origins",
|
||||
"furtherCBF16 scopes",
|
||||
"capitalgains/specialoperations",
|
||||
"officialL7M20M22transport"
|
||||
],
|
||||
"L7_resume_conditions": [
|
||||
"disposition/article/scope/period/order/limit and segregatedparcel for combination",
|
||||
"implement not-yet-supported treatment before adding its effect",
|
||||
"specific document only for dependentcase/field"
|
||||
],
|
||||
"L8_first_increment": {
|
||||
"status": "L8_first_increment_delimited_not_implemented",
|
||||
"date": "2026-10-26",
|
||||
"installed_L7": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"no_new_L8_calculator_installed": true,
|
||||
"initial_scope": "resident general IRPC,annualcivil2026,MZN,currentdetermined assessment,documented absence of positive PEC/unmappedcredits and autonomoustax needing ownsettlement",
|
||||
"inputs_reused": [
|
||||
"current L6 or applicable qualifiedL7 assessment key/version/subjectNUIT/period;never add both",
|
||||
"L5 received/effective/on_account qualified and reconciled withholding proofs",
|
||||
"actual documented PPC payments by subject/period/receipt",
|
||||
"known/declaredabsence/missing states for every credit/paymentfamily"
|
||||
],
|
||||
"wrong_credits_excluded": [
|
||||
"withholding remitted by enterprise on payments to others",
|
||||
"definitive withholding",
|
||||
"projected amount without effective proof",
|
||||
"duplicate receipt/allocation/year",
|
||||
"unmapped positive PEC/investment/doubletax credit"
|
||||
],
|
||||
"sequence": [
|
||||
"validassessment",
|
||||
"admissibledeductions and explicitabsence",
|
||||
"effective onaccount withholdings",
|
||||
"actual PPC",
|
||||
"signed arithmeticbalance",
|
||||
"applicable collection/refund minimum rules",
|
||||
"simulatedpayable orrecoverable;not submittedor receivedrefund"
|
||||
],
|
||||
"proposed_acceptance_cases": [
|
||||
{
|
||||
"colecta": "1408",
|
||||
"withholdings": "300",
|
||||
"PPC": "500",
|
||||
"arithmetic_balance": "608"
|
||||
},
|
||||
{
|
||||
"colecta": "1408",
|
||||
"withholdings": "1000",
|
||||
"PPC": "600",
|
||||
"arithmetic_balance": "-192"
|
||||
},
|
||||
{
|
||||
"colecta": "1408",
|
||||
"withholdings": "408",
|
||||
"PPC": "1000",
|
||||
"arithmetic_balance": "0"
|
||||
},
|
||||
"minimumrule boundaries afterperiod/version mapping",
|
||||
"knownzero vs declaredabsence vs missing",
|
||||
"wrongbeneficiary/definitive/duplicates",
|
||||
"calculation-save-recover-report with oldhistories unchanged"
|
||||
],
|
||||
"cases_tested_now": false,
|
||||
"rule_work_before_implementation": [
|
||||
"CIRPC63/67 with Lei12/2025 nature applicable",
|
||||
"Decreto9/2008 art21(2-5) deductionorder/limits and27(1-2/6) settlement",
|
||||
"100MZN minimum in accepted2008 exemplar:link to applicable version/period before enabling parameter;no generic credibility revalidation",
|
||||
"retain PEC/credits distinct and nonrefundable limits;no3/5year automaticcarry"
|
||||
],
|
||||
"boundaries": [
|
||||
"qualified cooperative withoutwithheldincome cannot silently acceptpositivereceivedwithholdings without L7segregation",
|
||||
"no L6fallback toignore applicablependingL7effect",
|
||||
"autonomoustax/61Apositive needs own settlement articulation",
|
||||
"fraction exact;unmapped formrepresentation onlyblocks affectedtransport"
|
||||
],
|
||||
"deferred": [
|
||||
"automatic PPC/PEC obligationcalculation",
|
||||
"positivePEC/creditorderlimitscarry",
|
||||
"autonomoustaxsettlement",
|
||||
"specialperiods/foreigncurrencypayments",
|
||||
"interest/penalties/calendar/guideremittance",
|
||||
"AT submission/refundprocessing",
|
||||
"unmappedM20M22fields"
|
||||
],
|
||||
"sources_reused": [
|
||||
{
|
||||
"file": "C:\\laragon\\www\\portal-investidor-irpc-l7-common-qa-20261026\\docs\\investmoz\\simulations\\source-archive\\Lei-34-2007-BR52.pdf",
|
||||
"sha256": "cdbef875ad7ccc1517b12faf5de0e893a70ed2ed81e33913cd6dc4a674474e6e",
|
||||
"articles": "CIRPC63/67",
|
||||
"PDF_pages": [
|
||||
18,
|
||||
19
|
||||
],
|
||||
"official_source_acceptance_preserved": true
|
||||
},
|
||||
{
|
||||
"file": "C:\\laragon\\www\\portal-investidor-irpc-l7-common-qa-20261026\\docs\\investmoz\\simulations\\source-archive\\Decreto-9-2008-BR16.pdf",
|
||||
"sha256": "96fccdecbfdc11c9eafb90fbc6c7bc259f88bbd4c7507d1ac3af1fa03f960697",
|
||||
"articles": "RIRPC21/27",
|
||||
"PDF_pages": [
|
||||
6,
|
||||
7
|
||||
],
|
||||
"official_source_acceptance_preserved": true
|
||||
},
|
||||
{
|
||||
"file": "C:\\laragon\\www\\portal-investidor-irpc-l7-common-qa-20261026\\docs\\investmoz\\simulations\\source-archive\\BR-248-I-Suplemento-1-2025.pdf",
|
||||
"sha256": "ccf2a8deeca820f2dd076b4b2141b1efe3f6a806568c3a587ca59a8e92f4c251",
|
||||
"articles": "Lei12/2025 IRPC67/version2026",
|
||||
"PDF_pages": [
|
||||
18,
|
||||
19,
|
||||
20
|
||||
],
|
||||
"official_source_acceptance_preserved": true
|
||||
}
|
||||
],
|
||||
"global_effort": {
|
||||
"initial_L8_L14_reference_hours": [
|
||||
240,
|
||||
416
|
||||
],
|
||||
"is_current_remainingforecast": false,
|
||||
"reconciliation_before_globalforecast": [
|
||||
"implemented/reusable vs remainingcode perlot",
|
||||
"reuseacceptedproofs;no duplicate sharedcomponentestimate",
|
||||
"documentarywait separately",
|
||||
"L1-L7residuals,integration/delivery,L15-L16 included"
|
||||
]
|
||||
},
|
||||
"L7_partial": true,
|
||||
"L8_final_still_not_implemented": true
|
||||
},
|
||||
"global_effort_forecast_not_assumed": true,
|
||||
"L6_operational_delimited": true,
|
||||
"L7_partial": true,
|
||||
"L8_final_separate": true,
|
||||
"SGF_TEMPO_untouched": true
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
{
|
||||
"status": "prepared_delivery_deferred_by_user_capacity_not_satisfied",
|
||||
"date": "2026-10-27",
|
||||
"candidate": "14360748194f3658d91a7d7ae5615efd0fcbfbb7",
|
||||
"QA_runtime_commit": "11a6cee981f0a425b0fceefb6ed85485bb298245",
|
||||
"candidate_branch": "codex/irpc-l8-settlement-qa-20261026",
|
||||
"remote_main_verified": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"installed_remote_verified": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"capacity": {
|
||||
"checked_at_UTC": "2026-10-27T06:05:28.744338+00:00",
|
||||
"partition": "/dev/md2 / ext4",
|
||||
"free_bytes": 4402343936,
|
||||
"free_GiB": 4.100002288818359,
|
||||
"required_after_backup_bytes": 5368709120,
|
||||
"previous_backup_reference_bytes": 175917490,
|
||||
"estimated_required_before_backup_bytes": 5544626610,
|
||||
"additional_free_bytes_needed": 1142282674,
|
||||
"additional_GiB_needed_rounded_up": 1.07,
|
||||
"inodes_available": 21340182,
|
||||
"release_entries_reference": 31259,
|
||||
"inodes_sufficient_against_reference": true,
|
||||
"fresh_measurement_required_on_resume": true,
|
||||
"installer_threshold_not_changed": true
|
||||
},
|
||||
"baseline": {
|
||||
"baseline": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"files_verified": 168,
|
||||
"active_writes": 0
|
||||
},
|
||||
"prepared_runtime_delta_files": 5,
|
||||
"preserved_runtime_files": 134,
|
||||
"originals_preserved": 31,
|
||||
"caches_read_only": {
|
||||
"caches": [
|
||||
{
|
||||
"path": "/root/.cache/composer/files",
|
||||
"resolved": "/root/.cache/composer/files",
|
||||
"symlink": false,
|
||||
"bytes": 127242240,
|
||||
"first_entries": [
|
||||
"carbonphp",
|
||||
"maatwebsite",
|
||||
"iamcal",
|
||||
"bordoni",
|
||||
"fidry",
|
||||
"mockery",
|
||||
"symfony",
|
||||
"mtdowling",
|
||||
"inertiajs",
|
||||
"tcg",
|
||||
"nyholm",
|
||||
"dflydev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/tmp/node-compile-cache",
|
||||
"resolved": "/tmp/node-compile-cache",
|
||||
"symlink": false,
|
||||
"bytes": 4009984,
|
||||
"first_entries": [
|
||||
"v22.23.4-x64-d04b8edd-1001"
|
||||
]
|
||||
}
|
||||
],
|
||||
"package_manager_processes": [],
|
||||
"open_cache_handles": [],
|
||||
"service": "ActiveState=inactive\nSubState=dead\n",
|
||||
"active_writes": 0
|
||||
},
|
||||
"caches_insufficient_to_resolve_gap": true,
|
||||
"cleanup_performed": false,
|
||||
"fresh_backup_executed": false,
|
||||
"fresh_restore_executed": false,
|
||||
"main_push_executed": false,
|
||||
"installation_executed": false,
|
||||
"server_persistent_writes": 0,
|
||||
"business_database_writes": 0,
|
||||
"user_decision": "Manter a entrega preparada por agora",
|
||||
"next_action": "New space/inode and main/servedrevision checks;confirm capacity for freshbackup/restore and isolatedbuild;then authorized Git delivery and onlydelta verification. Keep active release until new is ready.",
|
||||
"QA_proofs_reused": {
|
||||
"frontend": 19,
|
||||
"API_assertions": 170,
|
||||
"UI_round_trip": true,
|
||||
"typescript": true,
|
||||
"isolatedbuild": true,
|
||||
"not_repeated": true
|
||||
},
|
||||
"L8_partial": true,
|
||||
"PEC_and_own_credits_separate": true,
|
||||
"L7_residuals_unchanged": true,
|
||||
"SGF_TEMPO_untouched": true,
|
||||
"preflight_pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604",
|
||||
"resume_candidate_branch": "codex/irpc-l8-settlement-qa-20261026",
|
||||
"notes_branch": "codex/irpc-l8-delivery-capacity-20261027"
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
{
|
||||
"status": "QA_complete_ready_for_grouped_delivery_not_installed",
|
||||
"date": "2026-10-26",
|
||||
"branch": "codex/irpc-l8-settlement-qa-20261026",
|
||||
"runtime_revision": "11a6cee981f0a425b0fceefb6ed85485bb298245",
|
||||
"installed_revision_per_user": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"remote_main_checked": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"version": "IRPC-annual-settlement/1",
|
||||
"scope": "resident general IRPC,annualcivil2026,MZN,currentdetermined assessment,documented absence of positive PEC/unmappedcredits and autonomoustax needing ownsettlement",
|
||||
"inputs_reused": [
|
||||
"current L6 or applicable qualifiedL7 assessment key/version/subjectNUIT/period;never add both",
|
||||
"L5 received/effective/on_account qualified and reconciled withholding proofs",
|
||||
"actual documented PPC payments by subject/period/receipt",
|
||||
"known/declaredabsence/missing states for every credit/paymentfamily"
|
||||
],
|
||||
"PEC_and_special_credits_separate": true,
|
||||
"official_credit_consumption_or_central_reservation": false,
|
||||
"duplicate_guards": [
|
||||
"same L5 allocation/pair",
|
||||
"normalised issuer/document even if date changed",
|
||||
"same receipt as withholding and PPC",
|
||||
"receipt total including partial allocations in other contexts in same dossier",
|
||||
"same sourceKey L5 allocation cannot consume larger receipt twice",
|
||||
"different entity/year or inconsistent proven amount"
|
||||
],
|
||||
"cases": {
|
||||
"payable": {
|
||||
"status": "payable",
|
||||
"knownWithholdings": {
|
||||
"numerator": "300",
|
||||
"denominator": "1"
|
||||
},
|
||||
"knownPpc": {
|
||||
"numerator": "500",
|
||||
"denominator": "1"
|
||||
},
|
||||
"arithmeticBalance": {
|
||||
"numerator": "608",
|
||||
"denominator": "1"
|
||||
},
|
||||
"payable": {
|
||||
"numerator": "608",
|
||||
"denominator": "1"
|
||||
},
|
||||
"recoverable": {
|
||||
"numerator": "0",
|
||||
"denominator": "1"
|
||||
},
|
||||
"pending": []
|
||||
},
|
||||
"recoverable": {
|
||||
"status": "recoverable",
|
||||
"knownWithholdings": {
|
||||
"numerator": "1000",
|
||||
"denominator": "1"
|
||||
},
|
||||
"knownPpc": {
|
||||
"numerator": "600",
|
||||
"denominator": "1"
|
||||
},
|
||||
"arithmeticBalance": {
|
||||
"numerator": "-192",
|
||||
"denominator": "1"
|
||||
},
|
||||
"payable": {
|
||||
"numerator": "0",
|
||||
"denominator": "1"
|
||||
},
|
||||
"recoverable": {
|
||||
"numerator": "192",
|
||||
"denominator": "1"
|
||||
},
|
||||
"pending": []
|
||||
},
|
||||
"balanced": {
|
||||
"status": "balanced",
|
||||
"knownWithholdings": {
|
||||
"numerator": "408",
|
||||
"denominator": "1"
|
||||
},
|
||||
"knownPpc": {
|
||||
"numerator": "1000",
|
||||
"denominator": "1"
|
||||
},
|
||||
"arithmeticBalance": {
|
||||
"numerator": "0",
|
||||
"denominator": "1"
|
||||
},
|
||||
"payable": {
|
||||
"numerator": "0",
|
||||
"denominator": "1"
|
||||
},
|
||||
"recoverable": {
|
||||
"numerator": "0",
|
||||
"denominator": "1"
|
||||
},
|
||||
"pending": []
|
||||
},
|
||||
"absent": {
|
||||
"status": "payable",
|
||||
"knownWithholdings": {
|
||||
"numerator": "0",
|
||||
"denominator": "1"
|
||||
},
|
||||
"knownPpc": {
|
||||
"numerator": "0",
|
||||
"denominator": "1"
|
||||
},
|
||||
"arithmeticBalance": {
|
||||
"numerator": "1408",
|
||||
"denominator": "1"
|
||||
},
|
||||
"payable": {
|
||||
"numerator": "1408",
|
||||
"denominator": "1"
|
||||
},
|
||||
"recoverable": {
|
||||
"numerator": "0",
|
||||
"denominator": "1"
|
||||
},
|
||||
"pending": []
|
||||
},
|
||||
"missing": {
|
||||
"status": "indeterminate",
|
||||
"knownWithholdings": {
|
||||
"numerator": "300",
|
||||
"denominator": "1"
|
||||
},
|
||||
"knownPpc": {
|
||||
"numerator": "0",
|
||||
"denominator": "1"
|
||||
},
|
||||
"arithmeticBalance": null,
|
||||
"payable": null,
|
||||
"recoverable": null,
|
||||
"pending": [
|
||||
"QA-PPC-2026-1: Error: PPC exige comprovativo efectivo,MZN,data,entidade e exercício correspondentes;projecção/tesouraria não é pagamento"
|
||||
]
|
||||
},
|
||||
"duplicate": {
|
||||
"status": "indeterminate",
|
||||
"knownWithholdings": {
|
||||
"numerator": "300",
|
||||
"denominator": "1"
|
||||
},
|
||||
"knownPpc": {
|
||||
"numerator": "0",
|
||||
"denominator": "1"
|
||||
},
|
||||
"arithmeticBalance": null,
|
||||
"payable": null,
|
||||
"recoverable": null,
|
||||
"pending": [
|
||||
"QA-PPC-2026-1: Comprovativo utilizado além do montante disponível ou com montantes divergentes neste/outro mapa."
|
||||
]
|
||||
},
|
||||
"pec": {
|
||||
"status": "indeterminate",
|
||||
"knownWithholdings": {
|
||||
"numerator": "300",
|
||||
"denominator": "1"
|
||||
},
|
||||
"knownPpc": {
|
||||
"numerator": "500",
|
||||
"denominator": "1"
|
||||
},
|
||||
"arithmeticBalance": null,
|
||||
"payable": null,
|
||||
"recoverable": null,
|
||||
"pending": [
|
||||
"PEC: Error: montante positivo fora deste recorte:corresponder ordem,limite e transporte próprios;sem abatimento ou reembolso automático"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"frontend_tests": 19,
|
||||
"frontend_pass": 19,
|
||||
"API_tests": 1,
|
||||
"API_assertions": 170,
|
||||
"API_cases": 7,
|
||||
"database": "simulator_fiscal_delta_20261021_test",
|
||||
"host": "127.0.0.1",
|
||||
"port": 55441,
|
||||
"transaction_rollback": true,
|
||||
"actual_components_UI": {
|
||||
"actualComponents": true,
|
||||
"explicitPreparation": true,
|
||||
"onlyActualOnAccountProofSelectable": true,
|
||||
"duplicateSelectionDisabled": true,
|
||||
"missingNotZero": true,
|
||||
"ownBeneficiaryAndIncludedIncomeConfirmed": true,
|
||||
"actualPPCConfirmed": true,
|
||||
"PECAndCreditsSeparate": true,
|
||||
"payable608": true,
|
||||
"recoverable192": true,
|
||||
"balanced": true,
|
||||
"duplicateIndeterminate": true,
|
||||
"positivePECIndeterminate": true,
|
||||
"oldBooksAndPlanUnchanged": true,
|
||||
"saveReloadRecoverReportDownload": true,
|
||||
"errors": []
|
||||
},
|
||||
"wayfinder_with_form": "passed",
|
||||
"typescript": "passed",
|
||||
"isolated_QA_build": "passed",
|
||||
"build_existing_warnings": [
|
||||
"chunk size over500kB;plugin timing diagnostic"
|
||||
],
|
||||
"prior_accepted_suites_not_repeated": true
|
||||
},
|
||||
"runtime_delta": [
|
||||
"resources/js/components/simulation-form.tsx",
|
||||
"resources/js/components/simulation-irpc-annual.tsx",
|
||||
"resources/js/lib/irpc-annual-settlement.ts",
|
||||
"resources/js/lib/project-dossier-report.ts",
|
||||
"resources/js/lib/project-dossier.ts",
|
||||
"tests/Feature/IrpcAnnualSettlementDraftTest.php",
|
||||
"tests/frontend/irpc-annual-settlement.test.mjs",
|
||||
"tools/irpc-annual-settlement-qa.php"
|
||||
],
|
||||
"preservation": {
|
||||
"baseline": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"documentation_base": "d5f11462",
|
||||
"existing_tracked_files": 2832,
|
||||
"changed_existing_files": [
|
||||
"docs/investmoz/consolidated-review-matrix-2026-10-03.md",
|
||||
"docs/investmoz/unification/traceability-and-manual.md",
|
||||
"docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv",
|
||||
"resources/js/components/simulation-form.tsx",
|
||||
"resources/js/lib/project-dossier-report.ts",
|
||||
"resources/js/lib/project-dossier.ts"
|
||||
],
|
||||
"all_other_existing_files_byte_identical": true,
|
||||
"schema_configuration_permissions_unchanged": true,
|
||||
"L5_L6_L7_engines_and_fixtures_byte_identical": true,
|
||||
"originals_count": 31,
|
||||
"originals": {
|
||||
"docs/investmoz/simulations/source-archive/AT-Comunicado-9-2026-ISPC.pdf": "106f8a9ce9255c03549c70bf07fe999d32e6e55302d009b509862aa74ccb4973",
|
||||
"docs/investmoz/simulations/source-archive/AT-MRFTA-19-39.pdf": "8ea62c53066b482f87078a7a7b1ecf15ca98a12a122e8d7abca63acfc993186b",
|
||||
"docs/investmoz/simulations/source-archive/AT-Modelo-30-ISPC.pdf": "6802edd06b6ff638a0b851a3ec7ecf69af8f07840faa47446becad67d35d445c",
|
||||
"docs/investmoz/simulations/source-archive/AT-Modelo-B-Geral.pdf": "bd977c7c59d4d98befd92e2c566b1bf168cb1343bb519f51b41a3807f431fc57",
|
||||
"docs/investmoz/simulations/source-archive/BM-Mercado-Monetario-MAIBOR-20261025.html": "00e8a7e0d3a1db4ca3beb56d5361b2084a0f1684f3d40fc1c203702a2190e063",
|
||||
"docs/investmoz/simulations/source-archive/BR-16-I-Serie-2008-04-16.pdf": "fc373ff5637edf75ec6a9595dec8763a8503d4ee786e3b7d8f1c742eae9d80ee",
|
||||
"docs/investmoz/simulations/source-archive/BR-248-I-Suplemento-1-2025.pdf": "ccf2a8deeca820f2dd076b4b2141b1efe3f6a806568c3a587ca59a8e92f4c251",
|
||||
"docs/investmoz/simulations/source-archive/BR-89-I-Serie-2017-06-08.pdf": "11f0cab15eb6e51010952203ffa24fdc533a24fd642e19525fe4f46b17a1f5e5",
|
||||
"docs/investmoz/simulations/source-archive/BR-95-I-Suplemento-2025-05-21.pdf": "e0e682e2c027c3cd9c1d46a73a3f48bc5f6bdbf05667fd97314d7a3f6a456358",
|
||||
"docs/investmoz/simulations/source-archive/BR252-I-Serie-2022-Lei20-PESOE.pdf": "1159fd3ce1ba5581671796d083534da48bd3c5578298819e896f1c2a8026318d",
|
||||
"docs/investmoz/simulations/source-archive/Decreto-22-2021-BR70.pdf": "a8fac38dcfe08f9c7a8e46254cff10e1ec82fc4f7a8d88ad6e4fe7d91ffc21a5",
|
||||
"docs/investmoz/simulations/source-archive/Decreto-27-2026-BR123.pdf": "26249c3fa58f149c81de36e99d1aac2819a4771379d9e8833159660dabf539bb",
|
||||
"docs/investmoz/simulations/source-archive/Decreto-29-1998-BR22-5-suplemento.pdf": "6242cbe675faadf085f43f95ec8c7e8868aafe67c3b2ab2bb010992288f954f8",
|
||||
"docs/investmoz/simulations/source-archive/Decreto-3-2011-BR-11-I-mineiros.pdf": "5bca1133666ba9c69870b89823420175b7b5b8d0eccb667ecdf5c29716f3b6be",
|
||||
"docs/investmoz/simulations/source-archive/Decreto-37-2023-BR124.pdf": "7e680b191481faa0e2e9057fa5053587eb2a29d1d8c819e0eb9f02814255a04c",
|
||||
"docs/investmoz/simulations/source-archive/Decreto-9-2008-BR16.pdf": "96fccdecbfdc11c9eafb90fbc6c7bc259f88bbd4c7507d1ac3af1fa03f960697",
|
||||
"docs/investmoz/simulations/source-archive/Lei-13-2016-CIVA-BR-156-10-suplemento.pdf": "b90dc7c14ecea2e378c4a62e8e5a47d54a5644c457baeb8b8053b92fd2a5710b",
|
||||
"docs/investmoz/simulations/source-archive/Lei-14-1992-BR42.pdf": "089fff7423e99a70a230a73ca379e4ea3a91d124703f91016e57ff82794b9e56",
|
||||
"docs/investmoz/simulations/source-archive/Lei-17-2022-BR251-exemplar-MCNet5.pdf": "14eb34f0af91a8f5cb1770c7b52d6ff839c6818302d1ed96d79afbfb9fe999d4",
|
||||
"docs/investmoz/simulations/source-archive/Lei-17-2022-IPP-BR250-Parlamento.pdf": "978cd22403ffd336a631704ecd7a5bbd814a427c815b9acdaca5515591dd9e2a",
|
||||
"docs/investmoz/simulations/source-archive/Lei-19-2013-BR76.pdf": "bba96d645cc935ffc3d1a79b9f0f73ac1c693d6459c2ad41f56cd2841accae76",
|
||||
"docs/investmoz/simulations/source-archive/Lei-19-2017-IRPS-BR-OCAM.pdf": "c3a0186cb9ad090d7a9533006295dc9bb6a62ad0d6150173cbd49dba4ee4b52d",
|
||||
"docs/investmoz/simulations/source-archive/Lei-2-2011-BR-1-4-suplemento-MCNet.pdf": "a7543a68cc3287a46a83c39a04821b40f649dd06c4e9b5dc51ff0b47fba08899",
|
||||
"docs/investmoz/simulations/source-archive/Lei-20-2009-BR36-AT-exemplar19.pdf": "fc1c8144db42960cbf73e717e095896f511ece0f907f58f78819b27d6917a7ee",
|
||||
"docs/investmoz/simulations/source-archive/Lei-22-2022-IVA-republicada-BR-250-2-suplemento.pdf": "ea1b0dc6f5cf6e595f6d9a19e7042f398999e0087caef1785f6e8fac571b5f53",
|
||||
"docs/investmoz/simulations/source-archive/Lei-34-2007-BR52.pdf": "cdbef875ad7ccc1517b12faf5de0e893a70ed2ed81e33913cd6dc4a674474e6e",
|
||||
"docs/investmoz/simulations/source-archive/Lei-4-1994-BR37-3-suplemento.pdf": "210df9db8980d0a5690cd187a6eeec7e37a900d743e39062c16f4e0d12215c7e",
|
||||
"docs/investmoz/simulations/source-archive/Lei-4-2012-BR3.pdf": "b8845cef41dcbd9ba50c43dbfa743a56030dd3d348242a107e1ae30279eec121",
|
||||
"docs/investmoz/simulations/source-archive/Lei-7-1991-Partidos-IFES.pdf": "6b783a0bb3330688ef10660a58060d9724aa2da6a873d234fe902f0eaaeda42d",
|
||||
"docs/investmoz/simulations/source-archive/PT-MZ-CDT-1992.pdf": "d504e1024b28aee5c6acf4592acb96ec9c915a8414f67a61ab6984d6acf9df9d",
|
||||
"docs/investmoz/simulations/source-archive/PT-MZ-Protocolo-2009.pdf": "f353773dcf41f09f4daa6cf5ba5a5f7994f3e02615867c2dcffc61c3d901bf9b"
|
||||
},
|
||||
"all_seven_recovered_cases_match_final_inputs": true,
|
||||
"no_active_database_or_server_operations": true,
|
||||
"no_SGF_TEMPO_operations": true,
|
||||
"runtime_changed_existing_files": [
|
||||
"resources/js/components/simulation-form.tsx",
|
||||
"resources/js/lib/project-dossier-report.ts",
|
||||
"resources/js/lib/project-dossier.ts"
|
||||
],
|
||||
"documentation_changed_existing_files": [
|
||||
"docs/investmoz/consolidated-review-matrix-2026-10-03.md",
|
||||
"docs/investmoz/unification/traceability-and-manual.md",
|
||||
"docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv"
|
||||
],
|
||||
"documentation_only_appends_and_target_AUD_record": true
|
||||
},
|
||||
"sources_reused": [
|
||||
{
|
||||
"file": "docs/investmoz/simulations/source-archive/Lei-34-2007-BR52.pdf",
|
||||
"sha256": "cdbef875ad7ccc1517b12faf5de0e893a70ed2ed81e33913cd6dc4a674474e6e",
|
||||
"articles": "CIRPC63/67",
|
||||
"PDF_pages": [
|
||||
18,
|
||||
19
|
||||
],
|
||||
"official_source_acceptance_preserved": true
|
||||
},
|
||||
{
|
||||
"file": "docs/investmoz/simulations/source-archive/Decreto-9-2008-BR16.pdf",
|
||||
"sha256": "96fccdecbfdc11c9eafb90fbc6c7bc259f88bbd4c7507d1ac3af1fa03f960697",
|
||||
"articles": "RIRPC21/27",
|
||||
"PDF_pages": [
|
||||
6,
|
||||
7
|
||||
],
|
||||
"official_source_acceptance_preserved": true
|
||||
},
|
||||
{
|
||||
"file": "docs/investmoz/simulations/source-archive/BR-248-I-Suplemento-1-2025.pdf",
|
||||
"sha256": "ccf2a8deeca820f2dd076b4b2141b1efe3f6a806568c3a587ca59a8e92f4c251",
|
||||
"articles": "Lei12/2025 IRPC67/version2026",
|
||||
"PDF_pages": [
|
||||
18,
|
||||
19,
|
||||
20
|
||||
],
|
||||
"official_source_acceptance_preserved": true
|
||||
}
|
||||
],
|
||||
"minimum": {
|
||||
"rule": "Decreto9/2008 art27(6)",
|
||||
"scope": "2026 resident_general/calendar/MZN",
|
||||
"less_than": "100 MZN",
|
||||
"strict_boundary_tests": [
|
||||
"+99.99",
|
||||
"+100",
|
||||
"-99.99",
|
||||
"-100"
|
||||
],
|
||||
"arithmetic_exact": true,
|
||||
"new_rounding": false,
|
||||
"automatic_carry": false
|
||||
},
|
||||
"remaining_code": [
|
||||
"automatic PPC/PEC obligationcalculation",
|
||||
"positivePEC/creditorderlimitscarry",
|
||||
"autonomoustaxsettlement",
|
||||
"specialperiods/foreigncurrencypayments",
|
||||
"interest/penalties/calendar/guideremittance",
|
||||
"AT submission/refundprocessing",
|
||||
"unmappedM20M22fields"
|
||||
],
|
||||
"documentary_dependencies": {
|
||||
"previous_L5_L6_L7_matrix_items_preserved": true,
|
||||
"examples": [
|
||||
"mixed/withheld cooperativeincome needs L7 segregation",
|
||||
"express cumulation exception requires disposition/period/limits",
|
||||
"divergent M20M22 field needs exactedition and representation"
|
||||
],
|
||||
"only_dependent_case_blocked": true
|
||||
},
|
||||
"L6_operational_delimited": true,
|
||||
"L7_partial": true,
|
||||
"L8_partial": true,
|
||||
"submitted_or_payment_or_refund_received": false,
|
||||
"server_operations_this_turn": false,
|
||||
"reported_server_free_GiB": 4.14,
|
||||
"reported_capacity_not_measured_this_turn": true,
|
||||
"capacity_blocks_future_install_not_QA": true,
|
||||
"future_delivery": {
|
||||
"fresh_main_compatibility": true,
|
||||
"measure_space_and_inodes": true,
|
||||
"confirm_backup_and_isolated_build_capacity": true,
|
||||
"fresh_backup_restore": true,
|
||||
"keep_active_until_new_ready": true,
|
||||
"verify_served_revision_and_only_delta": true
|
||||
},
|
||||
"evidence_directory": "outputs/irpc-l8-settlement/",
|
||||
"global_effort": {
|
||||
"initial_L8_L14_reference_hours": [
|
||||
240,
|
||||
416
|
||||
],
|
||||
"is_current_remainingforecast": false,
|
||||
"reconciliation_before_globalforecast": [
|
||||
"implemented/reusable vs remainingcode perlot",
|
||||
"reuseacceptedproofs;no duplicate sharedcomponentestimate",
|
||||
"documentarywait separately",
|
||||
"L1-L7residuals,integration/delivery,L15-L16 included"
|
||||
]
|
||||
},
|
||||
"root_checkout_runtime_not_merged": true,
|
||||
"SGF_TEMPO_untouched": true
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"status": "L8_first_increment_delimited_not_implemented",
|
||||
"date": "2026-10-26",
|
||||
"installed_L7": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"no_new_L8_calculator_installed": true,
|
||||
"initial_scope": "resident general IRPC,annualcivil2026,MZN,currentdetermined assessment,documented absence of positive PEC/unmappedcredits and autonomoustax needing ownsettlement",
|
||||
"inputs_reused": [
|
||||
"current L6 or applicable qualifiedL7 assessment key/version/subjectNUIT/period;never add both",
|
||||
"L5 received/effective/on_account qualified and reconciled withholding proofs",
|
||||
"actual documented PPC payments by subject/period/receipt",
|
||||
"known/declaredabsence/missing states for every credit/paymentfamily"
|
||||
],
|
||||
"wrong_credits_excluded": [
|
||||
"withholding remitted by enterprise on payments to others",
|
||||
"definitive withholding",
|
||||
"projected amount without effective proof",
|
||||
"duplicate receipt/allocation/year",
|
||||
"unmapped positive PEC/investment/doubletax credit"
|
||||
],
|
||||
"sequence": [
|
||||
"validassessment",
|
||||
"admissibledeductions and explicitabsence",
|
||||
"effective onaccount withholdings",
|
||||
"actual PPC",
|
||||
"signed arithmeticbalance",
|
||||
"applicable collection/refund minimum rules",
|
||||
"simulatedpayable orrecoverable;not submittedor receivedrefund"
|
||||
],
|
||||
"proposed_acceptance_cases": [
|
||||
{
|
||||
"colecta": "1408",
|
||||
"withholdings": "300",
|
||||
"PPC": "500",
|
||||
"arithmetic_balance": "608"
|
||||
},
|
||||
{
|
||||
"colecta": "1408",
|
||||
"withholdings": "1000",
|
||||
"PPC": "600",
|
||||
"arithmetic_balance": "-192"
|
||||
},
|
||||
{
|
||||
"colecta": "1408",
|
||||
"withholdings": "408",
|
||||
"PPC": "1000",
|
||||
"arithmetic_balance": "0"
|
||||
},
|
||||
"minimumrule boundaries afterperiod/version mapping",
|
||||
"knownzero vs declaredabsence vs missing",
|
||||
"wrongbeneficiary/definitive/duplicates",
|
||||
"calculation-save-recover-report with oldhistories unchanged"
|
||||
],
|
||||
"cases_tested_now": false,
|
||||
"rule_work_before_implementation": [
|
||||
"CIRPC63/67 with Lei12/2025 nature applicable",
|
||||
"Decreto9/2008 art21(2-5) deductionorder/limits and27(1-2/6) settlement",
|
||||
"100MZN minimum in accepted2008 exemplar:link to applicable version/period before enabling parameter;no generic credibility revalidation",
|
||||
"retain PEC/credits distinct and nonrefundable limits;no3/5year automaticcarry"
|
||||
],
|
||||
"boundaries": [
|
||||
"qualified cooperative withoutwithheldincome cannot silently acceptpositivereceivedwithholdings without L7segregation",
|
||||
"no L6fallback toignore applicablependingL7effect",
|
||||
"autonomoustax/61Apositive needs own settlement articulation",
|
||||
"fraction exact;unmapped formrepresentation onlyblocks affectedtransport"
|
||||
],
|
||||
"deferred": [
|
||||
"automatic PPC/PEC obligationcalculation",
|
||||
"positivePEC/creditorderlimitscarry",
|
||||
"autonomoustaxsettlement",
|
||||
"specialperiods/foreigncurrencypayments",
|
||||
"interest/penalties/calendar/guideremittance",
|
||||
"AT submission/refundprocessing",
|
||||
"unmappedM20M22fields"
|
||||
],
|
||||
"sources_reused": [
|
||||
{
|
||||
"file": "C:\\laragon\\www\\portal-investidor-irpc-l7-common-qa-20261026\\docs\\investmoz\\simulations\\source-archive\\Lei-34-2007-BR52.pdf",
|
||||
"sha256": "cdbef875ad7ccc1517b12faf5de0e893a70ed2ed81e33913cd6dc4a674474e6e",
|
||||
"articles": "CIRPC63/67",
|
||||
"PDF_pages": [
|
||||
18,
|
||||
19
|
||||
],
|
||||
"official_source_acceptance_preserved": true
|
||||
},
|
||||
{
|
||||
"file": "C:\\laragon\\www\\portal-investidor-irpc-l7-common-qa-20261026\\docs\\investmoz\\simulations\\source-archive\\Decreto-9-2008-BR16.pdf",
|
||||
"sha256": "96fccdecbfdc11c9eafb90fbc6c7bc259f88bbd4c7507d1ac3af1fa03f960697",
|
||||
"articles": "RIRPC21/27",
|
||||
"PDF_pages": [
|
||||
6,
|
||||
7
|
||||
],
|
||||
"official_source_acceptance_preserved": true
|
||||
},
|
||||
{
|
||||
"file": "C:\\laragon\\www\\portal-investidor-irpc-l7-common-qa-20261026\\docs\\investmoz\\simulations\\source-archive\\BR-248-I-Suplemento-1-2025.pdf",
|
||||
"sha256": "ccf2a8deeca820f2dd076b4b2141b1efe3f6a806568c3a587ca59a8e92f4c251",
|
||||
"articles": "Lei12/2025 IRPC67/version2026",
|
||||
"PDF_pages": [
|
||||
18,
|
||||
19,
|
||||
20
|
||||
],
|
||||
"official_source_acceptance_preserved": true
|
||||
}
|
||||
],
|
||||
"global_effort": {
|
||||
"initial_L8_L14_reference_hours": [
|
||||
240,
|
||||
416
|
||||
],
|
||||
"is_current_remainingforecast": false,
|
||||
"reconciliation_before_globalforecast": [
|
||||
"implemented/reusable vs remainingcode perlot",
|
||||
"reuseacceptedproofs;no duplicate sharedcomponentestimate",
|
||||
"documentarywait separately",
|
||||
"L1-L7residuals,integration/delivery,L15-L16 included"
|
||||
]
|
||||
},
|
||||
"L7_partial": true,
|
||||
"L8_final_still_not_implemented": true
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
{
|
||||
"date": "2026-10-27",
|
||||
"status": "prospecting_handoff_ready_and_Gurue_private_hypothesis_in_QA_not_installed",
|
||||
"branch": "codex/proactive-handoff-gurue-qa-20261027",
|
||||
"baseline": "a78abf06d0ca075b18156ae3fd99649b69202481",
|
||||
"technical_candidate_unchanged": "1afab4a2a71f182f260e4d2555d79242261a4d2a",
|
||||
"runtime_unchanged": "3439f35038f15c93224e6cf876bf559135824d13",
|
||||
"songo": {
|
||||
"case_id": "CB-METROLOGIA-20261027",
|
||||
"record_id": 401,
|
||||
"source_version": 3,
|
||||
"context_revision": 3,
|
||||
"unchanged": true,
|
||||
"state": "private_pending_external_commercial_responses",
|
||||
"external_messages_sent": 0,
|
||||
"commercial_responses_received": 0,
|
||||
"partner_quotes_received": 0,
|
||||
"resume_when": "Inventories/programmes/interest and partner quotations for comparable scope received;identify independent buying centres before aggregating demand"
|
||||
},
|
||||
"prospecting_form": {
|
||||
"path": "docs/investmoz/unification/prospeccao-apoio-metrologico-20261027.pdf",
|
||||
"pages": 2,
|
||||
"interactive_fields": 42,
|
||||
"canonical_fields_and_widgets_agree": true,
|
||||
"unique_names": true,
|
||||
"all_fields_in_page": true,
|
||||
"saved_values_recovered": true,
|
||||
"appearance_streams_present": true,
|
||||
"real_form_not_prefilled_with_test_values": true,
|
||||
"delivered_format": "fillable_PDF",
|
||||
"docx_not_delivered": true,
|
||||
"sha256": "abed1dc12a8f635bf4c3aa39ba5823114d2155aaca9b675a8ca1b9fb6248e989",
|
||||
"visual_review": "Both final pages inspected;sample retained values checked separately"
|
||||
},
|
||||
"gurue": {
|
||||
"case_id": "GUR-CHA-20261027",
|
||||
"record_id": 402,
|
||||
"dossier_id": "883c8ec3-59a3-4074-b91c-b7d4a5d88ff0",
|
||||
"source_version": 1,
|
||||
"context_revision": 1,
|
||||
"evidence_count": 5,
|
||||
"need_state": "hypothesis",
|
||||
"private_draft_not_published": true,
|
||||
"created_saved_recovered_through_existing_services": true,
|
||||
"preview_and_confirmation": true,
|
||||
"deliberate_title_preserved": true,
|
||||
"existing_geo_and_sector_reused": true,
|
||||
"no_new_grants_or_business_promoter": true,
|
||||
"QA_operator_1021_only": true,
|
||||
"Songo_record_401_version_3_unchanged": true,
|
||||
"Songo_context_revision_3_unchanged": true,
|
||||
"no_application_code_or_fiscal_changes": true,
|
||||
"accepted_proofs_reused": true,
|
||||
"no_contact_or_server_operations": true,
|
||||
"QA_database": "proactive_investment_20261027_test",
|
||||
"row_preservation": {
|
||||
"opportunities": {
|
||||
"old_rows_unchanged": 53,
|
||||
"new_rows": 1
|
||||
},
|
||||
"desk_cases": {
|
||||
"old_rows_unchanged": 18,
|
||||
"new_rows": 1
|
||||
},
|
||||
"projects": {
|
||||
"old_rows_unchanged": 19,
|
||||
"new_rows": 0
|
||||
},
|
||||
"geo_locations": {
|
||||
"old_rows_unchanged": 1921,
|
||||
"new_rows": 0
|
||||
},
|
||||
"sectors": {
|
||||
"old_rows_unchanged": 12,
|
||||
"new_rows": 0
|
||||
},
|
||||
"documents": {
|
||||
"old_rows_unchanged": 63,
|
||||
"new_rows": 0
|
||||
},
|
||||
"value_chains": {
|
||||
"old_rows_unchanged": 0,
|
||||
"new_rows": 0
|
||||
},
|
||||
"audit_events": {
|
||||
"old_rows_unchanged": 394,
|
||||
"new_rows": 5
|
||||
},
|
||||
"organizations": {
|
||||
"old_rows_unchanged": 3,
|
||||
"new_rows": 0
|
||||
},
|
||||
"users": {
|
||||
"old_rows_unchanged": 40,
|
||||
"new_rows": 0
|
||||
},
|
||||
"investor_journeys": {
|
||||
"old_rows_unchanged": 15,
|
||||
"new_rows": 1
|
||||
},
|
||||
"journey_steps": {
|
||||
"old_rows_unchanged": 285,
|
||||
"new_rows": 19
|
||||
}
|
||||
}
|
||||
},
|
||||
"report": {
|
||||
"record_id": 402,
|
||||
"evidence_rows": 5,
|
||||
"source_version": 1,
|
||||
"context_revision": 1,
|
||||
"source_recovered_without_loss": true,
|
||||
"hypothesis_and_historic_period_visible": true,
|
||||
"commercial_inputs_unknown": true,
|
||||
"existing_report_helper": true,
|
||||
"accepted_suites_not_repeated": true
|
||||
},
|
||||
"source_register": [
|
||||
{
|
||||
"file": "ine-gurue-2020-2024.pdf",
|
||||
"url": "https://ine.gov.mz/documents/20119/337384/2_Gurue-%20Final_Junho2025.pdf/602d05a3-be99-47a4-be68-5277c4ca4a2f?download=true&t=1751024727586&version=1.0",
|
||||
"bytes": 3038756,
|
||||
"sha256": "9f0d3b868cfd3401f8d4f2fcceae0e5be164ba6dab927d1210e247b1711093d4",
|
||||
"accessed": "2026-10-27",
|
||||
"use": "Private read-only source copy;not imported or published"
|
||||
},
|
||||
{
|
||||
"file": "magoma-primary.html",
|
||||
"url": "https://www.asianteagroup.com/foot-gurue.html",
|
||||
"bytes": 5590,
|
||||
"sha256": "5881a5ec9a4b223932508fd48896c8a467a01387fdc7923eda4c4cb192adad9d",
|
||||
"accessed": "2026-10-27",
|
||||
"use": "Private read-only source copy;not imported or published"
|
||||
},
|
||||
{
|
||||
"file": "igc-enterprise-map-2014.pdf",
|
||||
"url": "https://www.theigc.org/wp-content/uploads/2014/06/An-Enterprise-Map-of-Mozambique-English.pdf",
|
||||
"bytes": 1746681,
|
||||
"sha256": "2d02a47c9e806490ba8d0cc016ef23d34bf8818f1b1c2dde5a0806818fa35c67",
|
||||
"accessed": "2026-10-27",
|
||||
"use": "Private read-only source copy;not imported or published"
|
||||
}
|
||||
],
|
||||
"provided_private_workbook": {
|
||||
"sha256": "1b5087b464e39e88c42def39655c2391aaaf684b4c832d6a77ff274b98889f00",
|
||||
"historical_reference_dates": [
|
||||
"2021-09-30",
|
||||
"2023-11-09",
|
||||
"2022-03-17"
|
||||
],
|
||||
"no_personal_data_or_contacts_exported": true,
|
||||
"not_imported_or_published": true
|
||||
},
|
||||
"pilot_limits": [
|
||||
"Activity documented;current unmet need and commercial interest unconfirmed",
|
||||
"2014 source is historical;no current volumes/prices/capacity inferred",
|
||||
"No assumed external green-leaf buyer,new factory,land access or certification",
|
||||
"Beneficiaries are not automatically buyers or payers"
|
||||
],
|
||||
"preserved": {
|
||||
"L8": "14360748194f3658d91a7d7ae5615efd0fcbfbb7",
|
||||
"SGF_TEMPO": "untouched",
|
||||
"accepted_proofs": "reused_without_repeating_suites",
|
||||
"main_last_read": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5"
|
||||
},
|
||||
"installation": "No remote or deployment operation;capacity remains a precondition to next installation",
|
||||
"private_outputs": "outputs/proactive-handoff-gurue-20261027/",
|
||||
"new_application_code": false
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
{
|
||||
"status": "QA_complete_candidate_not_installed",
|
||||
"date": "2026-10-27",
|
||||
"runtime_commit": "3439f35038f15c93224e6cf876bf559135824d13",
|
||||
"baseline_main": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"branch": "codex/proactive-investment-first-qa-20261027",
|
||||
"QA_directory": "C:\\laragon\\www\\portal-investidor-proactive-qa-20261027",
|
||||
"root_checkout": "C:/laragon/www/portal-investidor",
|
||||
"unavailable_local_scope_commit": "fa02c70",
|
||||
"unavailable_commit_is_not_dependency": true,
|
||||
"L8_candidate_preserved": "14360748194f3658d91a7d7ae5615efd0fcbfbb7",
|
||||
"L8_not_integrated_or_modified": true,
|
||||
"server_or_SGF_operations": false,
|
||||
"scope": "territory/sector,evidence,need,structuredidea,existingencryptedDossier;manualeditorialpreparation beforeAI",
|
||||
"existing_models_reused": [
|
||||
"geo_locations",
|
||||
"sectors",
|
||||
"value_chains",
|
||||
"projects",
|
||||
"economic_clusters",
|
||||
"development_corridors",
|
||||
"investment_zones",
|
||||
"Opportunity.management_draft",
|
||||
"audit_events",
|
||||
"portal_resources",
|
||||
"documents",
|
||||
"opportunity_documents",
|
||||
"desk_cases",
|
||||
"InvestorContext",
|
||||
"InvestmentConsumerScope",
|
||||
"InvestorPath"
|
||||
],
|
||||
"new_tables_or_migrations": false,
|
||||
"new_organisational_approvers_or_roles": false,
|
||||
"auth_delta": "Existing internal assignment may prepare/edit proactive drafts with real promoter unknown;all other role and operational checks retained and tested",
|
||||
"checks": {
|
||||
"API_tests": 14,
|
||||
"API_assertions": 139,
|
||||
"frontend_report_tests": 7,
|
||||
"database": "proactive_investment_20261027_test",
|
||||
"clone_source": "simulator_fiscal_delta_20261021_test",
|
||||
"host": "127.0.0.1",
|
||||
"port": 55441,
|
||||
"guarded": true,
|
||||
"API_transaction_rollback": true,
|
||||
"UI_persistent_synthetic_data_only_in_clone": true,
|
||||
"normal_password_and_MFA_UI": true,
|
||||
"UI": {
|
||||
"actualLaravelHTTP": true,
|
||||
"normalPasswordAndMFA": true,
|
||||
"createSaveRecoverEdit": true,
|
||||
"hypothesisAndConfirmedHistory": true,
|
||||
"onlyApplicableGroupsShown": true,
|
||||
"selectedRelationshipsAndAssumptionsTransported": true,
|
||||
"privateRelationshipReferenceNotExposed": true,
|
||||
"noBudgetPromoterCoordinatesRequired": true,
|
||||
"existingTerritoryAndSector": true,
|
||||
"explicitPromotionPreviewConfirm": true,
|
||||
"anonymousOnlyAuthorisedPublicContent": true,
|
||||
"authReturnPreservesSource": true,
|
||||
"existingDossier": true,
|
||||
"deliberateTitlePreserved": true,
|
||||
"reloadAndResumeSession": true,
|
||||
"publicUrl": "http://127.0.0.1:18760/oportunidades/inv-mz-gen-5137141825128895?perspective=ideas§or=energia-especifica",
|
||||
"record_id": 383,
|
||||
"dossier_id": "139e5faf-4979-4e2c-9a92-3e1465431642",
|
||||
"errors": []
|
||||
},
|
||||
"Wayfinder_with_form": "passed",
|
||||
"TypeScript": "passed",
|
||||
"isolated_QA_build": "passed",
|
||||
"build_advisories": [
|
||||
"Existing chunk-size and plugin-timing diagnostics;no buildfailure"
|
||||
],
|
||||
"unaffected_accepted_suites_not_repeated": true
|
||||
},
|
||||
"preservation": {
|
||||
"baseline": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"tracked_files_before": 2830,
|
||||
"changed_existing_files": [
|
||||
"app/Http/Controllers/OpportunityManagementController.php",
|
||||
"app/Models/Opportunity.php",
|
||||
"app/Services/InvestmentCatalogue.php",
|
||||
"app/Services/InvestorContext.php",
|
||||
"app/Services/OpportunityManagement.php",
|
||||
"app/Services/OpportunityPromotion.php",
|
||||
"app/Services/PortalProfileAccess.php",
|
||||
"docs/investmoz/consolidated-review-matrix-2026-10-03.md",
|
||||
"docs/investmoz/unification/traceability-and-manual.md",
|
||||
"docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv",
|
||||
"resources/js/components/opportunity-search-filters.tsx",
|
||||
"resources/js/lib/project-dossier.ts",
|
||||
"resources/js/pages/investment/catalogue.tsx",
|
||||
"resources/js/pages/investment/detail.tsx",
|
||||
"resources/js/pages/investment/shared.tsx",
|
||||
"resources/js/pages/investor-path/show.tsx",
|
||||
"resources/js/pages/management/opportunity-draft.tsx",
|
||||
"resources/js/pages/management/opportunity-promotion.tsx"
|
||||
],
|
||||
"unchanged_existing_files": 2812,
|
||||
"fiscal_engines_unchanged": 89,
|
||||
"fiscal_originals_unchanged": 31,
|
||||
"Rwanda_originals_unchanged": true,
|
||||
"L8_candidate_14360748_unchanged": true,
|
||||
"auth_delta": "Existing internal assignment may prepare/edit proactive drafts with real promoter unknown;all other role and operational checks retained and tested",
|
||||
"source_Database_and_active_environment_not_written": true,
|
||||
"QA_database": "proactive_investment_20261027_test",
|
||||
"clone_source": "simulator_fiscal_delta_20261021_test",
|
||||
"port": 55441,
|
||||
"root_runtime_not_changed": true,
|
||||
"SGF_TEMPO_untouched": true,
|
||||
"accepted_unaffected_suites_not_repeated": true,
|
||||
"no_migrations_config_or_active_grant_changes": true,
|
||||
"QA_synthetic_grants_only_in_isolated_clone": true,
|
||||
"includes_documentation_delta": true
|
||||
},
|
||||
"Rwanda_methodology": {
|
||||
"status": "user_provided_sources_located_and_relevant_passages_read",
|
||||
"date": "2026-10-27",
|
||||
"purpose": "Internal methodology for QA editorial preparation;not local economic evidence",
|
||||
"originals_unchanged": true,
|
||||
"no_source_publication_or_import": true,
|
||||
"no_foreign_tax_or_institutional_rules_imported": true,
|
||||
"sources": [
|
||||
{
|
||||
"path": "c:\\Mac\\Home\\Documents\\Docs pessoais\\Backup\\Documentos – MacBook Pro de Macbook\\Docs\\Rwanda\\20070627_Rwanda_5d0cc43d-c990-4cf1-8ee9-ada71094918f.pdf",
|
||||
"sha256": "18b07a9379a1ad0baa33697d57d6237f15a6fec346db44bfee7506bf1fa27dee",
|
||||
"bytes": 335937,
|
||||
"title": "Creating a Competitive Rwanda",
|
||||
"author": "Professor Michael E. Porter, Harvard Business School",
|
||||
"edition": "Kigali,June2007 (cover)",
|
||||
"pages": 31,
|
||||
"visual_pages_inspected": [
|
||||
1,
|
||||
14,
|
||||
27
|
||||
],
|
||||
"passages": [
|
||||
{
|
||||
"page": 14,
|
||||
"heading": "Improving the Business Environment: The Diamond",
|
||||
"application_pt": "Inventariar factores de produção, condições de procura e fornecedores/actividades de apoio;cada afirmação local depende de fonte e cobertura próprias."
|
||||
},
|
||||
{
|
||||
"page": 27,
|
||||
"heading": "Role of the Private Sector in Economic Development",
|
||||
"application_pt": "Identificar fornecedores, infra-estruturas e competências como relações a investigar;proximidade não cria compromisso ou acesso."
|
||||
}
|
||||
],
|
||||
"extraction": "pypdf;selectedpages rendered withPyMuPDF and visually inspected"
|
||||
},
|
||||
{
|
||||
"path": "c:\\Mac\\Home\\Documents\\Docs pessoais\\Backup\\Documentos – MacBook Pro de Macbook\\Docs\\Rwanda\\Rwanda Competitiveness Briefing_Prof Porter_OTF.ppt",
|
||||
"sha256": "4a9325ad64278cb0ef3c60367a05ee2ed9262e2cd49a48d579061349914aa830",
|
||||
"bytes": 1755648,
|
||||
"title": "How Rwanda Competes Today — Rwanda National Innovation and Competitiveness Program",
|
||||
"edition": "July20,2008;Executive Briefing for Prof.MichaelPorter,slide1",
|
||||
"slides": 50,
|
||||
"native_PowerPoint_read_only": true,
|
||||
"visual_slides_inspected": [
|
||||
17
|
||||
],
|
||||
"passages": [
|
||||
{
|
||||
"slide": 17,
|
||||
"heading": "Tourism Cluster—What the market is telling us",
|
||||
"application_pt": "Conservar origem,período,cobertura e amostra das observações de procura;interesse declarado de um inquirido não equivale a contrato ou encomenda em Moçambique.",
|
||||
"source_note": "OTF Tourism Channel Partner Survey,January2007,n=90,scale1–7 visible in slide;figures not transferred to pilotcases."
|
||||
},
|
||||
{
|
||||
"slide": 20,
|
||||
"heading": "Tea Cluster—Persistent constraints",
|
||||
"application_pt": "Estruturar a análise por etapas de produção,recolha,transformação,transporte e comercialização;as limitações do Ruanda não são lacunas comprovadas do Gurué.",
|
||||
"inspection": "Text extracted in native slide order;not yet visually inspected."
|
||||
},
|
||||
{
|
||||
"slide": 24,
|
||||
"heading": "Mining Cluster – Situation analysis",
|
||||
"application_pt": "Perguntar por competências,informação,fornecedores e serviços relacionados;nenhuma necessidade de Montepuez é inferida desta lista estrangeira.",
|
||||
"inspection": "Native text extracted;not visualproof."
|
||||
}
|
||||
],
|
||||
"extraction": "Legacy OLE exploratoryextraction followed bynativePowerPointreadonly extraction;native50slideorder is authoritative. OldOLE91historicaltextgroups not used as slide count."
|
||||
}
|
||||
],
|
||||
"implementation_mapping": [
|
||||
"evidence.category+purpose+source+locator+period+scope+coverage+verified_on",
|
||||
"methodology evidence cannot by itself confirm localneed",
|
||||
"need.type quantity/quality/logistics/processing/coordination/support",
|
||||
"idea.chain_id+stage+documentedresources+relations",
|
||||
"hypothesis vs confirmedneed vs preparation vs actualavailability separated"
|
||||
],
|
||||
"limitations": [
|
||||
"No actualpilot demand,supply,market_size,profitability or investmentcosts validated",
|
||||
"No direct or indirect disclosure of privatecompanylists or originaldecks",
|
||||
"Copyright/proprietary notices preserved;excerpts and renders remain ignored QA evidence,not public app assets"
|
||||
]
|
||||
},
|
||||
"public_projection_rules": [
|
||||
"No automatic private-to-public field copy",
|
||||
"Only selected public evidence and publictarget relationships",
|
||||
"Private relationship reference omitted",
|
||||
"Internal document classification,rights,scan and ownership link retained",
|
||||
"Literal private evidence reuse blocked;indirect disclosure is explicitly reviewed by existing editor",
|
||||
"Analytical state and publication state separate",
|
||||
"No automatic contract,availability,land,power,viability or taxbenefit"
|
||||
],
|
||||
"pilots": [
|
||||
{
|
||||
"context": "Cahora Bassa",
|
||||
"sector": "Energia",
|
||||
"territory": "bcc9e3cb-2359-524c-af4e-0ebc6f141d3d",
|
||||
"status": "synthetic_QA_only"
|
||||
},
|
||||
{
|
||||
"context": "Montepuez",
|
||||
"sector": "Mineração",
|
||||
"territory": "d4fb92cc-d278-5f69-9490-a98e6dfef18d",
|
||||
"status": "synthetic_QA_only"
|
||||
},
|
||||
{
|
||||
"context": "Gurué",
|
||||
"sector": "Agronegócio/cadeia do chá",
|
||||
"territory": "87a8ba3d-b152-560c-a566-7db4531ad536",
|
||||
"status": "synthetic_QA_only"
|
||||
}
|
||||
],
|
||||
"remaining": {
|
||||
"implemented_demonstrated": "Editorial technical workflow and scoped continuity listed in manual",
|
||||
"partial": "Real local economic analysis and availability of actual participations,not claimed",
|
||||
"documentary_dependencies": "Local evidence,period,coverage,source and specific contract/access/availability claims;onlydependentcase blocked",
|
||||
"resolved_dependency": "Both Rwanda exemplars available and passages inspected",
|
||||
"future": "Automaticintelligence/prioritisation/indicators/AI and economic quantification when data exist;not required for firsteditorial increment",
|
||||
"active_installation": "Out of authorised scope;futurefreshcompatibility/capacity/backuprestore required"
|
||||
},
|
||||
"matrix_ids_updated": [
|
||||
"RF-CLU-003",
|
||||
"MASTER-471012ab-0010",
|
||||
"MASTER-9dee08d0-0067",
|
||||
"MASTER-471012ab-0067"
|
||||
],
|
||||
"documentation_append_only": true,
|
||||
"evidence_directory": "outputs/proactive-investment-20261027/",
|
||||
"no_economic_validation": true,
|
||||
"no_actual_publication_or_homologation_installation": true
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"status": "private_opportunity_hypothesis_updated_dossier_v2_technical_delivery_independent",
|
||||
"date": "2026-10-27",
|
||||
"user_direction": "A ideia não é gerir concursos mas sim as oportunidades que geram.",
|
||||
"case_id": "CB-METROLOGIA-20261027",
|
||||
"baseline": "4f9450a71dcc03f17abe953c956956249798d4c0",
|
||||
"technical_candidate_preserved": "1afab4a2a71f182f260e4d2555d79242261a4d2a",
|
||||
"runtime_unchanged": "3439f35038f15c93224e6cf876bf559135824d13",
|
||||
"branch": "codex/proactive-opportunity-model-qa-20261027",
|
||||
"proof": {
|
||||
"case_id": "CB-METROLOGIA-20261027",
|
||||
"record_id": 401,
|
||||
"dossier_id": "894343c7-c33d-452e-a6a5-b6675f77ee23",
|
||||
"previous_source_version": 1,
|
||||
"new_source_version": 2,
|
||||
"before_context_revision": 1,
|
||||
"after_context_revision": 2,
|
||||
"direction": "Investment opportunity generated by demand;not tender management",
|
||||
"need_state": "hypothesis",
|
||||
"evidence_count": 7,
|
||||
"private_draft_not_published": true,
|
||||
"dossier_source_refreshed_through_preview_and_confirmation": true,
|
||||
"deliberate_dossier_fields_unchanged": true,
|
||||
"previous_audit_rows_unchanged": true,
|
||||
"no_new_entities_or_grants": true,
|
||||
"no_new_application_code": true,
|
||||
"accepted_technical_proofs_reused": true,
|
||||
"no_contact_or_server_operations": true,
|
||||
"QA_database": "proactive_investment_20261027_test",
|
||||
"row_preservation": {
|
||||
"opportunities": {
|
||||
"old_rows_unchanged": 52,
|
||||
"updated_case_rows_only": [
|
||||
"401"
|
||||
],
|
||||
"new_rows": 0
|
||||
},
|
||||
"desk_cases": {
|
||||
"old_rows_unchanged": 17,
|
||||
"updated_case_rows_only": [
|
||||
"894343c7-c33d-452e-a6a5-b6675f77ee23"
|
||||
],
|
||||
"new_rows": 0
|
||||
},
|
||||
"projects": {
|
||||
"old_rows_unchanged": 19,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 0
|
||||
},
|
||||
"geo_locations": {
|
||||
"old_rows_unchanged": 1921,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 0
|
||||
},
|
||||
"sectors": {
|
||||
"old_rows_unchanged": 12,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 0
|
||||
},
|
||||
"documents": {
|
||||
"old_rows_unchanged": 63,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 0
|
||||
},
|
||||
"value_chains": {
|
||||
"old_rows_unchanged": 0,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 0
|
||||
},
|
||||
"audit_events": {
|
||||
"old_rows_unchanged": 388,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
"focus": "Recurring complementary service generated by documented demand;customer problem,value,partners and resources",
|
||||
"new_sources": [
|
||||
{
|
||||
"title": "Anúncio HCB17/08/2026,051/2026",
|
||||
"url": "https://www.diarioeconomico.co.mz/wp-content/uploads/2026/08/concurso-hcb-tender-document-docu-mo-ambique-2026-1.pdf",
|
||||
"sha256": "bb4c33064e5d49504d8a85ac88ad1b847cfa6c69e1016e3ab588ff785b205c1f",
|
||||
"pages": 2,
|
||||
"visually_read": [
|
||||
1,
|
||||
2
|
||||
],
|
||||
"role": "Demand evidence and scope;not a new tender workflow"
|
||||
},
|
||||
{
|
||||
"title": "IPAC M0100 INNOQ–LM",
|
||||
"url": "https://www.ipac.pt/pesquisa/ficha_lac.asp?ID=M0100",
|
||||
"consulted": "2026-10-27",
|
||||
"technical_annex": "2026-02-17",
|
||||
"binary_snapshot": null,
|
||||
"binary_download_error": "Connection reset;web reading available",
|
||||
"role": "Potential national laboratory capability by scope;no partnership or full HCB eligibility granted"
|
||||
}
|
||||
],
|
||||
"commercial_questions": [
|
||||
"Que problema operacional recorrente existe no ciclo dos instrumentos e como é resolvido actualmente?",
|
||||
"Quais as famílias/modelos/gamas,quantidades,pontos e periodicidades?Que critérios de aceitação e prazo de devolução?",
|
||||
"O ciclo actual já está coberto?Que necessidade futura permanece e quando?",
|
||||
"Aceitaria serviço local associado?Que parte pode ser prestada fora do laboratório e com que responsabilidades?",
|
||||
"Qual o custo e tempo totais da solução actual e que melhoria justificaria pagar por apoio local?"
|
||||
],
|
||||
"partner_questions": [
|
||||
"Que instrumentos,gamas,pontos,incertezas,locais e prazos consegue cobrir hoje?",
|
||||
"Qual o âmbito acreditado/competência aplicável e que serviços ficam fora dele?",
|
||||
"Tem equipa,meios,disponibilidade e interesse em associação para apoio no Songo?",
|
||||
"Quais as responsabilidades,preços,transporte/embalagem/seguro e condições de custódia e rastreabilidade?"
|
||||
],
|
||||
"decision_paths": [
|
||||
{
|
||||
"condition": "Customer confirms recurring need,actual problem and willingness to consider service",
|
||||
"action": "Match partners and equivalent quotes;quantify business model before qualifying opportunity"
|
||||
},
|
||||
{
|
||||
"condition": "Past purchase satisfied current cycle;documented future need remains",
|
||||
"action": "Prepare future service horizon with actual timing,volume and conditions;do not reopen past tender"
|
||||
},
|
||||
{
|
||||
"condition": "Customer confirms current need fulfilled and no future/recurring need for proposed service",
|
||||
"action": "Archive hypothesis with dated buyer evidence and retain dossier history;do not treat missing information as no demand"
|
||||
},
|
||||
{
|
||||
"condition": "Data insufficient",
|
||||
"action": "Keep private hypothesis;affects only this business case,not technical delivery"
|
||||
}
|
||||
],
|
||||
"economic_comparison": {
|
||||
"basis": "Same instruments,quantity,frequency,quality,place and period;current solution vs proposed associated service",
|
||||
"current_solution_total": null,
|
||||
"proposed_service_total": null,
|
||||
"quantity": null,
|
||||
"period": null,
|
||||
"net_advantage": null,
|
||||
"missing_is_not_zero": true,
|
||||
"inputs": [
|
||||
"Laboratory service quotes",
|
||||
"Total transport/packing/insurance and return",
|
||||
"Local support cost",
|
||||
"Nonduplicated incremental fixed costs for same period",
|
||||
"Instrument turnaround days and substantiated operational impact"
|
||||
],
|
||||
"decision": "No positive advantage assumed;compare cost and time separately until both are measured. No generic wage,distance,tax or downtime assumptions."
|
||||
},
|
||||
"public_search_scope_limit": "No identifiable award/execution or2027commitment located in consulted public sources;absence of result is not proof of no contract. Supplier portal timed out via web and local TLS issuer verification failed;not bypassed. No further repeated search planned without new document or buyer input.",
|
||||
"not_a_tender_management_increment": true,
|
||||
"technical_release_independent_of_commercial_case": true,
|
||||
"no_installation_publication_or_external_messages": true,
|
||||
"L8_preserved": "14360748194f3658d91a7d7ae5615efd0fcbfbb7",
|
||||
"SGF_untouched": true,
|
||||
"evidence_directory": "outputs/proactive-commercial-followup-20261027",
|
||||
"matrix_ids": [
|
||||
"RF-CLU-003",
|
||||
"MASTER-471012ab-0010",
|
||||
"MASTER-9dee08d0-0067",
|
||||
"MASTER-471012ab-0067"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
{
|
||||
"status": "real_source_preliminary_case_demonstrated_private_QA_not_published",
|
||||
"date": "2026-10-27",
|
||||
"case_id": "CB-METROLOGIA-20261027",
|
||||
"baseline_candidate": "1afab4a2a71f182f260e4d2555d79242261a4d2a",
|
||||
"runtime_unchanged": "3439f35038f15c93224e6cf876bf559135824d13",
|
||||
"branch": "codex/proactive-real-pilot-qa-20261027",
|
||||
"new_application_code": false,
|
||||
"QA_database": "proactive_investment_20261027_test",
|
||||
"proof": {
|
||||
"case_id": "CB-METROLOGIA-20261027",
|
||||
"record_id": 401,
|
||||
"dossier_id": "894343c7-c33d-452e-a6a5-b6675f77ee23",
|
||||
"QA_only": true,
|
||||
"real_primary_sources": true,
|
||||
"synthetic_operator_only": true,
|
||||
"created_saved_recovered_via_existing_UI": true,
|
||||
"existing_private_dossier": true,
|
||||
"need_state": "hypothesis",
|
||||
"past_procurement_dates_explicit": true,
|
||||
"client_potential_not_committed": true,
|
||||
"all_five_evidence_entries_retained": true,
|
||||
"internal_workbook_reference_retained_privately": true,
|
||||
"territory_preserved": true,
|
||||
"no_economic_numbers_invented": true,
|
||||
"no_publication_action": true,
|
||||
"no_external_messages": true,
|
||||
"anonymous_dossier_denied": true,
|
||||
"accepted_technical_suites_not_repeated": true,
|
||||
"errors": []
|
||||
},
|
||||
"private_record": {
|
||||
"record_id": 401,
|
||||
"status": "draft",
|
||||
"not_published": true,
|
||||
"unknown_amount_preserved": true,
|
||||
"unknown_real_promoter_preserved": true,
|
||||
"QA_database": "proactive_investment_20261027_test"
|
||||
},
|
||||
"selection": {
|
||||
"selected": "Cahora Bassa",
|
||||
"reason": "Acervo empresarial interno com referências locais + relatório primário HCB2024 + plano primário compras2026 com serviço delimitado. É a combinação de fontes mais directamente utilizável nesta leitura dirigida.",
|
||||
"alternatives": [
|
||||
{
|
||||
"pilot": "Montepuez",
|
||||
"available": "Registos empresariais internos e documentação pública mineira; não se seleccionou um procedimento primário e necessidade tão delimitados nesta ronda.",
|
||||
"limitation": "Não equivale a falta de actividade ou inexistência de necessidades. Sem ranking económico."
|
||||
},
|
||||
{
|
||||
"pilot": "Gurué",
|
||||
"available": "Registos internos com actividades ligadas ao chá e referências públicas territoriais; as fontes de constrangimentos localizadas são antigas ou não delimitam uma procura actual específica.",
|
||||
"limitation": "O piloto continua válido para estudo posterior; não se presume que os constrangimentos antigos persistem."
|
||||
}
|
||||
]
|
||||
},
|
||||
"idea": "Associação de apoio local no Songo com laboratório qualificado para apoio metrológico à HCB; hipótese comercial.",
|
||||
"known_vs_unknown": {
|
||||
"known": "Actividade HCB e necessidade planeada de calibração2026; referências empresariais históricas internas.",
|
||||
"unknown": "Estado/recorrência da contratação,procura por satisfazer,volume,requisitos,oferta e parceiros actuais,preços,meios e viabilidade.",
|
||||
"not_inferred": "Concurso aberto,adjudicação,ausência de oferta,disponibilidade comercial,contrato,acesso,terra,energia ou benefício fiscal."
|
||||
},
|
||||
"source_manifest": [
|
||||
{
|
||||
"alias": "companies.xlsx",
|
||||
"original": "C:\\Mac\\Home\\Documents\\TEMPO\\Portal Tempo\\Dados de empresas\\EMPRESAS_LIST 2014-2022.xlsx",
|
||||
"bytes": 26586267,
|
||||
"sha256": "1ba4c4114b16b407e7746712d00d4f681246bbbc1b42351e96a31f7129acad30",
|
||||
"use": "private analytical read-only working copy; original unchanged"
|
||||
},
|
||||
{
|
||||
"alias": "licensed.xlsx",
|
||||
"original": "C:\\Mac\\Home\\Documents\\TEMPO\\Portal Tempo\\Servicos Tempo\\Relatorios\\novos\\docs\\Empresas Licenciadas.xlsx",
|
||||
"bytes": 34940776,
|
||||
"sha256": "1b5087b464e39e88c42def39655c2391aaaf684b4c832d6a77ff274b98889f00",
|
||||
"use": "private analytical read-only working copy; original unchanged"
|
||||
},
|
||||
{
|
||||
"alias": "tourism.xlsx",
|
||||
"original": "C:\\Mac\\Home\\Documents\\TEMPO\\Portal Tempo\\Servicos Tempo\\Relatorios\\novos\\docs\\CADASTRO DE EMPREENDIMENTOS TURISTICOS 3, 4 E 5 ESTRELAS 30.10.24 18,00h.xlsx",
|
||||
"bytes": 73955,
|
||||
"sha256": "f02e086ed4973ef17234aa6cc54b98fbb7a6952ffb16ec4dc4f7d0c72af6400c",
|
||||
"use": "private analytical read-only working copy; original unchanged"
|
||||
},
|
||||
{
|
||||
"alias": "hcb-concession.pdf",
|
||||
"original": "C:\\Mac\\Home\\Documents\\TEMPO\\Portal Tempo\\Legislacao\\MIREME\\HCB-TERMOS-DO-CONTRATO-DE-CONCESSAO.pdf",
|
||||
"bytes": 142063,
|
||||
"sha256": "f4afc62f140d197cae3bf395674adce2eba37f0436261d52d7eb554f6230a073",
|
||||
"use": "private analytical read-only working copy; original unchanged"
|
||||
},
|
||||
{
|
||||
"alias": "hcb-plan-2026.pdf",
|
||||
"url": "https://igepe.org.mz/wp-content/uploads/2026/06/HCB-Plano-Anual-de-Aquisicoes-2026.pdf",
|
||||
"bytes": 319956,
|
||||
"sha256": "cbc93102fea61a712c193d1c1815e7ec19e7d570ee2703c1b1390d4c05e5bd8e",
|
||||
"accessed": "2026-10-27",
|
||||
"use": "read-only primary source; no portal publication/import"
|
||||
},
|
||||
{
|
||||
"alias": "hcb-report-2024.pdf",
|
||||
"url": "https://hcbadm.mzbusiness.com/wp-content/uploads/2025/08/Relatorio-e-Contas-2024-Bilingue-VF-1.pdf",
|
||||
"bytes": 8215895,
|
||||
"sha256": "d0fed6af0e40fffd6f7f385152fdbfff2a10cae0b66c9d7a59a0a99658758080",
|
||||
"accessed": "2026-10-27",
|
||||
"use": "read-only primary source; no portal publication/import"
|
||||
},
|
||||
{
|
||||
"alias": "hcb-hidroelectricidade.html",
|
||||
"url": "https://www.hcb.co.mz/hidroelectricidade",
|
||||
"bytes": 52772,
|
||||
"sha256": "c5de0e6204909c6cdaea7b249c79897f1cc8539c4f58e4704e4d5844f9542a49",
|
||||
"accessed": "2026-10-27",
|
||||
"use": "read-only primary source; no portal publication/import"
|
||||
},
|
||||
{
|
||||
"alias": "cae.xlsx",
|
||||
"original": "C:/Mac/Home/Documents/TEMPO/Portal Tempo/Dados de empresas/CAE eBAU.xlsx",
|
||||
"bytes": 75018,
|
||||
"sha256": "83b4f1200988e99834c2ae3915346fbf237d128308554b67b5a080d4956bf506",
|
||||
"use": "read-only supplied code labels B857/F857 and B859/F859; not current official-version inference"
|
||||
}
|
||||
],
|
||||
"originals_unchanged": [
|
||||
{
|
||||
"alias": "companies.xlsx",
|
||||
"original_unchanged": true,
|
||||
"sha256": "1ba4c4114b16b407e7746712d00d4f681246bbbc1b42351e96a31f7129acad30"
|
||||
},
|
||||
{
|
||||
"alias": "licensed.xlsx",
|
||||
"original_unchanged": true,
|
||||
"sha256": "1b5087b464e39e88c42def39655c2391aaaf684b4c832d6a77ff274b98889f00"
|
||||
},
|
||||
{
|
||||
"alias": "tourism.xlsx",
|
||||
"original_unchanged": true,
|
||||
"sha256": "f02e086ed4973ef17234aa6cc54b98fbb7a6952ffb16ec4dc4f7d0c72af6400c"
|
||||
},
|
||||
{
|
||||
"alias": "hcb-concession.pdf",
|
||||
"original_unchanged": true,
|
||||
"sha256": "f4afc62f140d197cae3bf395674adce2eba37f0436261d52d7eb554f6230a073"
|
||||
},
|
||||
{
|
||||
"alias": "cae.xlsx",
|
||||
"original_unchanged": true,
|
||||
"sha256": "83b4f1200988e99834c2ae3915346fbf237d128308554b67b5a080d4956bf506"
|
||||
}
|
||||
],
|
||||
"old_QA_rows_unchanged": {
|
||||
"opportunities": {
|
||||
"old_rows_unchanged": 52,
|
||||
"new_rows": 1
|
||||
},
|
||||
"desk_cases": {
|
||||
"old_rows_unchanged": 17,
|
||||
"new_rows": 1
|
||||
},
|
||||
"projects": {
|
||||
"old_rows_unchanged": 19,
|
||||
"new_rows": 0
|
||||
},
|
||||
"geo_locations": {
|
||||
"old_rows_unchanged": 1921,
|
||||
"new_rows": 0
|
||||
},
|
||||
"sectors": {
|
||||
"old_rows_unchanged": 12,
|
||||
"new_rows": 0
|
||||
},
|
||||
"documents": {
|
||||
"old_rows_unchanged": 63,
|
||||
"new_rows": 0
|
||||
},
|
||||
"value_chains": {
|
||||
"old_rows_unchanged": 0,
|
||||
"new_rows": 0
|
||||
}
|
||||
},
|
||||
"technical_accepted_tests_not_repeated": true,
|
||||
"economic_payload_and_recovered_context_private_only": true,
|
||||
"new_publication": false,
|
||||
"external_contact": false,
|
||||
"server_operations": false,
|
||||
"SGF_changes": false,
|
||||
"L8_preserved": "14360748194f3658d91a7d7ae5615efd0fcbfbb7",
|
||||
"matrix_ids": [
|
||||
"RF-CLU-003",
|
||||
"MASTER-471012ab-0010",
|
||||
"MASTER-9dee08d0-0067",
|
||||
"MASTER-471012ab-0067"
|
||||
],
|
||||
"local_proof_directory": "outputs/proactive-real-pilot-20261027",
|
||||
"private_report": "outputs/proactive-real-pilot-20261027/real-case-private-report.html",
|
||||
"next_action": "Preparar reunião exploratória com as perguntas de estado/recorrência,âmbito técnico,oferta,associação e vantagem;nenhuma mensagem enviada."
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
{
|
||||
"status": "private_regional_opportunity_hypothesis_v3_sustainability_not_demonstrated",
|
||||
"date": "2026-10-27",
|
||||
"baseline": "52f54655d2827e97da2f15d14033e9a2713dddf1",
|
||||
"branch": "codex/proactive-regional-clients-qa-20261027",
|
||||
"runtime_unchanged": "3439f35038f15c93224e6cf876bf559135824d13",
|
||||
"case_id": "CB-METROLOGIA-20261027",
|
||||
"proof": {
|
||||
"case_id": "CB-METROLOGIA-20261027",
|
||||
"record_id": 401,
|
||||
"dossier_id": "894343c7-c33d-452e-a6a5-b6675f77ee23",
|
||||
"previous_source_version": 2,
|
||||
"new_source_version": 3,
|
||||
"before_context_revision": 2,
|
||||
"after_context_revision": 3,
|
||||
"direction": "Regional complementary investment opportunity;three additional prospects,commercial data missing",
|
||||
"need_state": "hypothesis",
|
||||
"evidence_count": 11,
|
||||
"private_draft_not_published": true,
|
||||
"dossier_source_refreshed_through_preview_and_confirmation": true,
|
||||
"deliberate_dossier_fields_unchanged": true,
|
||||
"previous_audit_rows_unchanged": true,
|
||||
"no_new_entities_or_grants": true,
|
||||
"no_new_application_code": true,
|
||||
"accepted_technical_proofs_reused": true,
|
||||
"no_contact_or_server_operations": true,
|
||||
"QA_database": "proactive_investment_20261027_test",
|
||||
"row_preservation": {
|
||||
"opportunities": {
|
||||
"old_rows_unchanged": 52,
|
||||
"updated_case_rows_only": [
|
||||
"401"
|
||||
],
|
||||
"new_rows": 0
|
||||
},
|
||||
"desk_cases": {
|
||||
"old_rows_unchanged": 17,
|
||||
"updated_case_rows_only": [
|
||||
"894343c7-c33d-452e-a6a5-b6675f77ee23"
|
||||
],
|
||||
"new_rows": 0
|
||||
},
|
||||
"projects": {
|
||||
"old_rows_unchanged": 19,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 0
|
||||
},
|
||||
"geo_locations": {
|
||||
"old_rows_unchanged": 1921,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 0
|
||||
},
|
||||
"sectors": {
|
||||
"old_rows_unchanged": 12,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 0
|
||||
},
|
||||
"documents": {
|
||||
"old_rows_unchanged": 63,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 0
|
||||
},
|
||||
"value_chains": {
|
||||
"old_rows_unchanged": 0,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 0
|
||||
},
|
||||
"audit_events": {
|
||||
"old_rows_unchanged": 391,
|
||||
"updated_case_rows_only": [],
|
||||
"new_rows": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
"commercial_data_statement": {
|
||||
"source": "User reply",
|
||||
"date": "2026-10-27",
|
||||
"text": "Ainda não há dados comerciais"
|
||||
},
|
||||
"assessment": "Compatibilidade técnica regional justifica prospecção adicional;procura recorrente,custos,capacidade disponível e sustentabilidade ainda não demonstrados.",
|
||||
"prospects": [
|
||||
{
|
||||
"entity": "HCB",
|
||||
"area": "Songo/Cahora Bassa",
|
||||
"known": "Necessidade metrológica documentada em2026",
|
||||
"status": "Cliente potencial inicial;procura actual/recorrente por confirmar",
|
||||
"quantity": null,
|
||||
"frequency": null,
|
||||
"price": null,
|
||||
"confirmed_order": null,
|
||||
"source": "Fundamento anterior preservado"
|
||||
},
|
||||
{
|
||||
"entity": "Vulcan Mozambique",
|
||||
"area": "Moatize",
|
||||
"known": "Mina,processamento e equipamentos de produção descritos pela própria empresa",
|
||||
"hypothesis": "Instrumentação de processo/manutenção pode beneficiar de apoio metrológico",
|
||||
"status": "Prospecto,não cliente confirmado",
|
||||
"quantity": null,
|
||||
"frequency": null,
|
||||
"price": null,
|
||||
"confirmed_order": null,
|
||||
"related_entity": "Nacala Logistics",
|
||||
"independent_purchase_confirmed": null,
|
||||
"source": "https://www.vulcaninternational.com/products-services/"
|
||||
},
|
||||
{
|
||||
"entity": "EDM",
|
||||
"area": "Tete/Moatize;unidade compradora por identificar",
|
||||
"known": "Plano2025,p68:calibração/teste a nível empresarial;activos deTete/Moatize referenciados",
|
||||
"hypothesis": "Verificar inventário regional e interesse em apoio associado",
|
||||
"status": "Prospecto;sem volume regional atribuído",
|
||||
"quantity": null,
|
||||
"frequency": null,
|
||||
"price": null,
|
||||
"confirmed_order": null,
|
||||
"source": "https://cdn.edm.co.mz/website/imprensa/Plano_Actividades_Orcamento_2025.pdf"
|
||||
},
|
||||
{
|
||||
"entity": "Nacala Logistics",
|
||||
"legal_buyer": null,
|
||||
"area": "Segmento Moatize",
|
||||
"known": "Operação ferroviária/manutenção;concessionárias indicam Vulcan como accionista",
|
||||
"hypothesis": "Verificar instrumentos de manutenção,localização e decisão de compra",
|
||||
"status": "Prospecto ligado àVulcan;diversificação independente não demonstrada",
|
||||
"quantity": null,
|
||||
"frequency": null,
|
||||
"price": null,
|
||||
"confirmed_order": null,
|
||||
"related_entity": "Vulcan Mozambique",
|
||||
"independent_purchase_confirmed": null,
|
||||
"source": "https://www.nacalalogistics.com/quem-somos/"
|
||||
}
|
||||
],
|
||||
"future_excluded_from_base": [
|
||||
{
|
||||
"entity": "Mphanda Nkuwa/GMNK",
|
||||
"status": "Projecto em desenvolvimento",
|
||||
"reason": "Necessidade e datas de operação futuras não demonstradas;sem receitas ou volume na base",
|
||||
"source": "https://www.gmnk.co.mz/en/about-us/project-description/"
|
||||
}
|
||||
],
|
||||
"buyer_data_needed": [
|
||||
"Entidade e centro de decisão/compra;relação com outros prospectos",
|
||||
"Inventário por família/modelo/gama/pontos/critério de aceitação",
|
||||
"Quantidade por janela e periodicidade efectiva de cada instrumento;sem anualizar por defeito",
|
||||
"Solução actual,prestador,prazo fora de serviço,custo total e necessidade ainda não satisfeita",
|
||||
"Interesse e condições de compra para lote/missão ou avença;horizonte de procura"
|
||||
],
|
||||
"partner_capacity_needed": [
|
||||
"Âmbito técnico e local permitido de execução por instrumento,com rastreabilidade",
|
||||
"Capacidade efectivamente disponível e prazo para cada janela;equipa e meios",
|
||||
"Preços por âmbito/lote,embalagem,transporte/seguro,custódia e responsabilidades",
|
||||
"Comprovar capacidade actual dos prestadores locais históricos;licença/CAE não é acreditação de calibração"
|
||||
],
|
||||
"frequency": {
|
||||
"confirmed_programs": null,
|
||||
"confirmed_annual_events": null,
|
||||
"rule": "Usar inventário e programa do proprietário;frequência por família/risco/uso e condições do serviço,não prazo do anúncio nem regra anual presumida."
|
||||
},
|
||||
"economics": {
|
||||
"analysis_unit": "Missão/lote comparável,com famílias e quantidades explícitas;período de análise comum",
|
||||
"mission_contribution": "Receita acordada da missão menos serviço laboratorial,apoio directo,transporte de ida/retorno,embalagem/seguro e outros custos incrementais da mesma missão.",
|
||||
"period_operating_balance": "Soma das contribuições de missões confirmadas menos custos fixos incrementais do mesmo período.",
|
||||
"double_count_prevention": "Transporte partilhado contado uma vez por missão;custos fixos não entram também na contribuição se subtraídos no período. Não somar volumes nacionais à carteira regional ou activos comuns duas vezes.",
|
||||
"sustainability_condition": "Cobertura operacional não basta:avaliar investimento,reposição,fundo de maneio e prazos de recebimento;testar concentração e perda de cliente antes de declarar serviço sustentável.",
|
||||
"numeric_inputs": {
|
||||
"missions": null,
|
||||
"instruments": null,
|
||||
"period": null,
|
||||
"prices": null,
|
||||
"laboratory_cost": null,
|
||||
"local_support_cost": null,
|
||||
"route_cost": null,
|
||||
"fixed_cost": null,
|
||||
"investment": null,
|
||||
"working_capital": null,
|
||||
"net_advantage": null,
|
||||
"break_even": null
|
||||
},
|
||||
"missing_is_not_zero": true,
|
||||
"scenarios_to_compare": [
|
||||
"Atendimento individual no Songo",
|
||||
"Missões agrupadas Songo–Tete/Moatize,apenas com janelas compatíveis",
|
||||
"Organização de apoio em Tete/Moatize com deslocação ao Songo;sem mudança canónica presumida"
|
||||
],
|
||||
"not_used_as_price": "Orçamento2025daEDM,capacidade de produção da mina,tarifas ferroviárias ou preços fictícios."
|
||||
},
|
||||
"source_register": [
|
||||
{
|
||||
"file": "vulcan.html",
|
||||
"url": "https://www.vulcaninternational.com/products-services/",
|
||||
"sha256": "44c92a7a405e7b84f51a6602a487ee4cbcb5e9d3ed42d6c9b2a47f55ba01800e",
|
||||
"bytes": 64512,
|
||||
"accessed": "2026-10-27",
|
||||
"use": "Private source copy;no automatic portal import/publication"
|
||||
},
|
||||
{
|
||||
"file": "nacala-company.html",
|
||||
"url": "https://www.nacalalogistics.com/quem-somos/",
|
||||
"sha256": "4c8c2f98a94f013ab463937c1ac343e26af2ea5fe82226764168b766dfea2c55",
|
||||
"bytes": 246823,
|
||||
"accessed": "2026-10-27",
|
||||
"use": "Private source copy;no automatic portal import/publication"
|
||||
},
|
||||
{
|
||||
"file": "nacala-operations.html",
|
||||
"url": "https://www.nacalalogistics.com/faq/",
|
||||
"sha256": "21f70dbbb8a9ea99f0ca3af728aa3b6a888e361994d78dae5292813437acdd9f",
|
||||
"bytes": 214596,
|
||||
"accessed": "2026-10-27",
|
||||
"use": "Private source copy;no automatic portal import/publication"
|
||||
},
|
||||
{
|
||||
"file": "edm-plan-2025.pdf",
|
||||
"url": "https://cdn.edm.co.mz/website/imprensa/Plano_Actividades_Orcamento_2025.pdf",
|
||||
"sha256": "8e25e3070062e6cad4a39449cb6d494263671506ff7bc71ce100787ae1bd80f1",
|
||||
"bytes": 25468134,
|
||||
"accessed": "2026-10-27",
|
||||
"use": "Private source copy;no automatic portal import/publication"
|
||||
},
|
||||
{
|
||||
"file": "gmnk-project.html",
|
||||
"url": "https://www.gmnk.co.mz/en/about-us/project-description/",
|
||||
"sha256": "705afaaba50074812aaf0884cd8757cfaba1e32dd83f90726d8755869b72d5f8",
|
||||
"bytes": 188060,
|
||||
"accessed": "2026-10-27",
|
||||
"use": "Private source copy;no automatic portal import/publication"
|
||||
}
|
||||
],
|
||||
"technical_delivery_independent": true,
|
||||
"no_publication_installation_or_external_messages": true,
|
||||
"accepted_proofs_reused": true,
|
||||
"L8_preserved": "14360748194f3658d91a7d7ae5615efd0fcbfbb7",
|
||||
"SGF_untouched": true,
|
||||
"evidence_directory": "outputs/proactive-regional-clients-20261027",
|
||||
"matrix_ids": [
|
||||
"RF-CLU-003",
|
||||
"MASTER-471012ab-0010",
|
||||
"MASTER-9dee08d0-0067",
|
||||
"MASTER-471012ab-0067"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"date": "2026-10-27",
|
||||
"status": "team_UI_delta_demonstrated_consolidated_candidate_not_installed",
|
||||
"branch": "codex/proactive-team-autonomy-qa-20261027",
|
||||
"runtime_commit": "51d536b7ba0d525323200418155459620ec07e41",
|
||||
"previous_candidate": "403c444a3e14e0ed83276ca318ad95083195708f",
|
||||
"accepted_technical_candidate": "1afab4a2a71f182f260e4d2555d79242261a4d2a",
|
||||
"main_checked": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"main_ancestor": true,
|
||||
"delta": "InvestmentComplements:authorised private preparation returns no public offers;public complements and access checks preserved",
|
||||
"new_tests": {
|
||||
"count": 2,
|
||||
"assertions": 18,
|
||||
"result": "passed",
|
||||
"scope": "private complement lookup,mixed public/private sources,unauthorised access",
|
||||
"transaction_rollback": true
|
||||
},
|
||||
"proof": {
|
||||
"record_id": 403,
|
||||
"dossier_id": "5bc28554-a2d1-4e60-9181-93ba0ecede59",
|
||||
"source_version": 4,
|
||||
"previous_context_revision": 1,
|
||||
"context_revision": 2,
|
||||
"same_dossier_continued": true,
|
||||
"private_source": true,
|
||||
"need_state": "hypothesis",
|
||||
"document_id": "19abe9ce-4c3f-4d53-b960-7ce0fc00435e",
|
||||
"resource_id": "d2c76068-3856-420c-8d2d-272684e92b70",
|
||||
"response_sha256": "b6cb6a7b7230a75bf5f4d56a7a2c1ac0dec7bb0fae0b85381eda56e53f0977c5",
|
||||
"scan": "clean",
|
||||
"scan_engine": "ClamAV",
|
||||
"download_matches_original": true,
|
||||
"response_reference_recovered_in_analysis_and_dossier": true,
|
||||
"deliberate_title_preserved": true,
|
||||
"old_source_snapshot_preserved": true,
|
||||
"new_UI_workflow": "normal login/MFA;create private draft;upload/recover original;associate response;revise idea;private dossier preview/confirm;edit again;continue same dossier;preview/confirm/reload",
|
||||
"no_service_or_SQL_writes_for_demonstration": true,
|
||||
"read_only_verification": true,
|
||||
"no_actual_team_training_session_claimed": true,
|
||||
"row_preservation": {
|
||||
"opportunities": {
|
||||
"old_rows_unchanged": 54,
|
||||
"new_rows": 1
|
||||
},
|
||||
"desk_cases": {
|
||||
"old_rows_unchanged": 19,
|
||||
"new_rows": 1
|
||||
},
|
||||
"documents": {
|
||||
"old_rows_unchanged": 63,
|
||||
"new_rows": 1
|
||||
},
|
||||
"opportunity_documents": {
|
||||
"old_rows_unchanged": 0,
|
||||
"new_rows": 1
|
||||
},
|
||||
"projects": {
|
||||
"old_rows_unchanged": 19,
|
||||
"new_rows": 0
|
||||
},
|
||||
"geo_locations": {
|
||||
"old_rows_unchanged": 1921,
|
||||
"new_rows": 0
|
||||
},
|
||||
"sectors": {
|
||||
"old_rows_unchanged": 12,
|
||||
"new_rows": 0
|
||||
},
|
||||
"value_chains": {
|
||||
"old_rows_unchanged": 0,
|
||||
"new_rows": 0
|
||||
},
|
||||
"organizations": {
|
||||
"old_rows_unchanged": 3,
|
||||
"new_rows": 0
|
||||
},
|
||||
"audit_events": {
|
||||
"old_rows_unchanged": 399,
|
||||
"new_rows": 10
|
||||
}
|
||||
},
|
||||
"Songo401_and_Gurue402_unchanged": true,
|
||||
"new_masters_or_grants": false,
|
||||
"publication_or_contact_external": false,
|
||||
"accepted_unaffected_suites_reused": true
|
||||
},
|
||||
"accepted_proofs_reused": [
|
||||
"14 API/139 assertions",
|
||||
"7 frontend report tests",
|
||||
"normal login/MFA and create/edit/history",
|
||||
"explicit publication/anonymous access controls",
|
||||
"Wayfinder --with-form",
|
||||
"TypeScript",
|
||||
"isolated QA frontend build"
|
||||
],
|
||||
"frontend_changed": false,
|
||||
"schema_or_configuration_changed": false,
|
||||
"no_new_roles_or_grants": true,
|
||||
"pilots_not_published_or_modified": [
|
||||
401,
|
||||
402
|
||||
],
|
||||
"commercial_outreach": false,
|
||||
"human_team_training_claimed": false,
|
||||
"L8_preserved": "14360748194f3658d91a7d7ae5615efd0fcbfbb7",
|
||||
"server_operations": false,
|
||||
"installation_conditions": [
|
||||
"fresh capacity/inodes measurement against build and backup requirements",
|
||||
"recheck current main",
|
||||
"fresh backup/restore",
|
||||
"keep active release until new ready",
|
||||
"verify served revision and installed delta only"
|
||||
],
|
||||
"private_outputs": "outputs/proactive-team-autonomy-20261027/"
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"date": "2026-10-27",
|
||||
"status": "exercise_prepared_awaiting_real_team_use",
|
||||
"installed_reference_from_accepted_receipt": "9fda6d6e12832a3cf25e7314f1f895dd430238c5",
|
||||
"installation_receipt": "docs/investmoz/unification/sequential-delivery-installed-20261027.json",
|
||||
"guide": "docs/investmoz/unification/traceability-and-manual.md#27102026--avaliação-de-utilização-pela-equipa-sem-codex",
|
||||
"evaluation_scope": [
|
||||
"prepare a private work analysis using an existing authorised source",
|
||||
"record evidence with source,period,coverage and distinction between fact and hypothesis",
|
||||
"structure a complementary idea with clients/payer,conditions and unknowns",
|
||||
"save and recover through the interface",
|
||||
"preview/confirm and recover in the same dossier",
|
||||
"revise a pending point and recover the new version without duplication"
|
||||
],
|
||||
"existing_guide_reused": true,
|
||||
"technical_proofs_reused": true,
|
||||
"new_technical_tests": 0,
|
||||
"new_installations": 0,
|
||||
"active_application_writes": 0,
|
||||
"private_pilots_modified": false,
|
||||
"team_messages_sent": 0,
|
||||
"team_execution_observed": false,
|
||||
"participants": [],
|
||||
"observed_results": [],
|
||||
"Codex_executes_team_exercise": false,
|
||||
"existing_authorised_accounts_only": true,
|
||||
"new_permissions_or_roles": false,
|
||||
"not_a_new_approval_gate": true,
|
||||
"results_to_return": [
|
||||
"date and operational profile",
|
||||
"internal analysis/dossier references in authorised channel",
|
||||
"steps achieved and guide/human help used",
|
||||
"step/field and concrete difficulty",
|
||||
"exact message or behaviour and expected result"
|
||||
],
|
||||
"resume_when": "Real team observations arrive;address only reported usability/access/save-recovery obstacles",
|
||||
"commercial_validation_separate": true,
|
||||
"Songo_and_Gurue": "private;external commercial evidence pending",
|
||||
"L8": "partial;PEC and own credits separate"
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,719 @@
|
||||
{
|
||||
"date": "2026-10-27T10:51:18.002627+00:00",
|
||||
"status": "both_deliveries_installed_in_requested_order",
|
||||
"order": [
|
||||
"l8",
|
||||
"proactive"
|
||||
],
|
||||
"stages": {
|
||||
"l8": {
|
||||
"candidate": "c85e772d2fd2be5182eb4d768ddd34d43962bf59",
|
||||
"previous": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"installed": {
|
||||
"status": "installed",
|
||||
"commit": "c85e772d2fd2be5182eb4d768ddd34d43962bf59",
|
||||
"release": "/var/www/investmoz-homologacao/releases/c85e772d2fd2be5182eb4d768ddd34d43962bf59-ae7401aa",
|
||||
"previous_release": "/var/www/investmoz-homologacao/releases/f8d57bddf96b4610604a013fcc5bdd703c7dc6d5-7a31e8ac",
|
||||
"database_migrations": 0,
|
||||
"content_imports": 0
|
||||
},
|
||||
"served": {
|
||||
"commit": "c85e772d2fd2be5182eb4d768ddd34d43962bf59",
|
||||
"branch": "main",
|
||||
"built_at": "2026-10-27T10:32:26.854949+00:00",
|
||||
"manifest_sha256": "f27852b26d53b46f6927ee46c13370db17a4bec1623655552fd8fdca3589005a"
|
||||
},
|
||||
"backup": {
|
||||
"stage": "/var/backups/investmoz-sequential-20261027/l8/backup",
|
||||
"created_at": "2026-10-27T10:25:59Z",
|
||||
"target": {
|
||||
"database": "teste_investidor",
|
||||
"port": 5432
|
||||
},
|
||||
"tables": 174,
|
||||
"files_verified": 369,
|
||||
"dump_sha256": "11bc7c8f25edc861b18785a9714845384cf29a5da92f58f55ff53f6913e69d42",
|
||||
"files_sha256": "52ffe40bcf943ce580047b55c34b60d3ba876d81dd4bc3ff4fbe1ec97a9c6f56",
|
||||
"restore_verified": false
|
||||
},
|
||||
"restore": {
|
||||
"restore_verified": true,
|
||||
"tables_verified": 174,
|
||||
"container_network": "none",
|
||||
"database": "irpc_l8_first_restore_20261027",
|
||||
"port": 55441,
|
||||
"source_dump_sha256": "11bc7c8f25edc861b18785a9714845384cf29a5da92f58f55ff53f6913e69d42",
|
||||
"active_database_writes": 0
|
||||
},
|
||||
"capacity_after_backup": {
|
||||
"at": "2026-10-27T10:28:35.403687+00:00",
|
||||
"baseline": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"capacity_after_backup_satisfied": true,
|
||||
"volumes": [
|
||||
{
|
||||
"path": "/var/www/investmoz-homologacao/releases",
|
||||
"free_bytes": 98153496576,
|
||||
"free_inodes": 23860325
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/investmoz-deploy",
|
||||
"free_bytes": 98153496576,
|
||||
"free_inodes": 23860325
|
||||
},
|
||||
{
|
||||
"path": "/var/backups",
|
||||
"free_bytes": 98153496576,
|
||||
"free_inodes": 23860325
|
||||
},
|
||||
{
|
||||
"path": "/tmp",
|
||||
"free_bytes": 98153496576,
|
||||
"free_inodes": 23860325
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/docker",
|
||||
"free_bytes": 98153496576,
|
||||
"free_inodes": 23860325
|
||||
}
|
||||
],
|
||||
"backup_age_seconds": 156.403651,
|
||||
"backup_dump_sha256": "11bc7c8f25edc861b18785a9714845384cf29a5da92f58f55ff53f6913e69d42",
|
||||
"restore_verified": true,
|
||||
"tables_verified": 174,
|
||||
"files_verified": 369,
|
||||
"backup_paths": {
|
||||
"dump": "/var/backups/investmoz-sequential-20261027/l8/backup/database.dump",
|
||||
"files": "/var/backups/investmoz-sequential-20261027/l8/backup/files-before.tar.gz"
|
||||
},
|
||||
"active_writes": 0
|
||||
},
|
||||
"source": {
|
||||
"phase": "after",
|
||||
"installed": "c85e772d2fd2be5182eb4d768ddd34d43962bf59",
|
||||
"files_verified": 996,
|
||||
"source_matches_Git": true,
|
||||
"active_writes": 0
|
||||
},
|
||||
"schema_permissions": {
|
||||
"schema_sha256": "5045b3e51d2185377aa3d9ac7fa07a44fad3ec620cdfa83ffe31c8884ee1601d",
|
||||
"roles_grants_sha256": "1530c33cb016e67bfdc64891ddfce7f185b13b56b2cd87c012871a685e118109",
|
||||
"filesystem_permissions": {
|
||||
".env": {
|
||||
"mode": 416,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
},
|
||||
"storage": {
|
||||
"mode": 1533,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
},
|
||||
"storage/app": {
|
||||
"mode": 1533,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
},
|
||||
"bootstrap/cache": {
|
||||
"mode": 1528,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
}
|
||||
},
|
||||
"comparison_identity": "postgres;catalogue read only;no passwords collected",
|
||||
"unchanged": true
|
||||
},
|
||||
"preservation": {
|
||||
"checked_at": "2026-10-27T10:34:53.148104+00:00",
|
||||
"installed": "c85e772d2fd2be5182eb4d768ddd34d43962bf59",
|
||||
"business_tables_unchanged": 172,
|
||||
"total_tables": 174,
|
||||
"operational_tables_to_reconcile": {
|
||||
"cache": {
|
||||
"before": {
|
||||
"rows": 106,
|
||||
"checksum": "6c05e12d73079effd52f3add83104de2"
|
||||
},
|
||||
"after": {
|
||||
"rows": 106,
|
||||
"checksum": "a9c2d7df6ecc8cabba35d5c6f1d019c5"
|
||||
}
|
||||
},
|
||||
"sessions": {
|
||||
"before": {
|
||||
"rows": 11,
|
||||
"checksum": "b83d84b3894b8fc6ef42b0b8fd937304"
|
||||
},
|
||||
"after": {
|
||||
"rows": 12,
|
||||
"checksum": "fea9aecf735aa394f40e9a4b6a55e27f"
|
||||
}
|
||||
}
|
||||
},
|
||||
"persistent_files_unchanged": 369,
|
||||
"original_configuration_preserved": true,
|
||||
"synthetic_QA_storage_not_served": true,
|
||||
"QA_storage_saved_outside_active": "/var/lib/investmoz-deploy/qa-runtime/c85e772d2fd2be5182eb4d768ddd34d43962bf59-ae7401aa",
|
||||
"fixture_or_content_imports": 0,
|
||||
"migrations": 0,
|
||||
"comparison_identity": "postgres;UTC;consistent before snapshot and after read-only transaction",
|
||||
"active_database_writes": 0
|
||||
},
|
||||
"operational_delta": {
|
||||
"status": "operational_delta_reconciled",
|
||||
"comparison_identity": "postgres before/after;isolated restored baseline;no RLS visibility inference",
|
||||
"cache": "queue:restart;requestthrottle;identical home-sector cached value with refreshed expiry(HomeController remember10min);no deletedcache",
|
||||
"sessions": "anonymous sessions from delivery user-agent or exactUA/time correlated with nginx public request;deleted sessions individually expired beyond configured lifetime,normal database session garbage collection(config/session lottery2/100)",
|
||||
"delta": {
|
||||
"cache": {
|
||||
"before_rows": 106,
|
||||
"after_rows": 106,
|
||||
"changes": [
|
||||
{
|
||||
"key_sha256": "7f7dd83f47f5bf404d55e6e9f1367948721579970b195680645e356031a070ff",
|
||||
"kind": "updated",
|
||||
"fields": [
|
||||
"value",
|
||||
"expiration"
|
||||
],
|
||||
"key_pattern": "investemoz-cache-illuminate:queue:restart",
|
||||
"is_queue_restart_key": true,
|
||||
"expiration_unchanged": false,
|
||||
"throttle_timer_pair": false,
|
||||
"same_value_home_cache_expiry_refresh": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"sessions": {
|
||||
"before_rows": 11,
|
||||
"after_rows": 15,
|
||||
"changes": [
|
||||
{
|
||||
"key_sha256": "7a0b0d7c40ef99d4c033c9df695a5cd69d6433f068463fdf9f8baff6835453f6",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
},
|
||||
{
|
||||
"key_sha256": "9f06bc9fb6ef8d45fe1c1093b4e54b59ee080463861b8051271597b0ec5e45a4",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
},
|
||||
{
|
||||
"key_sha256": "e66f917f9d71192fe17cf2c7c26046afa6bff0db292d0c232a5b59629be030a3",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
},
|
||||
{
|
||||
"key_sha256": "a84b009ac5f5358a0452f4a40968a4826e34ced257930b6ecf08a0289aa6684f",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"business_tables_to_confirm_separately": 172,
|
||||
"active_data_writes_by_comparison": 0,
|
||||
"restore_network": "none"
|
||||
},
|
||||
"public_delta": {
|
||||
"stage": "l8",
|
||||
"served_revision": {
|
||||
"commit": "c85e772d2fd2be5182eb4d768ddd34d43962bf59",
|
||||
"branch": "main",
|
||||
"built_at": "2026-10-27T10:32:26.854949+00:00",
|
||||
"manifest_sha256": "f27852b26d53b46f6927ee46c13370db17a4bec1623655552fd8fdca3589005a"
|
||||
},
|
||||
"manifest_hash_matches": true,
|
||||
"compiled_delta_markers": {
|
||||
"IRPC-annual-settlement/1": [
|
||||
"assets/project-dossier-BNt4O6Rz.js"
|
||||
],
|
||||
"Preparar saldo anual L8": [
|
||||
"assets/services-BvFvahdE.js"
|
||||
],
|
||||
"Calcular e guardar saldo anual L8": [
|
||||
"assets/services-BvFvahdE.js"
|
||||
],
|
||||
"Saldo anual simulado": [
|
||||
"assets/project-dossier-BNt4O6Rz.js"
|
||||
],
|
||||
"PEC e créditos separados": [
|
||||
"assets/project-dossier-BNt4O6Rz.js"
|
||||
]
|
||||
},
|
||||
"assets": [
|
||||
{
|
||||
"file": "assets/simulation-form-zFZ4YNrB.js",
|
||||
"status": 200,
|
||||
"sha256": "338068b86cce1c3215ee71b1328a6cb2f754b903ed78ff1886f8554df506d2d6"
|
||||
},
|
||||
{
|
||||
"file": "assets/services-BvFvahdE.js",
|
||||
"status": 200,
|
||||
"sha256": "97615f0d113746ee5ac1550a1e59c567dd152ef5ddac68f133bd2cee9e9c16d1"
|
||||
},
|
||||
{
|
||||
"file": "assets/project-dossier-BNt4O6Rz.js",
|
||||
"status": 200,
|
||||
"sha256": "8cf6a6678c5c9aed0d7b996147bc2fde35d20f86c73ec7bd894df2ae11aae75c"
|
||||
},
|
||||
{
|
||||
"file": "assets/project-dossier-document-Cj4QX7oF.js",
|
||||
"status": 200,
|
||||
"sha256": "302ec6831893f2ef4c09a90273b458c49a6ff281adb01c4594a166a90efe53e2"
|
||||
}
|
||||
],
|
||||
"simulator_status": 200,
|
||||
"served_component": "portal/services",
|
||||
"private_operations": 0,
|
||||
"QA_fixture_imports": 0,
|
||||
"accepted_QA_proofs_reused": true,
|
||||
"method": "Read-only served revision/manifest/compiled delta;no synthetic active records or publication"
|
||||
},
|
||||
"backup_restore_verified": true
|
||||
},
|
||||
"proactive": {
|
||||
"candidate": "9fda6d6e12832a3cf25e7314f1f895dd430238c5",
|
||||
"previous": "c85e772d2fd2be5182eb4d768ddd34d43962bf59",
|
||||
"installed": {
|
||||
"status": "installed",
|
||||
"commit": "9fda6d6e12832a3cf25e7314f1f895dd430238c5",
|
||||
"release": "/var/www/investmoz-homologacao/releases/9fda6d6e12832a3cf25e7314f1f895dd430238c5-88fc859c",
|
||||
"previous_release": "/var/www/investmoz-homologacao/releases/c85e772d2fd2be5182eb4d768ddd34d43962bf59-ae7401aa",
|
||||
"database_migrations": 0,
|
||||
"content_imports": 0
|
||||
},
|
||||
"served": {
|
||||
"commit": "9fda6d6e12832a3cf25e7314f1f895dd430238c5",
|
||||
"branch": "main",
|
||||
"built_at": "2026-10-27T10:50:00.471464+00:00",
|
||||
"manifest_sha256": "40de38cbf74b475f73de825bfd16af6fabe339faad4817e2857fd9ae36ec7cc0"
|
||||
},
|
||||
"backup": {
|
||||
"stage": "/var/backups/investmoz-sequential-20261027/proactive/backup",
|
||||
"created_at": "2026-10-27T10:36:28Z",
|
||||
"target": {
|
||||
"database": "teste_investidor",
|
||||
"port": 5432
|
||||
},
|
||||
"tables": 174,
|
||||
"files_verified": 369,
|
||||
"dump_sha256": "45107e48e18ab2b9a78af08374fe3bfa0af216f34433c10fc81f264400e331ce",
|
||||
"files_sha256": "f7196314f915e75975a9e580a69ddc4dffae64597ae05e9ae59cfbcbb0b47731",
|
||||
"restore_verified": false
|
||||
},
|
||||
"restore": {
|
||||
"restore_verified": true,
|
||||
"tables_verified": 174,
|
||||
"container_network": "none",
|
||||
"database": "irpc_l8_first_restore_20261027",
|
||||
"port": 55441,
|
||||
"source_dump_sha256": "45107e48e18ab2b9a78af08374fe3bfa0af216f34433c10fc81f264400e331ce",
|
||||
"active_database_writes": 0
|
||||
},
|
||||
"capacity_after_backup": {
|
||||
"at": "2026-10-27T10:46:06.120042+00:00",
|
||||
"baseline": "c85e772d2fd2be5182eb4d768ddd34d43962bf59",
|
||||
"capacity_after_backup_satisfied": true,
|
||||
"volumes": [
|
||||
{
|
||||
"path": "/var/www/investmoz-homologacao/releases",
|
||||
"free_bytes": 95851429888,
|
||||
"free_inodes": 23794207
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/investmoz-deploy",
|
||||
"free_bytes": 95851429888,
|
||||
"free_inodes": 23794207
|
||||
},
|
||||
{
|
||||
"path": "/var/backups",
|
||||
"free_bytes": 95851429888,
|
||||
"free_inodes": 23794207
|
||||
},
|
||||
{
|
||||
"path": "/tmp",
|
||||
"free_bytes": 95851429888,
|
||||
"free_inodes": 23794207
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/docker",
|
||||
"free_bytes": 95851429888,
|
||||
"free_inodes": 23794207
|
||||
}
|
||||
],
|
||||
"backup_age_seconds": 578.120001,
|
||||
"backup_dump_sha256": "45107e48e18ab2b9a78af08374fe3bfa0af216f34433c10fc81f264400e331ce",
|
||||
"restore_verified": true,
|
||||
"tables_verified": 174,
|
||||
"files_verified": 369,
|
||||
"backup_paths": {
|
||||
"dump": "/var/backups/investmoz-sequential-20261027/proactive/backup/database.dump",
|
||||
"files": "/var/backups/investmoz-sequential-20261027/proactive/backup/files-before.tar.gz"
|
||||
},
|
||||
"active_writes": 0
|
||||
},
|
||||
"source": {
|
||||
"phase": "after",
|
||||
"installed": "9fda6d6e12832a3cf25e7314f1f895dd430238c5",
|
||||
"files_verified": 1000,
|
||||
"source_matches_Git": true,
|
||||
"active_writes": 0
|
||||
},
|
||||
"schema_permissions": {
|
||||
"schema_sha256": "5045b3e51d2185377aa3d9ac7fa07a44fad3ec620cdfa83ffe31c8884ee1601d",
|
||||
"roles_grants_sha256": "1530c33cb016e67bfdc64891ddfce7f185b13b56b2cd87c012871a685e118109",
|
||||
"filesystem_permissions": {
|
||||
".env": {
|
||||
"mode": 416,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
},
|
||||
"storage": {
|
||||
"mode": 1533,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
},
|
||||
"storage/app": {
|
||||
"mode": 1533,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
},
|
||||
"bootstrap/cache": {
|
||||
"mode": 1528,
|
||||
"uid": 1001,
|
||||
"gid": 33
|
||||
}
|
||||
},
|
||||
"comparison_identity": "postgres;catalogue read only;no passwords collected",
|
||||
"unchanged": true
|
||||
},
|
||||
"preservation": {
|
||||
"checked_at": "2026-10-27T10:50:49.400700+00:00",
|
||||
"installed": "9fda6d6e12832a3cf25e7314f1f895dd430238c5",
|
||||
"business_tables_unchanged": 172,
|
||||
"total_tables": 174,
|
||||
"operational_tables_to_reconcile": {
|
||||
"cache": {
|
||||
"before": {
|
||||
"rows": 106,
|
||||
"checksum": "a9c2d7df6ecc8cabba35d5c6f1d019c5"
|
||||
},
|
||||
"after": {
|
||||
"rows": 106,
|
||||
"checksum": "db78f82003db53db664667b8e6f46088"
|
||||
}
|
||||
},
|
||||
"sessions": {
|
||||
"before": {
|
||||
"rows": 15,
|
||||
"checksum": "4df23659bf65acacc88e1d84d095a243"
|
||||
},
|
||||
"after": {
|
||||
"rows": 20,
|
||||
"checksum": "64d48443c5027a2fc08615f7528126b5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"persistent_files_unchanged": 369,
|
||||
"original_configuration_preserved": true,
|
||||
"synthetic_QA_storage_not_served": true,
|
||||
"QA_storage_saved_outside_active": "/var/lib/investmoz-deploy/qa-runtime/9fda6d6e12832a3cf25e7314f1f895dd430238c5-88fc859c",
|
||||
"fixture_or_content_imports": 0,
|
||||
"migrations": 0,
|
||||
"comparison_identity": "postgres;UTC;consistent before snapshot and after read-only transaction",
|
||||
"active_database_writes": 0
|
||||
},
|
||||
"operational_delta": {
|
||||
"status": "operational_delta_reconciled",
|
||||
"comparison_identity": "postgres before/after;isolated restored baseline;no RLS visibility inference",
|
||||
"cache": "queue:restart;requestthrottle;identical home-sector cached value with refreshed expiry(HomeController remember10min);no deletedcache",
|
||||
"sessions": "anonymous sessions from delivery user-agent or exactUA/time correlated with nginx public request;deleted sessions individually expired beyond configured lifetime,normal database session garbage collection(config/session lottery2/100)",
|
||||
"delta": {
|
||||
"cache": {
|
||||
"before_rows": 106,
|
||||
"after_rows": 106,
|
||||
"changes": [
|
||||
{
|
||||
"key_sha256": "7f7dd83f47f5bf404d55e6e9f1367948721579970b195680645e356031a070ff",
|
||||
"kind": "updated",
|
||||
"fields": [
|
||||
"value",
|
||||
"expiration"
|
||||
],
|
||||
"key_pattern": "investemoz-cache-illuminate:queue:restart",
|
||||
"is_queue_restart_key": true,
|
||||
"expiration_unchanged": false,
|
||||
"throttle_timer_pair": false,
|
||||
"same_value_home_cache_expiry_refresh": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"sessions": {
|
||||
"before_rows": 15,
|
||||
"after_rows": 20,
|
||||
"changes": [
|
||||
{
|
||||
"key_sha256": "f78ee9e6f589e1bbda4730d4e71a90c9ad082cc25776c415b6cc815ce4b4d491",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
},
|
||||
{
|
||||
"key_sha256": "7eb58435f5d60610be81945c0da4331a1dbfda680f7da3f107dbbeb6b60c39df",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
},
|
||||
{
|
||||
"key_sha256": "1d5026f13ace3894011db54d801f72cd76f9b138d54fe2f7b89f579743282db6",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
},
|
||||
{
|
||||
"key_sha256": "56820cc8560f13a2c0962a973bd05624712648c2beffd2058dfbae6c9103c7fa",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
},
|
||||
{
|
||||
"key_sha256": "a91337e37e71b520dd6d621b0ef7bbf68a9a20d099198ecd8edfdc365a9f52f1",
|
||||
"kind": "added",
|
||||
"fields": [
|
||||
"id",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"payload",
|
||||
"last_activity"
|
||||
],
|
||||
"anonymous_user": true,
|
||||
"delivery_user_agent": true,
|
||||
"expired_before_comparison": false,
|
||||
"session_lifetime_minutes": 120,
|
||||
"anonymous_public_request_logged": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"business_tables_to_confirm_separately": 172,
|
||||
"active_data_writes_by_comparison": 0,
|
||||
"restore_network": "none"
|
||||
},
|
||||
"public_delta": {
|
||||
"stage": "proactive",
|
||||
"served_revision": {
|
||||
"commit": "9fda6d6e12832a3cf25e7314f1f895dd430238c5",
|
||||
"branch": "main",
|
||||
"built_at": "2026-10-27T10:50:00.471464+00:00",
|
||||
"manifest_sha256": "40de38cbf74b475f73de825bfd16af6fabe339faad4817e2857fd9ae36ec7cc0"
|
||||
},
|
||||
"manifest_hash_matches": true,
|
||||
"compiled_delta_markers": {
|
||||
"IRPC-annual-settlement/1": [
|
||||
"assets/project-dossier-DFH3NDYe.js"
|
||||
],
|
||||
"Preparar saldo anual L8": [
|
||||
"assets/services-CV6TWKfT.js"
|
||||
],
|
||||
"Calcular e guardar saldo anual L8": [
|
||||
"assets/services-CV6TWKfT.js"
|
||||
],
|
||||
"Saldo anual simulado": [
|
||||
"assets/project-dossier-DFH3NDYe.js"
|
||||
],
|
||||
"PEC e créditos separados": [
|
||||
"assets/project-dossier-DFH3NDYe.js"
|
||||
],
|
||||
"Território e sector": [
|
||||
"assets/proactive-investment-CPkgrUFY.js"
|
||||
],
|
||||
"Preparar análise e ideia": [
|
||||
"assets/proactive-investment-CPkgrUFY.js"
|
||||
],
|
||||
"Hipótese analítica": [
|
||||
"assets/project-dossier-DFH3NDYe.js",
|
||||
"assets/proactive-investment-CPkgrUFY.js"
|
||||
],
|
||||
"Documento existente associado": [
|
||||
"assets/proactive-investment-CPkgrUFY.js"
|
||||
],
|
||||
"Origem privada autorizada deste dossier": [
|
||||
"assets/proactive-investment-CPkgrUFY.js"
|
||||
]
|
||||
},
|
||||
"assets": [
|
||||
{
|
||||
"file": "assets/project-dossier-DFH3NDYe.js",
|
||||
"status": 200,
|
||||
"sha256": "62f4e47f6efbb7916663604450ee427401080fad6f9332be2cd0dc017866b85a"
|
||||
},
|
||||
{
|
||||
"file": "assets/project-dossier-document-CgBtS4qw.js",
|
||||
"status": 200,
|
||||
"sha256": "fb9aa7e305891719ae49cf8bbcee05b3114c05c8ee1df20238964fddb56721dd"
|
||||
},
|
||||
{
|
||||
"file": "assets/catalogue-DRXXB4Y7.js",
|
||||
"status": 200,
|
||||
"sha256": "66a2ae7c819f1ac36ffd37e8456c3cfd2537c820845b20eddb4dd7bfaf4a32a2"
|
||||
},
|
||||
{
|
||||
"file": "assets/services-CV6TWKfT.js",
|
||||
"status": 200,
|
||||
"sha256": "656da0adacd9141fcd9b1e82ab9959a62ea381a3815e183c5535801c95d92dff"
|
||||
},
|
||||
{
|
||||
"file": "assets/simulation-form-zFZ4YNrB.js",
|
||||
"status": 200,
|
||||
"sha256": "338068b86cce1c3215ee71b1328a6cb2f754b903ed78ff1886f8554df506d2d6"
|
||||
},
|
||||
{
|
||||
"file": "assets/proactive-investment-CPkgrUFY.js",
|
||||
"status": 200,
|
||||
"sha256": "288cd1005a05c82241a1ddd8c5bb446e297ead7b7605060cec80d268726522ac"
|
||||
},
|
||||
{
|
||||
"file": "assets/opportunity-draft-Da2FBHoN.js",
|
||||
"status": 200,
|
||||
"sha256": "ba50f61a39693ebebbe30ba1937d45c92b80f81ab9a98418ef75662f893cdfb2"
|
||||
},
|
||||
{
|
||||
"file": "assets/detail-BfSgTC5d.js",
|
||||
"status": 200,
|
||||
"sha256": "234657a2e5ebad7985d78ea49c5536c31e4aac9a143a02e7682d898e47cee530"
|
||||
},
|
||||
{
|
||||
"file": "assets/show-CJYhqIE4.js",
|
||||
"status": 200,
|
||||
"sha256": "6579df14a154c98235330f550e13bee20e74f19517cc1d166ae26322f56c74f9"
|
||||
}
|
||||
],
|
||||
"simulator_status": 200,
|
||||
"served_component": "portal/services",
|
||||
"public_catalogue_delta": {
|
||||
"ideas": {
|
||||
"status": 200,
|
||||
"component": "investment/catalogue"
|
||||
},
|
||||
"needs": {
|
||||
"status": 200,
|
||||
"component": "investment/catalogue"
|
||||
},
|
||||
"exists": {
|
||||
"status": 200,
|
||||
"component": "investment/catalogue"
|
||||
}
|
||||
},
|
||||
"private_operations": 0,
|
||||
"QA_fixture_imports": 0,
|
||||
"accepted_QA_proofs_reused": true,
|
||||
"method": "Read-only served revision/manifest/compiled delta;no synthetic active records or publication"
|
||||
},
|
||||
"backup_restore_verified": true
|
||||
}
|
||||
},
|
||||
"main": "9fda6d6e12832a3cf25e7314f1f895dd430238c5",
|
||||
"final_served_revision": "9fda6d6e12832a3cf25e7314f1f895dd430238c5",
|
||||
"private_pilots_preserved_no_publication": true,
|
||||
"fixtures_not_imported_into_active_database": true,
|
||||
"QA_runtime_storage_outside_active_release": true,
|
||||
"active_schema_migrations": 0,
|
||||
"new_grants": false,
|
||||
"SGF_TEMPO": "untouched",
|
||||
"accepted_business_proofs": "reused;post-install checks limited to deltas;existing installer automated checks retained",
|
||||
"prior_capacity_GiB": 91.60694122314453,
|
||||
"second_delivery_retry": {
|
||||
"initial_candidate": "56c0c6a7caa65a4cac54e17f9d455739f8eb6198",
|
||||
"initial_candidate_activated": false,
|
||||
"active_L8_preserved": true,
|
||||
"reason": "One frontend test depended on ignored local outputs/proactive-investment-20261027/recovered-context.json",
|
||||
"correction": "9fda6d6e12832a3cf25e7314f1f895dd430238c5 changes only the test and a minimal synthetic public API projection;no profile,pilot,credentials or live records",
|
||||
"application_runtime_identical_to_56c0c6a7": true,
|
||||
"directed_portability_test": "passed;one test;no skipped test",
|
||||
"existing_installer_guards_retained": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"date": "2026-10-27",
|
||||
"status": "authorised_prepared_not_installed_SSH_session_unavailable",
|
||||
"authorization": "User explicitly authorised both deliveries,first L8 then proactive,no new authorisation required",
|
||||
"stage1": {
|
||||
"candidate": "c85e772d2fd2be5182eb4d768ddd34d43962bf59",
|
||||
"includes": "14360748194f3658d91a7d7ae5615efd0fcbfbb7",
|
||||
"runtime": "11a6cee981f0a425b0fceefb6ed85485bb298245",
|
||||
"capacity_notes_reconciled": "c85e772d changes documentation only;historical suspension superseded by current explicit authorisation;capacity must be freshly measured",
|
||||
"runtime_delta_files": [
|
||||
"resources/js/components/simulation-form.tsx",
|
||||
"resources/js/components/simulation-irpc-annual.tsx",
|
||||
"resources/js/lib/irpc-annual-settlement.ts",
|
||||
"resources/js/lib/project-dossier-report.ts",
|
||||
"resources/js/lib/project-dossier.ts"
|
||||
]
|
||||
},
|
||||
"stage2": {
|
||||
"runtime_merge_commit": "74f7f93a750cfb88f9816512ee7add6473a3e34f",
|
||||
"branch": "codex/sequential-delivery-20261027",
|
||||
"includes_proactive_candidate": "0ff402a11dbf8d41c499dccd39184fdc20c833f4",
|
||||
"L8_is_ancestor": true,
|
||||
"shared_report_conflict": "Both imports and both row providers retained",
|
||||
"L8_other_runtime_files_byte_identical": [
|
||||
"resources/js/components/simulation-form.tsx",
|
||||
"resources/js/components/simulation-irpc-annual.tsx",
|
||||
"resources/js/lib/irpc-annual-settlement.ts",
|
||||
"resources/js/lib/project-dossier-report.ts"
|
||||
],
|
||||
"proactive_other_runtime_files_byte_identical": true
|
||||
},
|
||||
"local_verification": {
|
||||
"TypeScript": "passed",
|
||||
"isolated_build": "passed",
|
||||
"shared_report_delta": {
|
||||
"scope": "Only shared dossier report merge integration;accepted business-rule suites reused",
|
||||
"annual_rows": 6,
|
||||
"proactive_rows": 10,
|
||||
"annual_report_preserved": true,
|
||||
"private_idea_report_preserved": true,
|
||||
"inputs_unchanged": true,
|
||||
"no_cross_inference": true,
|
||||
"no_QA_data_written_or_published": true
|
||||
},
|
||||
"accepted_suites": "reused,not repeated",
|
||||
"no_database_or_fixture_operations": true
|
||||
},
|
||||
"server": {
|
||||
"SSH_bridge_state": "closed",
|
||||
"key_authentication": "denied with registered host key verified",
|
||||
"fresh_capacity": "not measured in this passage",
|
||||
"fresh_backup": false,
|
||||
"fresh_restore": false,
|
||||
"installation": false,
|
||||
"public_served_revision_read": {
|
||||
"checked_at_UTC": "2026-10-27T10:14:16.489135+00:00",
|
||||
"http_status": 200,
|
||||
"revision": {
|
||||
"commit": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"branch": "main",
|
||||
"built_at": "2026-10-26T14:26:51.629481+00:00",
|
||||
"manifest_sha256": "367be71b25b56a83571d610e211ea11beae2af87989d62ef6cc7b9c54eabf580"
|
||||
},
|
||||
"method": "Public revision read only;no SSH,backup or installation executed"
|
||||
}
|
||||
},
|
||||
"main_at_preparation": "f8d57bddf96b4610604a013fcc5bdd703c7dc6d5",
|
||||
"main_push_executed": false,
|
||||
"required_execution_controls": [
|
||||
"Use existing authenticated local SSH session;do not request authorisation again",
|
||||
"Fresh capacity/inodes,backup and restore per existing procedure;keep active release until candidate ready",
|
||||
"Refresh preparation candidate/base/hashes per stage;do not reuse old dated receipts",
|
||||
"Stage1 only,L8;verify actual served revision and onlyL8 delta",
|
||||
"Only after stage1 confirmed,stage2;fresh guards and verify proactive delta and L8 preservation",
|
||||
"Exclude QA fixtures/outputs/test data from deployment inputs;no seed/import;preserve private pilots",
|
||||
"Return actual installed/served hashes and fresh receipt paths;do not label this local preparation as installation"
|
||||
],
|
||||
"actual_remote_changes": 0
|
||||
}
|
||||
@@ -2523,8 +2523,8 @@ As estimativas são **horas de trabalho técnico**, não calendário nem mediç
|
||||
| L4 — ISPC: elegibilidade e apuramento | Campos de enquadramento e motor genérico | Regime/actividade/volume elegível, opções/exclusões, escalões/taxas aplicáveis, mínimo, trimestre e retenções específicas; comparação só entre regimes admissíveis | Vendas por actividade, custos, NUIT, natureza jurídica e residência confirmada | Lei9/2025 e regulamentação/período; distinguir receita anual, trimestre e excesso | 40–64 h |
|
||||
| L5 — retenções IRPC e guias | Documentos de compras/vendas e guia M/39 como exemplar | Rendimento pago/recebido, entidade que retém, residente/não residente/EP, evento temporal, excepções e casos digitais/e-money; guia e comprovativo ligados à operação | Contrapartes, facturas, pagamentos, período, moeda, oportunidade | Artigos aplicáveis por rendimento, taxa/convenção se invocada; corrigir remissões do exemplar. Sem submissão electrónica AT presumida | 32–56 h |
|
||||
| L6 — IRPC anual: regime normal | Disponível5aaf1a56:percurso normal demonstrado atécolecta,períodos/moedas e preparação parcialM20/M22 | Operacional no âmbito demonstrado por decisãoTempo26/10;limitações explícitas;5grupos código+5documentais preservados;sem conclusão integral | Plano financeiro,dados comuns,activos/livros e histórico;retenções/pagamentos/créditos anuaisL8 | Pendências bloqueiam só os casos dependentes;L7/L8 próprios | Estimativa inicial48–80h;saldo não reestimado |
|
||||
| L7 — IRPC: tratamentos específicos | 632dc069 instalado;cumulações14 prontas emQA,sem instalação | CIRPC12+CBF16 qualificados e61(4) separado;incompatibilidadeCBF4/13 e lacunas explícitas;L7parcial | Activos/períodos/saldos/benefícios reutilizados;diferença25 uma vez e15 já nos75;taxa16% só sobre base elegível | Outras combinações/excepções e restantes tratamentos dependem de regra/parcela/ordem/limites;L8 conserva saldo final | Estimativa inicial48–80h;saldo integral não reestimado |
|
||||
| L8 — IRPC: liquidação e pagamentos | Parcelas L5–L7 e formulários originais | PPC/PEC, deduções/créditos, dupla tributação quando aplicável, saldo anual a pagar/recuperar; calendário e reconciliação com pagamentos | Retenções, colecta, saldos anteriores, pagamentos/comprovativos | Base anterior para PPC/PEC, regras de limitação/transporte; não usar cinco anos ou compensação automática sem cotejo específico | 32–56 h |
|
||||
| L7 — IRPC: tratamentos específicos | f8d57bdd instalado;632dc069 e a7434cd2 preservados no percurso | Cumulações demonstradas disponíveis;7famílias de saldo e documentos por caso discriminados;L7parcial | Activos/períodos/saldos/benefícios reutilizados;ordem,limites e incompatibilidades explícitos | Outras combinações/específicos/mistos/transporte próprios;L8delimitado separadamente | Inicial48–80h;saldo não reestimado |
|
||||
| L8 — IRPC: liquidação e pagamentos | Primeiro incremento delimitado,não implementado:colecta válida→retenções recebidas por conta/PPC comprovados→saldo simulado | Residente geral,ano2026/MZN;ausências documentadas dePEC/créditos/autónomos fora do recorte;gravação/recuperação/relatório a demonstrar | Reutiliza colectaL6/L7,L5received/effective/on_account ecomprovativos do próprio sujeito/período | Não abater retenções por conta de terceiros;PEC/créditos/limites próprios;regra de mínimo/versionamento a aplicar;camposM20M22 só bloqueiam transporte afectado | Inicial32–56h;não é previsão actual do recorte |
|
||||
| L9 — INSS: contribuição social | Massa salarial agregada e referência TCO3%+4% | Trabalhadores, remuneração/base contributiva, exclusões, empregador/trabalhador, TCO/TCP, declaração e encargos por período | Equipa/custos, entidade e calendário; cadastro de pessoa partilhado com L10 | Regulamento e alterações aplicáveis, natureza do vínculo; confirmar base antes da taxa. Contribuição social, distinta dos impostos | 24–40 h |
|
||||
| L10 — IRPS: retenção mensal e líquido | Entrada IRPS, custos salariais e escalões anuais documentais | Tabela mensal própria, remunerações/benefícios, situação pessoal relevante, retenção, salário líquido e contribuição ligada a L9 | Mesmo trabalhador/folha salarial, pagamentos e retenções | Tabela mensal do período, residência e condições familiares necessárias; não dividir escalões anuais por12 | 40–64 h |
|
||||
| L11 — IRPS: apuramento anual e outras categorias | Escalões anuais e exemplares M/19/M/20/anexos | Categorias aplicáveis aos rendimentos documentados, actividade independente, capitais/prediais/mais-valias, englobamento/tratamento autónomo, deduções, retenções e saldo | Dados pessoais autorizados, rendimentos/despesas, activos e L10 | Código IRPS/Lei11/2025, âmbito/categoria/período e deduções pessoais; diferenças de edição dos anexos. Não copiar regras IRPC | 48–80 h |
|
||||
@@ -6572,3 +6572,402 @@ A opção «Preparar cumulações dos tratamentosL7 registados» reutiliza coope
|
||||
Entrega agrupada preparada com os sete casos novos compatíveis;incompatibilidade e informação insuficiente acompanham o mesmo candidato como estados demonstrados. Não houve instalação nesta passagem. A futura entrega requer main compatível,capacidade do servidor medida novamente ebackup/restauro fresco,mantendo a versão activa até a nova ficar pronta. Recibo:`docs/investmoz/simulations/irpc-l7-combinations-qa-20261026.json`;provas:`outputs/irpc-l7-combinations/`. Reprodução só do delta:`node --test tests/frontend/irpc-special-combinations.test.mjs`;`php tools/irpc-special-combinations-qa.php routes`;`php tools/irpc-special-combinations-qa.php test`;`tsc --noEmit`;build com `INVESTMOZ_QA_BUILD=1`. **L7 parcial;colecta simulada distinta do saldo finalL8.**
|
||||
|
||||
Conferência de compatibilidade:main `a7434cd2` incorporado na candidata,com apresentação/catálogo e linhas não fiscais da matriz preservados. Recuperada a adenda históricaQA13 que tinha desaparecido do manual no main;isto é perda documental,não perda do cálculo13. Só tipos/build de integração foram conferidos novamente;provas fiscais aceites conservadas. A revisão servida não foi consultada nesta passagemQA.
|
||||
|
||||
## 26/10/2026 — Cumulações L7 entregues pelo Git
|
||||
|
||||
**Instalado `f8d57bddf96b4610604a013fcc5bdd703c7dc6d5`.** A anteriora7434cd2,que já incluía632dc069,fica preservada. Main/candidata compatíveis;apresentação ecatálogo sectorial entregues entretanto mantidos. A notaQA anterior é histórica:não há pendência de instalação deste incremento.
|
||||
|
||||
Medição inicial:5.06GiB,com inodes suficientes,mas sem margem para o backup fresco mais o mínimo5GiB do instalador. Recuperados0.21GiB somente da cache versionada de compilaçãoNode em`/tmp/node-compile-cache`,sem gestores de pacotes ou ficheiros abertos. Fontes,node_modules,releases,backups,logs,originais eSGF mantidos;permissões/proprietário da pasta preservados. Nova capacidade:5.26GiB e21374782inodes. Backup fresco`2026-10-26T14:20:47Z`:174tabelas/369ficheiros econfiguração;restauro isolado sem rede/55441 com174checksums iguais. Após o backup restavam5.10GiB,acima do mínimo5GiB de compilação;a guarda de um segundo backup não é requisito para repetir o backup acabado de executar. Nenhum limiar foi reduzido.
|
||||
|
||||
Só depois destas guardas,integraçãoGit sem forçar histórico;release anterior activa até a nova estar pronta. Compilação,tipos econtrolos automáticos do procedimento passaram:1054testesfrontend,API59testes/317asserções,preservação1teste/3106asserções. Reutilizadas as provasQA12testes/API133/UI/relatórios,não repetidas por iniciativa desta entrega. Conferidos4ficheiros fiscais do delta,68protegidos,31originais,369persistentes/configuração e174tabelas;172tabelas de negócio mantidas,cache/sessões reconciliadas com eventos operacionais/acessos públicos. Schema,roles/grants epermissões iguais;sem migrações/importações/escrita privada sintética. Revisão/manifest servidos,15marcadores,4assets eHTTP200 do simulador conferidos.
|
||||
|
||||
O recorte mantém a diferençaCBF16 de25MZN aplicada uma vez,com15recuperados já incluídos nos75deduzidos;depois aplica16% à base cooperativa integralmente elegível. No caso combinado,colecta496,80MZN;com despesa autónoma qualificada,512,80+35=547,80MZN. Valores são colecta simulada,não saldo finalL8. IncompatibilidadeCBF4/13,excepções sem correspondência e informação em falta permanecem explícitas;nenhum benefício é escolhido ouapagado automaticamente.
|
||||
|
||||
Após a instalação ficaram4.14GiB livres. Antes de outra compilação,voltar a resolver capacidade contra o mínimo existente e o backup dessa execução;esta entrega foi concluída e não autoriza apagar releases,backups ou provas. SaldoL7 e primeiro incrementoL8 são discriminados na secção seguinte. Recibo:`docs/investmoz/simulations/irpc-l7-combinations-delivery-20261026.json`;provas:`outputs/irpc-l7-combinations-delivery-20261026/`. **L7 parcial;L8 conserva saldo final.**
|
||||
|
||||
## 26/10/2026 — Saldo consolidado de L7 e primeiro incremento delimitado de L8
|
||||
|
||||
**L7 parcial,com a entrega de cumulaçõesf8d57bdd registada acima.** Deixam de estar pendentes de instalação a combinaçãoCIRPC12+CBF16 no recorte qualificado,a separação do imposto autónomo61(4) e os estados de incompatibilidade/falta/excepção não correspondida demonstrados. Isso não implementa todas as cumulações nem os tratamentos abaixo. Fontes oficiais e provas aceites permanecem válidas;documento em falta limita só o caso/campo que dele dependa.
|
||||
|
||||
| CódigoL7 ainda por implementar | Exemplo e condição concreta de retoma |
|
||||
| --- | --- |
|
||||
| Outras origens/segregações de despesas autónomas | Despesa100 com apenas60 correspondidos em36g ou encargo fora do resultado:ligar origem/parcela e incidência61(4),sem segundo acréscimo. |
|
||||
| Cooperativas mistas/retidas e demais entidades9–14 | Base agrária com serviços não abrangidos ou rendimentos sujeitos a retenção:segregar proveitos/custos/base e aplicar o artigo específico;não reduzir tudo a16%. |
|
||||
| ExtensõesCBF16 e outras combinações | Activo anterior a2025,usado/reabilitado/reavaliado,método/período fora da cobertura,ou excepção expressa à não cumulação:ligar regra temporal/base/método e disposição,ordem e limites à parcela;reutilizar activos/quotas,sem reescrever o passado. |
|
||||
| Mais-valias61-A e operações54–56/41-A | Ganho já incluído no resultado ou transferência de activo/perda:implementar apuramento e reconciliação próprios,sem dupla incidência ou compensação presumida. |
|
||||
| CBF17–19 e direito potencial15 | Formação/investimento com activos e despesas elegíveis/excluídos:implementar base,limite,janela temporal e compatibilidade. Direito/origem do crédito emL7;utilização anual e saldo emL8. |
|
||||
| Regimes sectoriais/territoriais e benefícios específicos | EstatutoZEE ou projecto de infra-estruturas:aplicar disposição/período efectivos e excepção quando prevista;endereço/sector não concede benefício. |
|
||||
| TransporteL7M20/M22 | Efeito calculado sem campo/edição correspondente:identificar exemplar,instrução,campo e representação;conservar o cálculo exacto independente. |
|
||||
|
||||
**Documentos por caso,distintos de código:**natureza/parcela/período;estatuto/reconhecimento exigido ou norma de excepção;saldos anteriores e distinção de exclusão temporária/permanente;disposição/ordem/limites da combinação;exemplar/edição/campo/representação. Não pedir nova validação genérica da autenticidade de fontes aceites,nem repetir pesquisas anteriores sem informação nova. Não preencher campo,código,taxa ou saldo por presunção.
|
||||
|
||||
### L8 — primeiro percurso a implementar em QA:colecta→pagamentos comprovados→saldo simulado
|
||||
|
||||
**Delimitado,não implementado ou instalado nesta passagem.** Recorte inicial:IRPC de residente no regime geral,ano civil2026,MZN,com colecta corrente determinada e suportes que permitem reconciliar o fecho. Parte de uma execuçãoL6 válida ou deL7 válida quando os efeitos aplicáveis estejam qualificados;guarda chave/versão/NUIT/período e valores de origem. Não soma colectaL6 com colectaL7 nem a colecta ordinária com uma colecta combinada que já a inclua. Não usa uma versãoL6 para ignorar um efeitoL7 positivo ou pendente que afecte o mesmo fecho. Um caso ordinário independente não espera pela implementação de outro benefício ou por um campoM20/M22 desconhecido.
|
||||
|
||||
**Dados reutilizados e qualificações novas apenas onde necessárias:**
|
||||
|
||||
1. **Colecta:**reutilizar a execução e as condições existentes,distinguindo colecta ordinária,imposto autónomo e colecta combinada. O primeiro fecho completo limita-se aos casos com ausência documentada de tributação autónoma/mais-valias que exija liquidação própria. Se existir imposto autónomo positivo,a parcela ordinária pode ser apresentada,mas não como saldo total até corresponder a articulação;não o apagar ou compensar por pressuposto.
|
||||
2. **Retenções sofridas:**reutilizarL5 apenas quando `direction=received`,natureza `on_account`,origem efectiva,documento/prova e montante sofrido reconciliados,mesmo sujeito/NUIT/período e rendimento incluído na base apropriada. Retenção entregue pela empresa por pagamento a terceiros,retenção definitiva,mera projecção,guia sem pagamento ou montante ainda não comprovado não são crédito próprio. EmL7cooperativa,a declaração de ausência de rendimentos retidos não pode coexistir silenciosamente com retenção recebida positiva;esse caso exige a segregação própria,sem bloquear o regime normal independente.
|
||||
3. **Pagamentos por conta efectuados:**registar/reutilizar comprovativo,identificador,data,exercício,sujeito e montanteMZN;reconciliar parcelas e pagamentos sem dupla utilização. Neste primeiro incremento,não calcular automaticamente a obrigaçãoPPC a partir do exercício anterior,nem transformar tesouraria prevista em pagamento efectuado.
|
||||
4. **Outros créditos/PEC:**reutilizar a informação existente e distinguir valor conhecido,ausência declarada e falta de informação. O primeiro percurso completo exige ausência documentada dePEC e créditos por dupla tributação/investimento/outros créditos ainda sem limite/ordem correspondidos. Presença positiva mantém a parcela/fecho dependente indeterminado;não usar zero. CBF15 potencialL7 não é automaticamente crédito anual utilizável. PEC não se transforma em montante reembolsável nem recebe transporte de3/5anos por presunção.
|
||||
5. **Identidade/duplicação:**contrapartes e documentos existentes são reutilizados;qualificar beneficiário e NUIT do próprio sujeito. Deduplicar por origem/documento/comprovativo e controlar afectações parciais;um comprovativo não pode aparecer integralmente em retenções ePPC,ou em dois exercícios. Preservar valores declarados e histórico,sem consumo de saldo oficial.
|
||||
|
||||
**Resultado e sequência a demonstrar:**colecta válida→deduções admissíveis e respectivas ausências→retenções efectivamente sofridas por conta→PPC comprovados→saldo aritmético→aplicação das regras de cobrança/reembolso do recorte→montante simulado a pagar ou recuperar. Mostrar a decomposição e o sinal;zero só com entradas completas ou ausência documentada. Informação em falta não transforma a colecta em saldo final. Como a base nasce do plano,o resultado continua uma simulação identificada,não autoliquidação submetida,pagamento efectuado ou reembolso deferido/recebido.
|
||||
|
||||
**Fontes já disponíveis para o cotejo dirigido de implementação:**CIRPC63/67,natureza das retenções com as alteraçõesLei12/2025;RegulamentoDecreto9/2008 art21(2–5),ordem/limites das deduções,eart27(1–2/6),pagamentos e reembolso. O exemplar aceite prevê no27(6) um mínimo de100MZN;esse parâmetro e a fronteira devem ser ligados à versão/período aplicáveis antes de activar o consumidor,não inferidos de um rótulo de formulário. O cotejo de aplicabilidade/alterações desta regra é trabalho de implementação da fonte aceite,não pedido de certificação genérica nem reabertura dos cálculosL6/L7. Arts64–66/PEC e créditos específicos mantêm as suas regras próprias;juros/multas/calendário,geração de guias,submissão e processamento de reembolso seguem incrementos próprios.
|
||||
|
||||
| Critério de aceitação a executar,sem prova reivindicada agora | Exemplo sintético proposto |
|
||||
| --- | --- |
|
||||
| Saldo positivo com pagamentos/retencões válidos | Colecta1408−retenção sofrida300−PPC500=608MZN de saldo aritmético;qualificar valor a pagar segundo a regra aplicável. |
|
||||
| Saldo negativo | Colecta1408−retenção1000−PPC600=−192MZN;identificar192 a recuperar no recorte,se a regra permitir,sem afirmar reembolso recebido. |
|
||||
| Zero e fronteiras do mínimo | Colecta1408−408−1000=0;demonstrar os lados inferior/igual/superior do mínimo do parâmetro versionado,sem arredondamento novo. |
|
||||
| Ausência vs informação em falta | Ausência documentada de retenções/PPC/outros créditos permite saldo com parcelas zero justificadas;suporte ou natureza por determinar mantém só o fecho dependente indeterminado. |
|
||||
| Reutilização e dupla dedução | Seleccionar retenção recebida e comprovativo existentes,recusar pagamento a terceiros/retenção definitiva/duplicado e demonstrar conservação dos originais e cenários anteriores. |
|
||||
| Cálculo→gravação→recuperação→relatório | Novo livro/snapshotL8 ligado à chave da colecta e às provas seleccionadas;resultado13/14 eL5 anteriores imutáveis;mudança da fonte invalida a fotografia corrente sem recalcular históricos. Relatório/exportação apresenta colecta,abatimentos,saldo e lacunas concordantes. |
|
||||
|
||||
Só serão demonstradas estas novas regras/efeitos,emQA isolada e com as guardas existentes. Fracções continuam exactas;representação/campos oficiais sem correspondência ficam identificados e não bloqueiam cálculo independente. Pagamentos noutra moeda,períodos especiais,PEC/créditos positivos,liquidação autónoma e demais situações ficam no saldo concreto deL8,com condição de retoma por regra,origem,limite,período e prova. A documentação deste recorte não é novo cálculo executável.
|
||||
|
||||
### Esforço global:referência inicial não é previsão actual
|
||||
|
||||
As240–416horas deL8–L14 permanecem identificadas como referência inicial de planeamento,não saldo actual nem prazo assumido. Antes de estimar o conjunto:reconciliar por lote o que já está implementado/reutilizável e o que falta em código;descontar provas aceites sem as repetir;separar espera documental;incluir resíduosL1–L7,integrações/entregas eL15–L16,SISA/encargos imobiliários. Campos de entrada,fontes inventariadas ou percentagens isoladas não provam percurso executável completo. Contar apenas o delta necessário e não somar duas vezes componentes partilhados. Esta passagem entregaL7 e delimitaL8;gere uma estimativa reconciliada futura,sem converter os intervalos iniciais numa promessa global. **L7 parcial;saldo finalL8 ainda não implementado nesta entrega.**
|
||||
|
||||
## 26/10/2026 — L8: primeiro saldo anual simulado demonstrado em QA
|
||||
|
||||
**QA concluído em `11a6cee9`; ainda sem instalação.** `f8d57bdd` permanece a entrega comunicada no portal. Este incremento reutiliza a colecta corrente de L6 ou o total ordinário L7 aplicável, sem somar ambos nem contornar um tratamento pendente. Recorte: sujeito residente no regime geral, ano civil de 2026, MZN, sem PEC/créditos positivos ou imposto autónomo que exijam liquidação própria. L6 operacional no âmbito demonstrado; L7 mantém o saldo parcial já discriminado. Não há nova pesquisa ou reabertura das provas aceites.
|
||||
|
||||
**Percurso executável:** «Preparar saldo anual L8» reutiliza NUIT, exercício e chave/versão da colecta sem substituir edições deliberadas. Selecciona os comprovativos L5 recebidos, efectivos, por conta e reconciliados; confirma o próprio beneficiário e a inclusão do rendimento na base do exercício. Retenções entregues pela empresa por pagamentos a terceiros, definitivas ou projectadas não são abatimentos próprios. PPC exige recibo, emitente, data, titular, exercício, moeda, montante comprovado, parcela utilizada e confirmação do pagamento efectivo; não usa previsões do plano nem calcula a obrigação PPC. A reutilização não apaga provas ou consome saldos oficiais.
|
||||
|
||||
Conhecido, ausência declarada com suporte e informação em falta são estados distintos. Ausência contraditória, titular/exercício divergente, prova em falta ou origem desactualizada mantêm o saldo dependente indeterminado. A identidade normalizada do emitente/comprovativo detecta repetição mesmo com data alterada; a mesma prova não pode ser retenção e PPC. Controla limites do comprovativo e da afectação L5, incluindo parcelas em outros contextos do mesmo dossier. São simulações alternativas, sem reserva central ou consumo de crédito fiscal entre dossiers independentes.
|
||||
|
||||
| Caso demonstrado | Resultado L8 simulado |
|
||||
| --- | --- |
|
||||
| Colecta 1 408 − retenção sofrida 300 − PPC 500 | **608 MZN a pagar**. |
|
||||
| Colecta 1 408 − retenção sofrida 1 000 − PPC 600 | Saldo aritmético −192: **192 MZN a recuperar**, sem afirmar reembolso recebido. |
|
||||
| Colecta 1 408 − retenção 408 − PPC 1 000 | Saldo zero, com parcelas completas. |
|
||||
| Ausência declarada de retenções/PPC, PEC ausente e outros créditos conhecidos zero | 1 408 MZN a pagar; estados conhecidos/ausentes conservados. |
|
||||
| PPC por comprovar, prova repetida ou PEC positivo ainda sem regra própria | Saldo a pagar/recuperar indeterminado; entradas e subtotais conhecidos conservados. |
|
||||
| Fronteiras do mínimo: saldos ±99,99 e ±100 | Aritmética exacta; abaixo de 100 MZN sem cobrança/reembolso neste recorte; em 100 aplica pagar/recuperar. Sem arredondamento ou transporte de crédito inventado. |
|
||||
| Colecta anual L7 acelerada aceite de 1 996,80, sem abatimentos declarados | Reutilizada uma vez: saldo simulado 1 996,80, sem somar a referência L6 nem recalcular o benefício. |
|
||||
|
||||
**Fontes e limites:** CIRPC arts. 63/67, Lei 34/2007 e natureza da retenção na redacção aplicável da Lei 12/2025; Regulamento Decreto 9/2008 arts. 21(2–5) e 27(1–2/6). O mínimo de 100 MZN do art. 27(6) está ligado ao recorte ordinário de 2026; as alterações IRPC do acervo de 2025 não substituem essa regra. Exemplares, páginas e hashes constam do recibo, com aceitação oficial anterior preservada. Não generalizar este parâmetro a períodos/regimes não correspondidos. PEC positivo, crédito de investimento, dupla tributação e outros créditos não recebem abatimento, limite, transporte ou reembolso presumidos. Um crédito potencial L7 não passa automaticamente a crédito utilizável L8.
|
||||
|
||||
**Gravação e recuperação:** livro opcional `irpcAnnual` no snapshot existente, por contexto, sujeito e exercício; ligado à execução da colecta e às provas L5 seleccionadas. Guarda o input e o resultado simulado, acrescenta o resultado anterior ao histórico sem o recalcular, e invalida o resultado corrente quando mudam as fontes/entradas. HTML e dossier financeiro recuperam colecta, provas/parcelas, estados, saldo, lacunas e limites concordantes. Sem preparação L8, os relatórios anteriores não ganham linhas L8. Plano, originais, livros e históricos L5–L7 permanecem imutáveis. O saldo não é declaração submetida, pagamento efectuado ou reembolso recebido.
|
||||
|
||||
**Provas novas:** 19 testes frontend dirigidos; API privada QA, 1 teste/170 asserções, sete casos com cálculo → gravação → recuperação → HTML/dossier; base isolada `simulator_fiscal_delta_20261021_test`, loopback 55441, guarda de identidade e transacção com rollback. Interface real: preparar, preencher só dados em falta, seleccionar prova, impedir repetição, pagar/recuperar/zero/ausência/indeterminação, guardar/recarregar/recuperar/exportar, sem erros de página. Wayfinder `--with-form`, TypeScript e build QA passaram. Comparação de 2 832 ficheiros anteriores: só três pontos de integração alterados, mais os cinco ficheiros novos do incremento; motores L5/L6/L7, fontes, fixtures, schema, configuração e permissões preservados; 31 originais iguais. Não se repetiram suites aceites de L3, ISPC, câmbio ou L5–L7. SGF TEMPO separado.
|
||||
|
||||
### Saldo concreto L8 após este incremento
|
||||
|
||||
| Código ainda por implementar | Condição concreta de retoma |
|
||||
| --- | --- |
|
||||
| PEC e créditos positivos: investimento, dupla tributação e outros créditos próprios | Correspondência do crédito, titular/exercício, montante efectivamente disponível, ordem, limite e transporte aplicáveis; prova de cada saldo. Não presumir reembolsabilidade ou prazo de 3/5 anos. |
|
||||
| Liquidação de imposto autónomo/61-A e articulação com o saldo anual | Segregar a parcela autónoma e corresponder quais abatimentos podem incidir sobre ela; não a ignorar nem compensar automaticamente com prejuízo/PPC. |
|
||||
| Períodos especiais e comprovativos noutra moeda | Corresponder exercício/data de afectação e regra cambial fiscal do pagamento; reutilizar periodização/câmbio existentes sem confirmar pressupostos por omissão. |
|
||||
| Cálculo da obrigação PPC/PEC, calendários, juros/multas e guias | Regra, parâmetros, factos e vencimentos próprios por período. O registo de PPC efectuado já demonstrado não calcula a obrigação. |
|
||||
| Transporte oficial M20/M22, submissão e processamento de reembolso | Edição/campo, representação de fracções e fluxo de recepção correspondidos; sem preencher campos provisórios como oficiais. |
|
||||
|
||||
**Esclarecimentos documentais aguardados:** permanecem as dúvidas concretas L5/L6/L7 já registadas, sem nova pesquisa repetida. Exemplo: cooperativa com rendimentos mistos/retidos requer segregação antes de utilizar retenção positiva; excepção de cumulação exige disposição, período e limites correspondidos; campo M20/M22 divergente requer edição/campo exactos. Cada falta só bloqueia o seu caso. Ausência de documento num cenário não bloqueia o saldo normal independente acima.
|
||||
|
||||
**Próxima entrega:** compatibilidade conferida com `origin/main` em `f8d57bdd`, sem incorporar runtime do checkout raiz. Nenhum acesso ou operação no servidor nesta passagem. Os 4,14 GiB são o valor comunicado, não medição nova; antes de instalar, medir espaço/inodes, confirmar capacidade para backup/restauro fresco e compilação isolada, mantendo a versão activa até a nova estar pronta. Recibo: `docs/investmoz/simulations/irpc-l8-first-qa-20261026.json`; provas: `outputs/irpc-l8-settlement/`. Reprodução só do delta: `node --test tests/frontend/irpc-annual-settlement.test.mjs`; `php tools/irpc-annual-settlement-qa.php routes`; `php tools/irpc-annual-settlement-qa.php test`; `tsc --noEmit`; build com `INVESTMOZ_QA_BUILD=1`. **L8 parcial, QA pronto, sem instalação.** A referência inicial de 240–416 horas L8–L14 não é previsão actual; permanece necessária a reconciliação do trabalho reutilizado, resíduos e L15–L16 antes de assumir prazo global.
|
||||
|
||||
## 27/10/2026 — entrega L8 preparada; instalação adiada por capacidade
|
||||
|
||||
**Candidato `14360748` pronto; não instalado.** A conferência SSH autenticada de 27/10, 06:05 UTC (08:05 em Moçambique), confirmou `f8d57bdd` como revisão activa e `main` remoto. Compatibilidade por ancestralidade, pacote QA e 168 ficheiros do destino conferidos: 134 ficheiros protegidos, três integrações anteriores e 31 originais. O delta executável continua limitado a cinco ficheiros L8; os 19 testes, API/170 asserções, interface, recuperação/relatórios, tipos e build aceites foram reutilizados, sem nova ronda.
|
||||
|
||||
**Impedimento concreto:** partição `/dev/md2`, montada em `/`, com 4 402 343 936 bytes livres (**4,10 GiB**) e 21 340 182 inodes disponíveis. Inodes suficientes face à referência da release (31 259 entradas). O instalador existente exige **5 GiB livres após o backup**; com a referência observada do backup anterior de 175 917 490 bytes, faltam pelo menos **1,07 GiB adicionais antes do backup**. É uma estimativa mínima de capacidade, a medir novamente; não uma autorização para reduzir o limiar. Caches regeneráveis de Composer/Node somam cerca de 0,12 GiB e não cobrem a diferença. Diagnóstico apenas por leitura, sem limpeza de caches, releases, backups, provas, dependências ou ficheiros SGF TEMPO.
|
||||
|
||||
**Decisão expressa do utilizador: «Manter a entrega preparada por agora».** Não foram executados backup/restauro frescos, integração no `main` nem instalação. A versão activa foi preservada e a sessão SSH encerrada. Na retoma, seleccionar o ramo candidato `codex/irpc-l8-settlement-qa-20261026`, voltar a conferir `main` e revisão servida, medir capacidade/espaço/inodes, executar backup/restauro fresco e compilação isolada, mantendo o activo até a nova release estar pronta. Só depois conferir a revisão servida e o delta L8. As notas desta espera ficam no ramo documental `codex/irpc-l8-delivery-capacity-20261027`; não mudam o código candidato. L8 parcial, PEC/créditos próprios separados e saldo L7 preservado. Recibo: `docs/investmoz/simulations/irpc-l8-delivery-capacity-20261027.json`; provas e auxiliares preparados: `outputs/irpc-l8-first-delivery-20261027/` no checkout raiz.
|
||||
## 27/10/2026 — identidade proactiva: primeiro incremento demonstrado em QA
|
||||
|
||||
**QA concluído em `3439f350`; sem instalação, publicação real ou análise económica validada.** Partida no `main` remoto `f8d57bdd`, conferido novamente antes da entrega. Ramo separado `codex/proactive-investment-first-qa-20261027`, worktree `C:/laragon/www/portal-investidor-proactive-qa-20261027`. A referência local `fa02c70` e o ramo `codex/proactive-investment-scope-20261027` não foram encontrados no repositório consultado; o âmbito expresso da Tempo foi suficiente e não se criou dependência desse commit. **L8 `14360748` mantém-se preparado, sem instalação e sem integração nesta candidata.** A capacidade do servidor continua fora deste trabalho local. Sem SSH, instalação, limpeza do servidor ou intervenção no SGF TEMPO nesta passagem.
|
||||
|
||||
### Diagnóstico dirigido e decisões de implementação
|
||||
|
||||
| Componente existente | Reutilização e lacuna concreta tratada |
|
||||
| --- | --- |
|
||||
| `geo_locations`, `sectors`, `value_chains`, `projects`, `economic_clusters`, `development_corridors`, `investment_zones` | Mesmos identificadores, hierarquia, sectores e referências públicas já disponíveis; selectores e catálogo existentes. Não se criaram mestres territoriais, empresas, projectos ou estruturas para completar campos em falta. |
|
||||
| `investment_gaps` e `investment_specific_needs` | Mantidos nos seus âmbitos de lacuna de cluster/cadeia e necessidade de manifestação. O schema público exige contexto de cluster/cadeia/capacidade no primeiro e submissão/opções no segundo. Não se inventam esses valores para guardar uma hipótese territorial inicial. A análise editorial é uma parte versionada do rascunho existente, não outro catálogo ou cadastro de lacunas económicas validadas. |
|
||||
| `Opportunity`, `OpportunityManagement`, `management_draft`, `audit_events` | Acrescentado só o bloco opcional `proactive`: evidências, necessidade, ideia e relações. Reutilizados identidade, chave de criação, etag, rascunho, auditoria cifrada e versões. Criação repetida não duplica a ficha; versão antiga não sobrescreve edição concorrente. |
|
||||
| Editor de oportunidades e designação interna da equipa | Lacuna confirmada: a preparação inicial exigia organização promotora até quando desconhecida. Permitida a preparação/edição de análise proactiva sem promotor real apenas no âmbito da designação interna existente. Organização real fica nula; operador e responsável continuam identificados. Sem novo papel, aprovador, grant activo ou permissão universal. Os restantes percursos mantêm as condições anteriores; actores não designados e operadores de outro âmbito são recusados. |
|
||||
| `portal_resources`, `documents`, `opportunity_documents` e gestor documental existente | Referência ao documento já associado, fonte, exemplar, localizador, período, abrangência, cobertura e verificação. Não copia o binário nem altera direitos, classificação ou scan. Documento interno/restrito ou fora do âmbito não passa a público pelo formulário da análise. Listas de empresas, hotéis e restaurantes continuam inicialmente internas. |
|
||||
| `OpportunityPromotion` e catálogo/ficha existentes | Síntese expressamente pública, prévia e confirmação no fluxo já autorizado, com MFA normal. Nenhum texto interno é preenchido automaticamente. Estado da necessidade e estado da publicação são independentes. Consulta anónima só da versão publicada. |
|
||||
| `InvestorContext`, escolhas por oportunidade, `desk_cases`, `InvestorPath` e simulador | A origem, versão, território, sector, cadeia/etapa, relações públicas seleccionadas, pressupostos e limites seguem no contexto cifrado do dossier existente. Selecções múltiplas conservam uma fotografia por ideia; o consumidor/simulador recebe só a escolha em tratamento. Título e outras edições deliberadas são preservados. Sem regra fiscal nova ou benefício inferido da localização. |
|
||||
|
||||
### Implementado e demonstrado
|
||||
|
||||
- **Evidência:** actividades, recursos, infra-estruturas, oferta e procura; facto separado da interpretação. Finalidade local ou metodológica, acesso interno ou público autorizado e documento associado opcionais. Duplicação de evidência ou da mesma referência na análise é recusada. Informação em falta permanece em falta.
|
||||
- **Necessidade:** problema, oferta/procura observadas, quantidade/qualidade/logística/transformação/coordenação/apoio, clientes/beneficiários, fontes, limites e pendências. Pode guardar como hipótese. Confirmação exige os campos/fundamento e evidências locais seleccionadas com proveniência/cobertura/período/verificação; referência internacional, por si só, não confirma procura local. Histórico mostra hipótese e confirmação anteriores sem recalcular nem apagar os originais.
|
||||
- **Ideia:** solução, actividade, cadeia existente/etapa, abrangência, recursos, criar/expandir/associar, pressupostos, condições, pendências e próxima acção. Relações com estruturas existentes mantêm a qualificação documentada, hipotética ou proximidade. Nenhuma relação cria contrato, energia acessível, terra disponível, participação ou benefício fiscal.
|
||||
- **Aplicabilidade:** “O que existe” mostra evidências e contexto; “Necessidade” acrescenta a lacuna; “Ideia” acrescenta a solução. Campos anteriores ficam conservados quando ocultos. Não se exigem montante, promotor, coordenadas ou uma oportunidade previamente publicada para iniciar a preparação da equipa.
|
||||
- **Divulgação:** grupos “O que existe”, “Necessidades identificadas” e “Ideias de investimento” no catálogo existente; a consulta de oportunidades cadastradas conserva a verificação de disponibilidade na respectiva ficha. Uma ideia não é convertida em oportunidade com participação disponível. Textos públicos são redigidos separadamente, com revisão expressa da exposição directa/indirecta. Evidências internas e cópias literais detectadas são bloqueadas; uma confirmação pública depende do fundamento público seleccionado. Relações divulgadas transportam apenas referência pública, qualificação e base pública, sem copiar a referência privada.
|
||||
- **Continuidade:** criar → guardar → recuperar → editar → prévia/publicação em QA → consulta anónima → autenticação → dossier → recarregar/retomar sessão. Login e MFA Fortify normais demonstrados com contas sintéticas QA. O mesmo contexto chega ao dossier, sem substituir o título deliberado do investidor. Relatório existente mostra origem, estado, fundamento, evidências, relações, pressupostos, limites e próximo passo por ideia; sem preparação proactiva não acrescenta linhas.
|
||||
|
||||
### Referências metodológicas do Ruanda — dependência resolvida
|
||||
|
||||
O responsável forneceu os dois caminhos após a procura dirigida inicial. Exemplares acessíveis, originais preservados e hashes conferidos antes/depois. **Não foram importados ou publicados no portal.** Texto integral extraído e imagens de leitura ficam apenas nas provas privadas/ignoradas; o pacote entrega rastreabilidade e paráfrases metodológicas, sem os originais ou a reprodução integral dos diapositivos.
|
||||
|
||||
| Exemplar e passagem utilizada | Aplicação delimitada |
|
||||
| --- | --- |
|
||||
| `20070627_Rwanda_5d0cc43d-c990-4cf1-8ee9-ada71094918f.pdf`, 31 páginas, capa “Creating a Competitive Rwanda”, Michael E. Porter/HBS, Kigali, Junho2007. SHA256 `18b07a9379a1ad0baa33697d57d6237f15a6fec346db44bfee7506bf1fa27dee`. P14, “Improving the Business Environment: The Diamond”; P27, “Role of the Private Sector in Economic Development”, conferidas visualmente. | Perguntar por factores de produção, procura, fornecedores, actividades e serviços de apoio; distinguir relação documentada de acesso/compromisso. Cada afirmação sobre Moçambique precisa de evidência local própria. |
|
||||
| `Rwanda Competitiveness Briefing_Prof Porter_OTF.ppt`, 50 diapositivos na leitura nativa PowerPoint, capa “How Rwanda Competes Today”, RNIC, briefing para Prof. Porter, 20Julho2008. SHA256 `4a9325ad64278cb0ef3c60367a05ee2ed9262e2cd49a48d579061349914aa830`. Slide17, procura turística, fonte/amostra/período visíveis; slide20, constrangimentos por etapa da cadeia do chá; slide24, diagnóstico mineiro, texto em ordem nativa. | Conservar fonte, período, abrangência e cobertura/amostra das observações; estruturar etapas e limitações em vez de presumir uma lacuna. Dados, valores, projecções e instituições estrangeiras não são transferidos para os pilotos nem para regras fiscais. Slide17 conferido visualmente;20/24 lidos em texto nativo, sem alegar conferência visual desses dois. |
|
||||
|
||||
Os caminhos completos e os trechos/limites estão no recibo. O PDF2007 e o briefing2008 são exemplares distintos. Os 91 grupos de texto históricos encontrados numa exploração OLE não foram usados como número de diapositivos; a ordem nativa de 50 é a referência do PPT. A metodologia internacional orienta perguntas e organização; não demonstra procura em Cahora Bassa, Montepuez ou Gurué.
|
||||
|
||||
### Guia curto de utilização em QA
|
||||
|
||||
1. Entre na conta da equipa com a designação existente e abra **Minhas oportunidades → Nova oportunidade → Preparar análise e ideia**. Escolha título, sector e nível territorial conhecidos. O promotor real pode ficar por identificar; não são necessários montante ou coordenadas.
|
||||
2. Acrescente evidências. Separe o facto da interpretação e preencha fonte/exemplar, localizador, período, abrangência, cobertura e data de verificação. Marque referências internacionais como **metodológicas** e listas internas como **internas**. Use o documento já associado quando disponível.
|
||||
3. Mantenha a necessidade como **hipótese** enquanto faltar fundamento local. Para confirmar, explicite problema, observações, tipo, beneficiários, fundamentação e evidências locais. “Confirmada” não significa viabilidade comercial demonstrada. Guarde com motivo e recupere o rascunho; o histórico conserva o fundamento anterior.
|
||||
4. Quando aplicável, escolha **Ideia de investimento** e prepare solução/actividade, cadeia/etapa, recursos, relações e próxima acção. A proximidade fica identificada como proximidade. Escolhas existentes e campos ocultos continuam conservados.
|
||||
5. Abra **Divulgação promocional — Em preparação**. Redija os campos públicos separadamente, seleccione só evidências públicas e relações autorizadas, reveja a exposição directa/indirecta, prepare a prévia e confirme **apenas em QA**. A referência privada da relação e os documentos internos não são copiados. A revisão editorial continua humana no fluxo existente; o controlo literal não é validação semântica de todas as inferências possíveis.
|
||||
6. Consulte sem sessão em `/oportunidades?perspective=ideas` (ou `exists`/`needs`). **Iniciar ou continuar o roteiro deste investimento** utiliza a autenticação e o dossier existentes. Confirme o contexto na prévia antes de guardar; pode continuar um dossier ou criar um novo. Para várias ideias, escolha a que está em tratamento nos consumidores. O simulador recebe o contexto e conserva os seus dados/regras próprios; não calcula sem dados ou pressupostos explícitos.
|
||||
|
||||
**Reprodução técnica só do delta:** `php tools/proactive-investment-qa.php routes` (`--with-form`); `php tools/proactive-investment-qa.php test`; `node --test tests/frontend/proactive-investment.test.mjs`; `tsc --noEmit`; build com `INVESTMOZ_QA_BUILD=1`. Base isolada `proactive_investment_20261027_test`,127.0.0.1:55441, clonada do QA anterior com o mesmo schema/identificadores; guarda de identidade e rollback nos testes. Flags existentes de perfis/contratos especializados/percurso foram configuradas só no bootstrap QA; `.env`, configuração activa e grants activos não mudaram. O servidor HTTP de prova usou127.0.0.1:18760, não a homologação.
|
||||
|
||||
### Provas, preservação e saldo concreto
|
||||
|
||||
**Passaram:**14 testes da API/139asserções;7testes frontend de relatório/isolamento por ideia;Wayfinder,TypeScript ebuildQA;interface real com login/MFA,criação/edição/recuperação,histórico,perguntas aplicáveis,prévia/publicação QA,consulta anónima,contexto após autenticação,recarregar/retomar sessão,relações/pressupostos e ausência de erros de página. Casos Cahora Bassa/energia,Montepuez/mineração eGurué/chá são **inequivocamente sintéticos**,reutilizando distritos e sectores existentes. Não se publicou uma análise económica real nem se validou um mercado.14testes não são nova ronda de L3/ISPC/câmbio/L5–L8.
|
||||
|
||||
**Preservado:**15pontos de integração anteriores e7ficheiros novos de código/testes/guarda;89ficheiros de motores fiscais e31originais fiscais iguais,mais os2originais Ruanda intactos. Sem migrações ou novo catálogo/base territorial/sistema de permissões. Sem escrita na base origem ou activa;fixtures/grants sintéticos apenas no clone QA. A candidataL8 `14360748` conserva exactamente a mesma referência. O checkout raiz recebe somente este registo documental,sem integrar o runtime do ramoQA.
|
||||
|
||||
| Estado | Saldo e condição concreta de retoma |
|
||||
| --- | --- |
|
||||
| Implementado e demonstrado neste incremento | Percurso editorial técnico completo acima, no recorte QA e com os estados/limites visíveis. Pode preparar novos investimentos sem depender de oportunidades publicadas. |
|
||||
| Parcial — conteúdo económico real dos três pilotos | Recolher oferta/procura locais,exemplares,períodos,cobertura e informação de clientes/beneficiários;relacionar recursos/serviços com evidência. Só os casos apoiados por esses dados podem mudar de hipótese. Nenhuma falta bloqueia outra análise independente. |
|
||||
| Dependência documental/comercial | Contrato/encomenda,energia acessível,terra,participação disponível e condições comerciais precisam de prova específica por caso. A qualificação formal da oportunidade continua nos campos/fluxos existentes;este incremento não a presume a partir da localização,lista de empresas ou necessidade. Listas e contactos privados exigem síntese autorizada e revisão editorial no fluxo actual antes de qualquer divulgação. |
|
||||
| Dependência resolvida | Os dois exemplares Ruanda foram localizados/lidos nos trechos identificados;deixam de constar como ficheiros indisponíveis. A sua existência não substitui a evidência local. |
|
||||
| Trabalho futuro,fora do primeiro incremento | Automatizar inventário,indicadores,comparação/priorização e eventual IA;quantificar mercado/custos/rentabilidade só com dados/pressupostos explícitos;eventual correspondência a lacunas mestre de cluster quando os seus campos e fundamento forem conhecidos. Não há novo prazo global ou implantação activa reivindicados. |
|
||||
| Entrega futura no destino | CandidataQA peloGit apenas. Conferir o main vigente e compatibilidade com outros incrementos antes de integrar;capacidade,backup/restauro e instalação são uma execução separada autorizada. A espera de capacidade deL8 não foi contornada. |
|
||||
|
||||
Recibo:`docs/investmoz/unification/proactive-investment-first-qa-20261027.json`;provas:`outputs/proactive-investment-20261027/`. Não há novos cálculos fiscais,submissão AT,publicação na homologação ou alteração do SGF TEMPO.
|
||||
|
||||
## 27/10/2026 — primeiro caso proactivo com fontes reais: Cahora Bassa / apoio metrológico
|
||||
|
||||
**Análise preliminar privada demonstrada em QA, sobre o runtime aceite `3439f350` / candidata `1afab4a2`, sem nova alteração funcional ou instalação.** Caso `CB-METROLOGIA-20261027`, ficha QA `401`, dossier privado QA `894343c7-c33d-452e-a6a5-b6675f77ee23`. O operador é uma conta sintética QA já existente; os factos e referências desta análise são reais e identificados, distintos dos cenários fictícios anteriores. Não se publicou a análise, não se contactou comprador ou prestador e não se transportaram contactos, documentos pessoais ou NUIT das listas. L8 `14360748` conserva a mesma referência e continua separado. Main remoto conferido: `f8d57bdd`; sem SSH, limpeza, instalação ou intervenção no SGF TEMPO.
|
||||
|
||||
### Escolha do piloto e fontes reutilizadas
|
||||
|
||||
| Piloto | Resultado da triagem dirigida |
|
||||
| --- | --- |
|
||||
| **Cahora Bassa — seleccionado** | A lista empresarial fornecida contém referências históricas locais de reparação/manutenção mecânica e eléctrica. O acervo inclui a reprodução histórica da concessão HCB. Foram acrescentados o relatório primário HCB2024, a página institucional de engenharia e, decisivamente, o Plano de Compras HCB2026 publicado pelo IGEPE, que delimita um serviço concreto de calibração. É uma decisão por disponibilidade de fundamento nesta ronda, sem ranking de rentabilidade ou potencial económico. |
|
||||
| Montepuez | Há referências empresariais internas e fontes mineiras localizadas. Não foi escolhido nesta ronda um âmbito primário de aquisição tão directamente utilizável para esta aplicação. Não se conclui que falte actividade ou procura; continua elegível para outro caso documentado. |
|
||||
| Gurué | Há referências históricas internas ligadas ao chá e perfis/fontes públicos localizados. Os constrangimentos antigos encontrados não bastam para atribuir automaticamente uma lacuna actual à cadeia do chá. Não foram transpostos para a proposta de Cahora Bassa. |
|
||||
|
||||
Inventário anterior de606 fontes preservado e consultado; listagem dirigida dos documentos acessíveis no acervo e triagem dos dois workbooks empresariais/cadastro turístico ficam nas provas privadas. Os workbooks têm grãos/períodos/versões distintos e registos repetidos: não se somaram os totais entre eles nem se contou uma denominação repetida como várias empresas. O cadastro de alojamento de3–5estrelas não demonstrou cobertura distrital comparável neste recorte; não demonstra ausência de hotéis ou serviços e não foi usado para inferir procura metrológica.
|
||||
|
||||
| Evidência / exemplar | Âmbito usado e limite |
|
||||
| --- | --- |
|
||||
| HCB, **Relatório e Contas2024**, edição bilingue,63páginas PDF; PDFp9/página impressa14. URL `https://hcbadm.mzbusiness.com/wp-content/uploads/2025/08/Relatorio-e-Contas-2024-Bilingue-VF-1.pdf`. SHA256 `d0fed6af0e40fffd6f7f385152fdbfff2a10cae0b66c9d7a59a0a99658758080`. | Actividade e infra-estruturas existentes da HCB. Página conferida visualmente; não é carteira de contratos disponíveis. Matambo não é atribuída ao distrito de Cahora Bassa. |
|
||||
| HCB, **Plano Anual de Compras2026**,8páginas; PDFp1,2.ª/3.ªlinhas de dados. URL `https://igepe.org.mz/wp-content/uploads/2026/06/HCB-Plano-Anual-de-Aquisicoes-2026.pdf`. SHA256 `cbc93102fea61a712c193d1c1815e7ec19e7d570ee2703c1b1390d4c05e5bd8e`. | Duas entradas de calibração de equipamento de medida e monitorização, concurso limitado, previsões19/02–30/06 e05/05–14/09/2026. Em27/10/2026 os prazos previstos já passaram. Plano não confirma procedimento aberto, adjudicação ou procura ainda insatisfeita. “1” em “Qtde de Itens” não é número de instrumentos; linhas de igual designação não provam dois contratos independentes. Conferência visual da tabela. |
|
||||
| Lista fornecida **Empresas Licenciadas.xlsx**, `Servicos Tempo/Relatorios/novos/docs`, folha`EMPRESAS`; SHA256 `1b5087b464e39e88c42def39655c2391aaaf684b4c832d6a77ff274b98889f00`. | Pistas internas: L19376,D19376,O19376:P19376,U19376:V19376 e L55640,D55640,O55640:P55640,U55640:V55640. Licenças2018/2021, não capacidade actual. Linhas12243/19376/65567 repetem denominação e não são contadas como três empresas. Nenhuma lista/contacto foi copiada para publicação. |
|
||||
| **CAE eBAU.xlsx** fornecido, folha`CAE`, B857/F857 e B859/F859. | Etiquetas de33120 — reparação/manutenção de máquinas/equipamentos e33140 — equipamento eléctrico, lidas no exemplar fornecido. Não comprovam calibração, qualificação, acreditação ou vigência actual de licença; não se declarou uma versão oficial actual do catálogo sem identificação. Hash/caminho no recibo. |
|
||||
| **HCB-TERMOS-DO-CONTRATO-DE-CONCESSAO.pdf** fornecido, página única; BR I Série47,21/11/2007,Decreto57/2007,artigo2. SHA256 `f4afc62f140d197cae3bf395674adce2eba37f0436261d52d7eb554f6230a073`. | Contexto documental histórico da actividade, conferido visualmente. Sem análise da vigência actual ou aplicação de regra ao novo investimento. Direitos de concessão não se tornam direitos do promotor. Original preservado, não importado/publicado. |
|
||||
| Página institucional HCB`https://www.hcb.co.mz/hidroelectricidade`, consultada27/10/2026. | Contexto do complexo e CAPEX Vital; sem data editorial precisa ou progresso actualizado de cada obra. Não comprova contratação adicional. Captura/hash privados; sem copiar projecções para o orçamento da ideia. |
|
||||
|
||||
Os exemplares Ruanda já aceites continuam apenas metodológicos; não se repetiu a sua prova nem se usaram como evidência de procura local. Os cinco originais locais usados permanecem com hashes iguais. Fontes públicas adicionais foram guardadas como cópias privadas de consulta, sem importação, publicação ou alteração de direitos no portal.
|
||||
|
||||
### Actividade, necessidade e ideia estruturada
|
||||
|
||||
**O que existe:** actividade hidroeléctrica e infra-estruturas HCB documentadas; registos históricos locais de actividades de reparação/manutenção. **Necessidade documental:** o comprador planeou serviços de calibração em2026. **Hipótese por verificar:** existe procura residual/recorrente e uma vantagem concreta de apoio local no Songo. Não há evidência de falta de fornecedores, atrasos, preços elevados ou adjudicação disponível; a necessidade comercial mantém o estado **hipótese**, com esse fundamento guardado.
|
||||
|
||||
**Ideia:** estudar associação entre prestador local e laboratório qualificado para apoio metrológico à HCB no Songo: inventário/gestão de instrumentos, preparação, recolha/entrega controlada e acompanhamento documental. Calibração/ensaios só por quem demonstrar competência no âmbito contratado. A associação é uma proposta, não acordo. **Cliente potencial:** HCB, apenas nas unidades e procedimentos em que o serviço se justifique; outros clientes não foram presumidos. Etapa: apoio à manutenção na produção/transporte de electricidade. Sem criar cadeia mestre ou relação canónica para preencher uma correspondência não disponível no clone. Abrangência distrital/proposta no Songo, sem parcela, instalações, energia ou acesso assegurados.
|
||||
|
||||
**Condições:** confirmar requisitos efectivos do comprador e do âmbito metrológico, capacidade, rastreabilidade, segurança/acesso, responsabilidades, regras de associação/transporte e eventual acreditação exigida. Não se impôs certificação específica por interpretação do plano. Recursos de operação, equipa, instrumentos, veículo, instalações e laboratório ainda não estão assegurados. Montante, promotor empresarial, coordenadas exactas, preços, volume, mercado, receitas e rentabilidade permanecem por determinar; sem usar zero ou totais do plano como substitutos.
|
||||
|
||||
### Demonstração deste caso e continuidade
|
||||
|
||||
Criada pela interface existente,guardada,recuperada e conferida na mesma ficha privada. Cinco evidências preservadas;necessidade comercial como hipótese;campos de clientes,oferta,procura,condições e próxima acção recuperados sem alteração. A mesma contaQA preparou um dossier privado pelo percurso existente,confirmou o contexto e recuperou a fotografia da ideia pela API autenticada. O relatório existente produziu as cinco linhas de evidência e os mesmos limites;uma leitura privada de prova reúne essas linhas e as observações do caso. Nenhuma publicação promocional foi preparada ou confirmada. Ficha permanece`draft`,fora da consulta publicada;consulta anónima do dossier recusada.
|
||||
|
||||
Reutilizadas as14provas API/139asserções,7provas frontend,tipos ebuild de`1afab4a2`;não se repetiu a ronda técnica ou fiscal. Feita apenas aplicação e conferência do novo caso real. A primeira leitura da página do dossier antecedeu o fim da gravação do contexto;após recuperação concluída,interface eAPI concordaram. Corrigida a espera no script local de prova,sem mudar código da aplicação ou regravar históricos. Preservação por hash das linhas anteriores no mesmo clone:52fichas,17dossiers,19projectos,1921territórios,12sectores,63documentos;uma ficha e um dossier novos. Sem migrações,importação de empresas,novos grants ou alteração do destino activo.
|
||||
|
||||
**Para consultar ao retomar QA:**usar a contaQA já designada e abrir`/minhas-oportunidades/401/edit`;comparar os campos/fundamentos;abrir o dossier`/investimentos/894343c7-c33d-452e-a6a5-b6675f77ee23`. É um percurso privado,não um link público nem uma nova instalação. Recibo:`docs/investmoz/unification/proactive-real-pilot-qa-20261027.json`;provas privadas:`outputs/proactive-real-pilot-20261027/`. Cookies,credenciais,extractos integrais de listas,originais e ficheiros de diagnóstico não integram o pacote de entrega.
|
||||
|
||||
### Saldo e perguntas concretas de retoma
|
||||
|
||||
| Ponto | Exemplo/pergunta e condição de retoma |
|
||||
| --- | --- |
|
||||
| Procura actual e estado das compras | As entradas terminavam em30/06 e14/09/2026:foram executadas,adjudicadas,canceladas ou reprogramadas? Existe novo ciclo em2027? Retoma da qualificação comercial apenas com estado e necessidade residual/recorrente identificados pelo comprador. |
|
||||
| Âmbito técnico e operacional | Que famílias/instrumentos,quantidades,periodicidade,local de execução e prazo de devolução se aplicam? Que qualificação/rastreabilidade/acreditação é exigida neste âmbito? Obter a especificação antes de dimensionar meios ou afirmar elegibilidade. |
|
||||
| Oferta e associação | Os dois registos internos seleccionados continuam activos,interessados e tecnicamente aptos? Que laboratório pode assumir o âmbito? Verificar capacidade/competência,consentimento e oferta concorrente;cadastro/CAE não basta. Não enviar contactos ou listas automaticamente. |
|
||||
| Vantagem e viabilidade | O apoio no Songo reduz um problema mensurável do cliente face à solução actual? Comparar transporte,prazos,risco,custos e condições;quantificar só quando houver dados. Não comprar equipamento ou criar orçamento com base apenas no plano. |
|
||||
| Divulgação ou uso no activo | Preparar eventual síntese pública separada só quando autorizada/revista;instalação do código não publica nem transporta automaticamente a ficha e o dossierQA. Capacidade,compatibilidade e backup/restauro serão tratados na execução futura aplicável. Nenhuma dependência de capacidade impede esta análise privada. |
|
||||
|
||||
**Estado:**primeira aplicação real demonstrada,análise económica/comercial preliminar. Preparadas perguntas para reunião exploratória com a HCB,sem as enviar. L8eSGF preservados;limites e pendências anteriores não foram eliminados.
|
||||
|
||||
## 27/10/2026 — orientação confirmada: oportunidades geradas pela procura
|
||||
|
||||
**Decisão expressa do responsável:** “a ideia não é gerir concursos mas sim as oportunidades que geram”. O anúncio é uma fonte de procura para preparar oportunidades complementares; não se cria um circuito de concursos, candidaturas ou adjudicações. O percurso técnico aceite em`1afab4a2` continua preparado para entrega independentemente da confirmação comercial do caso. Instalação e capacidade do servidor seguem separadas;sem nova intervenção no destino ou no SGF TEMPO. L8`14360748`preservado.
|
||||
|
||||
**Caso privado QA — evolução da mesma ficha e dossier:**ficha401,versão1→2;dossier`894343c7-c33d-452e-a6a5-b6675f77ee23`,contexto1→2. Sete evidências recuperadas. Modelo centrado em serviço recorrente de apoio metrológico no Songo,associando apoio local e laboratório competente:inventário/calendário,preparação,recolha/entrega controlada e documentação. Cliente potencial inicial:HCB. Outros clientes dependem de identificação própria. Sem contrato,parceria,procura recorrente ou vantagem económica declarados como confirmados. Título e campos deliberados do dossier conservados;fotografia anterior e388eventos de auditoria existentes intactos. Não se criou outra ficha,dossier,empresa,grant ou regra fiscal.
|
||||
|
||||
### O que a nova fonte esclarece
|
||||
|
||||
- **Procura e âmbito:**o anúncio da HCB,de17/08/2026,referência051/2026,identifica quinze famílias de instrumentos e outros a especificar nos TdR;por exemplo,manómetros,balanças,paquímetros/micrómetros,multímetros e instrumentos de análise eléctrica. O PDF tem2páginas,ambas lidas visualmente;SHA256`bb4c33064e5d49504d8a85ac88ad1b847cfa6c69e1016e3ab588ff785b205c1f`;exemplar`https://www.diarioeconomico.co.mz/wp-content/uploads/2026/08/concurso-hcb-tender-document-docu-mo-ambique-2026-1.pdf`. Não contém volumes,gamas,incertezas,periodicidade ou execução. O prazo04/09/2026é histórico,não oportunidade aberta presumida. Não se mapeou automaticamente este procedimento a uma das duas linhas do plano.
|
||||
- **Qualificação:**o anúncio específico pede licença para o serviço,acreditação/credenciação para calibração,três anos de experiência,três referências e equipa qualificada. Isso esclarece aquela contratação;não se converte em condição para preparar a nova oportunidade nem em requisito universal para todo apoio logístico/metrológico futuro. A execução técnica de calibração deve corresponder à competência/âmbito e aos requisitos efectivos do serviço a prestar.
|
||||
- **Possível prestação laboratorial:**a ficha pública IPAC`M0100`,INNOQ–Laboratório de Metrologia,Maputo,anexo17/02/2026,publica capacidades por âmbito:inclui electricidade,pesagem e pressão com gamas,incertezas e condições de local. Fonte`https://www.ipac.pt/pesquisa/ficha_lac.asp?ID=M0100`,consultada27/10/2026. É uma entidade a consultar sobre serviços,sem acordo ou capacidade disponível confirmados. Não se estende a cobertura a todas as famílias da HCB ou a uma instalação no Songo. Os prestadores históricos locais continuam por verificar.
|
||||
|
||||
A consulta pública dirigida não localizou prova identificável de adjudicação/execução ou compromisso para2027. Isso não prova que não houve contrato,que a compra continua aberta ou que existe procura por satisfazer. Rótulos“Em Curso” e campos0,00dos agregadores não são preço,volume ou estado confirmado. Não prolongar a mesma pesquisa sem novo documento ou resposta do cliente. O estado da compra passada é contexto para a procura futura,não o produto a gerir.
|
||||
|
||||
### Preparação da oportunidade e condição de retoma
|
||||
|
||||
| Questão de negócio | Informação concreta a obter e uso |
|
||||
| --- | --- |
|
||||
| Problema do cliente e recorrência | Que problema operacional existe no ciclo dos instrumentos,como é resolvido hoje e que necessidade futura permanece? Identificar instrumentos,quantidades,frequências e horizonte. Compra satisfeita pode cobrir só um ciclo;não autoriza presumir recorrência. |
|
||||
| Âmbito da prestação | Por família/modelo/gama,pontos e incerteza:que trabalho é exigido,onde pode ocorrer e com que prazo? Separar inventário/logística/documentação local da execução técnica da calibração. |
|
||||
| Parceiros e recursos | Confirmar capacidade real,disponibilidade e interesse dos prestadores locais e de laboratório(s). Corresponder âmbito a instrumentos concretos,com responsabilidades,custódia,segurança e condições comerciais;nenhum parceiro é designado automaticamente. |
|
||||
| Valor e receitas | Testar menor custo total,menos tempo fora de serviço ou melhor organização/rastreabilidade,sem os declarar como benefícios já medidos. Serviço por lote ou avença são hipóteses de receita,sem preço ou vontade de pagar conhecidos. |
|
||||
| Vantagem económica | Comparar solução actual e proposta para o mesmo âmbito,volume,qualidade,local e período:serviço laboratorial,transporte/retorno,embalagem/seguro,apoio local e custos incrementais sem duplicação. Medir prazos separadamente;monetizar impacto operacional só com base fornecida. Valores e vantagem permanecem indeterminados. |
|
||||
|
||||
**Resultados úteis previstos pelo responsável:**(1)procura recorrente/problema/interesse demonstrados→corresponder parceiros e dimensionar o serviço;(2)ciclo actual satisfeito,necessidade futura documentada→reformular horizonte;(3)cliente confirma necessidade satisfeita e sem necessidade futura para a solução→arquivar a hipótese com essa conclusão e conservar o dossier;(4)informação insuficiente→manter hipótese privada,sem declarar ausência de procura. Nenhum desses estados impede a entrega técnica do percurso proactivo.
|
||||
|
||||
Perguntas de descoberta e comparação foram preparadas,sem envio a terceiros. A ficha mantém`hypothesis`/`draft`,sem publicação. O contexto foi actualizado pelo mecanismo existente de prévia/confirmação e recuperado com os sete fundamentos;relatório existente reproduz as novas linhas. Sem alteração de código da aplicação,migração,novas entidades ou repetição das provas técnicas/fiscais aceites. Apenas a própria ficha e o seu dossier mudaram;52outrasfichas,17outrosdossiers,19projectos,1921territórios,12sectores,63documentos e históricos anteriores preservados.
|
||||
|
||||
Recibo:`docs/investmoz/unification/proactive-opportunity-model-qa-20261027.json`;análise privada actual:`outputs/proactive-commercial-followup-20261027/opportunity-private-brief.html`. A versão anterior da prova continua conservada. Esta passagem consolida o modelo da oportunidade e o saldo de validação comercial;não instala ou publica uma oportunidade real.
|
||||
|
||||
## 27/10/2026 — hipótese regional: outros clientes e sustentabilidade do apoio metrológico
|
||||
|
||||
**Pedido do responsável:** estudar outros clientes regionais,frequência,custos e capacidade dos parceiros,sem transformar sinais de procura em gestão de concursos. **Dado comercial expresso:** “Ainda não há dados comerciais”. A ficha permanece privada e a entrega técnica do percurso continua independente desta validação. Mantém-se`1afab4a2`como candidata técnica aceite,runtime`3439f350`,sem instalação nesta passagem. L8`14360748`eSGF TEMPO preservados.
|
||||
|
||||
**Resultado delimitado:** há base documental para prospectar três entidades adicionais — Vulcan/Moatize,EDM/Tete–Moatize e Nacala Logistics/segmentoMoatize — mas não há procura,recorrência,preço ou capacidade disponível confirmados para este serviço. Não se afirmou sustentabilidade,mercado dimensionado ou clientes contratados. A mesma ficha401e o dossier`894343c7-c33d-452e-a6a5-b6675f77ee23`foram actualizados da versão/contexto2para3,com11evidências. Origem Cahora Bassa/Energia,localização canónica,título e campos deliberados do dossier conservados;abrangência comercial regional identificada separadamente.
|
||||
|
||||
| Prospecto | Facto e fonte usados | Hipótese comercial e limite |
|
||||
| --- | --- | --- |
|
||||
| Vulcan Mozambique/Moatize | A própria empresa descreve mina,processamento de carvão e equipamentos produtivos em`https://www.vulcaninternational.com/products-services/`,consultado27/10/2026,página sem data editorial identificada. | Verificar instrumentos de processo/manutenção e necessidade de apoio metrológico. Não foi recebido pedido nem inventário;capacidade de produção da mina não é volume de calibração. |
|
||||
| EDM/Tete–Moatize | **Plano de Actividades e Orçamento2025**,PDFp68/página impressa68,Direcção de Transporte:linha3,calibração/reparação de equipamentos de teste;linha7,activos deMoatize/móvelTete;linha17,automaçãoSETete. Fonte`https://cdn.edm.co.mz/website/imprensa/Plano_Actividades_Orcamento_2025.pdf`,86páginas;conferidos visualmente apenas a página68e o detalhe relevante. Hash/cópia privada no recibo. | Serviço de calibração planeado a nível empresarial em2025 e referências regionais não demonstram parcela de procura actual emTete. Identificar unidade compradora,inventário e solução actual. O orçamento não é preço unitário,receita ou mercado regional. Não atribuir activosHCBàEDM ou contá-los duas vezes. |
|
||||
| Nacala Logistics/Moatize | A empresa descreve operação ferroviária atéMoatize e manutenção preventiva em`https://www.nacalalogistics.com/quem-somos/`e`https://www.nacalalogistics.com/faq/`,consultados27/10/2026. Na secção Accionistas,as concessionárias identificam Vulcan Mozambique como accionista. | Verificar instrumentos de manutenção e entidade/centro de compra. A marca agrega concessionárias;não equivale a uma contraparte contratual única. A ligação comVulcan impede assumir diversificação independente;não se somaram volumes ou clientes confirmados. |
|
||||
| Mphanda Nkuwa/GMNK — futuro separado | Descrição institucional em`https://www.gmnk.co.mz/en/about-us/project-description/`,consultada27/10/2026,qualifica o projecto em desenvolvimento. | Sem entrada na procura recorrente de base,receita ou carga de trabalho actual. Retomar apenas com necessidade e horizonte concretos;não inferir encomenda da capacidade projectada ou localização. |
|
||||
|
||||
As páginas institucionais confirmam apenas os factos no seu âmbito;relevância metrológica de mineração/ferrovia e interesse em apoio associado são inferências a testar,identificadas como tal. Fontes,exemplar,data e hashes foram guardados em provas privadas;nenhuma empresa,lista,documento ou relação canónica foi importado/publicado. As referências históricas de parceiros locais e o âmbitoIPAC/INNOQjá demonstrado foram reutilizados,sem repetir a pesquisa nem alargar automaticamente a cobertura técnica.
|
||||
|
||||
### Dados mínimos por cliente e parceiro
|
||||
|
||||
Por **cliente/centro de compra**:instrumentos,famílias/modelos/gamas,pontos e critério de aceitação;quantidade por janela e programa efectivo;prazo fora de serviço;prestador,processo e custo actuais;necessidade ainda não satisfeita;interesse e condições de pagar por lote/missão ou avença. Frequência permanece indeterminada e deve vir do programa do proprietário;sem regra anual por defeito,sem converter prazo de anúncio ou quinze famílias em quantidade/recorrência.
|
||||
|
||||
Por **parceiro**:âmbito de competência e local permitido por instrumento;capacidade efectivamente disponível em cada janela,equipa,meios,prazo e preço. Verificar capacidade actual dos prestadores locais históricos,sem confundir reparação/CAEcom acreditação de calibração. O âmbito publicado doINNOQ–LMemMaputo é pista parcial,não reserva de capacidade nem cobertura de todas as famílias. Famílias não correspondidas continuam separadas das compatíveis.
|
||||
|
||||
### Comparação económica delimitada
|
||||
|
||||
A unidade de comparação é a **missão/lote**:mesmo âmbito,quantidade,qualidade,local e período que a solução actual. A contribuição da missão é a receita acordada menos laboratório,apoio directo,transporte de ida/retorno,embalagem/seguro e outros custos incrementais dessa missão. Custos de transporte partilhado entram uma vez;custos fixos incrementais são deduzidos uma vez no período,sem os duplicar também na contribuição. Para sustentabilidade,avaliar ainda investimento,reposição de meios,fundo de maneio e prazos de recebimento;resultado operacional isolado não basta.
|
||||
|
||||
Comparar atendimento individual noSongo,missões agrupadas Songo–Tete/Moatize com janelas compatíveis e uma organização de apoio emTete/Moatize com deslocação aoSongo. Essas alternativas são hipóteses de funcionamento,não mudança de localização,cotação de rota ou recomendação de investimento já aprovada. Nenhum quilómetro,custo de deslocação,preço,volume,receita,margem,poupança ou ponto de equilíbrio foi inventado. A agregação pode partilhar logística e também criar custos,prazos ou restrições de custódia;isso tem de ser medido.
|
||||
|
||||
**Condição de retoma:** obter inventários/programas e interesse dos prospectos;identificar entidade compradora e concentraçãoVulcan/Nacala;com o mesmo âmbito pedir propostas de laboratório,apoio local e transporte;comparar as alternativas e a solução actual. Sem esses dados,o resultado útil é “carteira regional prospectável,sustentabilidade por demonstrar”. Se os dados posteriores mostrarem procura insuficiente ou serviço já satisfatório,conservar essa conclusão e reformular/arquivar a hipótese. Não repetir pesquisa pública para substituir dados comerciais que o responsável confirmou ainda não existirem. Nenhuma mensagem foi enviada a terceiros.
|
||||
|
||||
**Preservação e prova desta evolução:**guardar→prévia/confirmação do contexto→recuperação no mesmo dossier→linhas do relatório existente,com11evidências e valores comerciais em falta. Apenas ficha401e o seu dossier foram actualizados;52outrasfichas,17outrosdossiers,19projectos,1921territórios,12sectores,63documentos e391eventos anteriores de auditoria intactos. Sem nova entidade,grant,migração,código da aplicação ou ronda das provas técnicas/fiscais aceites. Fonte e contexto anteriores conservados,sem publicar a ficha.
|
||||
|
||||
Recibo:`docs/investmoz/unification/proactive-regional-clients-qa-20261027.json`;estudo privado:`outputs/proactive-regional-clients-20261027/regional-private-brief.html`. A entrega técnica e a eventual instalação continuam separadas do estado comercial desta oportunidade.
|
||||
|
||||
|
||||
## 27/10/2026 — passagem à prospecção e segundo piloto territorial privado
|
||||
|
||||
**Decisão do responsável:** o caso de apoio metrológico está suficientemente estruturado para prospecção. Fica privado e pendente de informação externa; não continuar a aprofundá-lo para concluir a funcionalidade. Nenhum contacto ou proposta comercial foi recebido ou enviado nesta passagem. A ficha401 e o dossier `894343c7-c33d-452e-a6a5-b6675f77ee23` mantêm fonte/contexto3, sem alterações.
|
||||
|
||||
**Ficha curta para a equipa:** `docs/investmoz/unification/prospeccao-apoio-metrologico-20261027.pdf`, PDF preenchível de duas páginas e42campos, com uma página por cliente e outra por parceiro. Cliente: instrumentos/gamas/quantidades, programa efectivo e janelas, requisitos, solução actual, contratação e próxima acção. Parceiro: âmbito, equipa/meios e capacidade disponível, prazo, preços discriminados, impostos/moeda, deslocações/custódia e validade da proposta. Sem resposta, os dados ficam por determinar. Guardar uma cópia por entidade/centro de compra ou parceiro, com evidência/data e responsável.
|
||||
|
||||
**Retoma da viabilidade do Songo:** quando chegarem inventários, programas, interesse e cotações comparáveis, actualizar a comparação já preparada para o mesmo âmbito, volume, qualidade, local e período. Distinguir entidade, utilizador e centro que decide/paga; a ligação Vulcan/Nacala impede presumir compradores independentes. Somar cada missão/transporte partilhado uma vez. Não usar ausência de resposta como ausência de procura ou zero. Necessidade satisfeita pode conduzir a reformulação futura ou arquivo fundamentado, preservando o dossier.
|
||||
|
||||
**Próximo piloto — Gurué:** foi criado, por serviços existentes e apenas na base QA isolada, o caso `GUR-CHA-20261027`, ficha402/fonte1 e dossier `883c8ec3-59a3-4074-b91c-b7d4a5d88ff0`/contexto1. Ideia privada: estudar apoio associado à colheita, qualidade da folha verde e organização das entregas na cadeia do chá. Reutilizados o distrito canónico de Gurué e o sector Agronegócio; nenhum novo mestre, promotor empresarial, montante ou coordenada presumidos.
|
||||
|
||||
Cinco referências distinguem actividade de procura: INE2020–2024, edição2025, PDFp9/Quadro1.1; página do próprio Asian Tea Group sobre Chá de Magoma; IGC2014, PDFp75,78–79/impressas60,63–64; e referências privadas da lista já fornecida, com datas2021–2023 e códigos declarados. INE e produtor documentam actividades; o estudo2014 é histórico e orienta perguntas, sem transportar volumes, preços, capacidades ou intenções para2026. Cadastros antigos não comprovam competência ou disponibilidade actual. Não se presume compra de folha externa, oferta em falta, nova fábrica ou interesse em contratar.
|
||||
|
||||
**Acção delimitada do Gurué:** compreender como se colhe, avalia e entrega hoje; identificar problema mensurável, intervenientes, critérios do processador, quantidades/janelas, solução/custo actuais e quem contrataria/pagaria pelo apoio. Magoma é unidade potencial a consultar; Chazeiras é referência histórica cuja situação actual deve ser confirmada. Beneficiário não equivale a pagador. Necessidade, parceiros, custos e viabilidade permanecem em hipótese, sem bloquear a funcionalidade técnica ou exigir prolongamento de pesquisa pública.
|
||||
|
||||
**Demonstração apenas do delta:** criação→gravação→prévia/confirmação→recuperação→linhas do relatório existente, com5evidências e pressupostos visíveis. Conservados todos os53registos anteriores de oportunidades,18dossiers,19projectos,1921territórios,12sectores,63documentos,394eventos de auditoria,40utilizadores e3organizações. Novos apenas a ficha/dossier/percurso QA e respectivos registos de histórico. Sem alteração de código, schema, permissões ou provas técnicas/fiscais aceites. O formulário foi reaberto e ensaiado com valores sintéticos numa cópia; a versão para a equipa está em branco, com campos interactivos verificados e as duas páginas revistas visualmente.
|
||||
|
||||
**Entrega técnica independente:** `1afab4a2` continua candidata técnica aceite, runtime `3439f350`, sem instalação ou publicação nesta passagem. A capacidade do servidor deve ser novamente medida no procedimento da futura entrega; não se declarou resolvida nem se apagou conteúdo. L8 `14360748`, SGF TEMPO e demais provas preservados. Esta passagem não envia a ficha a terceiros nem publica oportunidades reais.
|
||||
|
||||
Recibo: `docs/investmoz/unification/proactive-handoff-gurue-qa-20261027.json`. Prova privada e nota do piloto: `outputs/proactive-handoff-gurue-20261027/gurue-proof.json` e `gurue-private-brief.html`. Saldo do Songo: recolha externa; saldo do Gurué: descoberta dirigida da necessidade; saldo da instalação: capacidade e procedimento de entrega. Estes três estados permanecem independentes.
|
||||
|
||||
|
||||
## 27/10/2026 — autonomia pela interface e candidata técnica consolidada
|
||||
|
||||
**Âmbito pedido:** reutilizar as provas aceites; demonstrar apenas anexar respostas, rever a ideia privada e encaminhar/actualizar o mesmo dossier pela interface, sem intervenção de código ou SQL na operação da equipa. Songo aguarda respostas externas e Gurué mantém a hipótese agrícola privada; ambos ficaram intactos. Não foram recolhidas respostas comerciais reais nem observada uma sessão de formação com funcionários.
|
||||
|
||||
### Guia curto da equipa
|
||||
|
||||
1. Entrar com o perfil operacional já autorizado e o MFA normal. Em **Minhas oportunidades → Nova oportunidade → Preparar análise e ideia**, indicar título, sector e apenas o território conhecido. Não substituir o promotor real por quem prepara a análise; a preparação interna permite que ainda seja desconhecido.
|
||||
2. Em **Evidências e proveniência**, separar facto e interpretação, identificar fonte/exemplar, trecho, período, abrangência e limitações. Manter **Interna — análise privada**. Guardar o rascunho e aguardar a confirmação do servidor.
|
||||
3. Para uma resposta recebida, abrir **Imagens, documentos e localizações → Documentos**, escolher o original, identificar emissor/versão/data quando conhecidos, página e afirmação fundamentada. Escolher classificação e consulta internas e **Guardar recurso**. O ficheiro fica privado e o seu estado de scan é visível; o download só fica disponível após scan limpo dos mesmos bytes.
|
||||
4. Regressar ao rascunho e escolher esse ficheiro em **Documento existente associado** na evidência correspondente. Rever a oferta/procura observadas, solução, pressupostos, pendências e próxima acção. Uma resposta parcial não confirma procura, preços ou sustentabilidade. Guardar e recuperar a ficha para conferir os dados.
|
||||
5. Usar **Preparar ou continuar investimento com esta ficha**. Se já existir, escolher o dossier e **Preparar neste dossier**; não criar outro para uma nova edição. Criar um dossier apenas para um investimento novo, com o título escolhido e consentimento de reutilização do próprio perfil.
|
||||
6. Confirmar a localização, usar **Rever dados antes de guardar**, conferir divergências e impactos e **Guardar dados do investimento**. O título e as edições deliberadas conservam-se. A referência à resposta acompanha a análise; o original permanece no gestor documental da ficha, acessível pelo link da ficha de origem e seus recursos, sem cópia ou divulgação automática dos bytes.
|
||||
7. Para novas respostas/edições, voltar à mesma ficha, guardar a revisão e continuar o mesmo dossier com nova prévia/confirmação. O dossier recebe a versão actual após confirmação; o estado anterior conserva-se no histórico. Informação em falta continua por determinar, sem zero presumido.
|
||||
8. **Divulgação promocional** é uma acção separada. Nada neste percurso publica o piloto, os anexos ou o dossier. A eventual decisão de publicação real continua independente da demonstração sintética e da instalação técnica.
|
||||
|
||||
### Delta demonstrado e correcção delimitada
|
||||
|
||||
Ensaio com o operador QA existente, login/MFA normais e apenas controlos da interface: nova ficha sintética403, resposta PDF de ensaio anexada e recuperada, ClamAV real limpo, hash do download igual ao original; documento associado à evidência; ideia revista; dossier `5bc28554-a2d1-4e60-9181-93ba0ecede59` criado e depois continuado sem duplicação. Fonte4/contexto2, hipótese e título deliberado preservados. O anexo e os dados são sintéticos; não constituem resposta de clientes ou parceiros reais.
|
||||
|
||||
Foi reproduzido e corrigido um aviso enganador: o pedido de complementos públicos tratava uma análise privada autorizada como referência pública desaparecida. **InvestmentComplements** consulta primeiro a autorização existente e devolve uma lista vazia para essa preparação privada; não a transforma em oferta pública. Origens públicas continuam a produzir os seus complementos; pedidos sem acesso continuam sem obter a fonte privada. Dois testes novos dirigidos,18asserções, passaram em transacção QA. A demonstração privada foi retomada sem o aviso. Não se alteraram permissões, tabelas, frontend ou motores fiscais.
|
||||
|
||||
Todos os54registos anteriores de oportunidades,19dossiers,63documentos,19projectos,1921territórios,12sectores,3organizações e399eventos de auditoria preservados por comparação de hashes. Novos apenas a amostra QA e seus registos. As provas anteriores de criação/edição, publicação expressa, anonimato, histórico, relatório, Wayfinder, TypeScript e build foram reutilizadas; não se repetiram suites fiscais ou a análise económica dos pilotos. Foi conferida a recuperação da referência documental e das novas linhas pelo relatório existente.
|
||||
|
||||
### Candidata para instalação futura
|
||||
|
||||
Runtime desta correcção: `51d536b7`; inclui o percurso técnico `3439f350`/candidata aceite `1afab4a2`, documentação e ficha de prospecção `403c444a`. A comparação com main remoto `f8d57bdd` confirmou ancestralidade, sem alterações entretanto integradas a perder. O delta de runtime face à candidata anterior limita-se à consulta de complementos; frontend, schema e configuração mantêm-se.
|
||||
|
||||
**Não instalado.** Antes da entrega activa, medir novamente espaço/inodes na partição do instalador e dos backups, confrontar com a necessidade efectiva de compilação isolada/backup, conferir o main então actual, executar backup/restauro fresco e manter a versão activa até a nova estar pronta. Depois conferir revisão servida e apenas o delta. A preparação dos pilotos QA não integra dados na base activa nem publica oportunidades. L8 `14360748` permanece separado; SGF TEMPO intocado. Não se fizeram SSH, limpeza, backup ou instalação nesta passagem.
|
||||
|
||||
Recibo: `docs/investmoz/unification/proactive-team-autonomy-qa-20261027.json`. Provas e pacote local: `outputs/proactive-team-autonomy-20261027/`. A verificação comprova que o percurso está disponível aos perfis autorizados através da interface; não declara formação da equipa, viabilidade dos pilotos ou conclusão integral dos requisitos nacionais.
|
||||
|
||||
|
||||
## 27/10/2026 — duas entregas autorizadas: L8 primeiro, percurso proactivo depois
|
||||
|
||||
O responsável autorizou expressamente a execução das duas entregas pelo procedimento existente, sem nova ronda de autorização. A indicação histórica de manter preparado em `c85e772d` foi reconciliada: o commit acrescenta documentação de capacidade, sem mudar o código de L8 `14360748`/runtime `11a6cee9`. A autorização actual permite retomar; não substitui a medição de capacidade nem o backup/restauro frescos.
|
||||
|
||||
**Etapa1:** L8 em `c85e772d`, com a colecta válida, retenções efectivamente sofridas e PPC comprovados no recorte aceite; PEC e créditos próprios continuam separados. **Etapa2:** ramo `codex/sequential-delivery-20261027`, merge de L8 e do percurso proactivo `0ff402a1`, runtime reconciliado `74f7f93a`. A etapa2 só segue após confirmar a revisão efectivamente servida na etapa1.
|
||||
|
||||
O relatório comum tinha um conflito de imports. Foram conservados ambos e as chamadas de linhas anuais e proactivas. Os restantes ficheiros de runtime de cada candidata ficaram idênticos à origem. Verificação apenas da integração partilhada:6linhas anuais e10linhas proactivas recuperadas, entradas intactas e sem inferência cruzada. TypeScript e compilação QA isolada passaram; suites económicas/fiscais aceites não repetidas. Documentação de ambas as linhas conservada, sem importação de fixtures ou escrita em bases.
|
||||
|
||||
**Estado efectivo desta passagem: preparado, sem instalação.** O main remoto permanece `f8d57bdd` e a revisão pública servida foi conferida por HTTP em27/10/2026,10:14UTC, também `f8d57bdd`. A ponte SSH local estava `closed`; a autenticação por chave foi recusada com a chave do servidor registada e conferida. Não havia aqui uma sessão autenticada utilizável. Não foram executados backup/restauro frescos, alteração de main ou instalação. A capacidade antiga de4,10GiB é histórica e não foi apresentada como medição actual.
|
||||
|
||||
Retomar na sessão local com SSH autenticado, usando a autorização já registada: medir espaço/inodes na partição efectiva, comparar com compilação e backup, conferir main e revisão activa, criar e ensaiar backup fresco, instalar L8 e conferir apenas o seu delta. Depois repetir as guardas necessárias para a candidata conjunta e conferir o delta proactivo preservando L8. Manter a versão activa até a nova estar pronta. Excluir fixtures QA dos inputs de instalação; não executar seeders/importações de amostras, não publicar pilotos privados nem usar o pacote QA como cópia da base activa. SGF TEMPO separado.
|
||||
|
||||
Recibo de preparação: `docs/investmoz/unification/sequential-delivery-preparation-20261027.json`. Provas e instrução de passagem: `outputs/sequential-delivery-20261027/`. Os recibos de execução e as duas revisões servidas serão registados apenas depois de execução real na sessão autenticada; este recibo não os substitui.
|
||||
|
||||
|
||||
## 27/10/2026 — L8 e percurso proactivo instalados pela sequência autorizada
|
||||
|
||||
Entrega1: **L8 `c85e772d`**, anterior `f8d57bdd`. Entrega2, apenas após conferir a primeira: **percurso proactivo `9fda6d6e`**, incluindo `56c0c6a7` e preservando L8. As duas revisões foram conferidas no registo do instalador e no recurso público `/build/revision.json`, com hash do manifest e marcadores compilados dos deltas. `c85e772d` conserva o código aceite de `14360748`; o merge proactivo mantém ambos os fornecedores de linhas do relatório. A referência final servida passa a `9fda6d6e`.
|
||||
|
||||
A tentativa proactiva em `56c0c6a7` não foi activada: um teste dependia de um ficheiro de outputs existente apenas no QA local. L8 permaneceu em serviço. A correcção `9fda6d6e` torna esse teste portátil com um exemplar mínimo sintético da projecção pública da API, sem perfis, credenciais ou pilotos reais e sem escrita em outputs. O teste dirigido passou; o código da aplicação é byte a byte idêntico a `56c0c6a7`. Não se transportou a base QA nem se saltou a guarda do instalador. A nova tentativa usou o backup/restauro ainda fresco, com capacidade e fonte activa novamente conferidas.
|
||||
|
||||
A ligação SSH foi restabelecida pelo responsável na janela local, sem credenciais na conversa ou nos recibos. A medição inicial encontrou91,6GiB livres e inodes suficientes; a capacidade foi novamente conferida depois de cada backup. Instalador existente e suas guardas preservados; a versão anterior permaneceu activa até a nova release estar pronta. Os controlos automáticos do instalador foram mantidos, sem nova ronda manual das provas funcionais/económicas aceites.
|
||||
|
||||
**Backup/restauro fresco em cada etapa:** `/var/backups/investmoz-sequential-20261027/l8/backup` e `/var/backups/investmoz-sequential-20261027/proactive/backup`. Em cada uma, dump consistente e369ficheiros persistentes/configuração verificados; restauro das174tabelas num contentor sem rede, porta55441, com contagens/checksums iguais. Recibos `backup-receipt.json`, `restore-receipt.json`, `schema-permissions-before.json`, `schema-permissions-after.json`, `preservation-receipt.json` e `operational-delta-receipt.json` conservados nesses directórios. Hashes exactos no recibo consolidado.
|
||||
|
||||
**Preservação demonstrada:**172tabelas de negócio intactas em cada comparação; apenas cache/sessões operacionais reconciliados individualmente por identidade/timeouts e pedidos públicos de entrega. Schema, papéis, grants, permissões e originais persistentes conservados. Fontes instaladas comparadas aos commits:996ficheiros após L8 e1000após o proactivo. Sem migrations na base activa, importação de amostras QA, seeders ou publicação dos pilotos. O instalador manteve base e storage sintéticos isolados; o storage QA fica fora da árvore servida, e a release usa os mesmos `.env` e storage persistentes por ligação.
|
||||
|
||||
**Âmbito:** L8 continua parcial, com PEC e créditos de regra própria separados; os resultados continuam simulações. Songo permanece privado e pendente de respostas externas; Gurué continua hipótese agrícola privada. Disponibilização técnica não confirma clientes, procura, sustentabilidade ou publicação comercial. L3, ISPC, câmbio, L6/L7 e SGF TEMPO preservados.
|
||||
|
||||
Recibo consolidado: `docs/investmoz/unification/sequential-delivery-installed-20261027.json`. Provas locais: `outputs/l8-proactive-install-20261027/`. Os recibos históricos de preparação/suspensão mantêm-se como histórico e deixam de representar pendência de instalação destas duas candidatas.
|
||||
|
||||
Recibo remoto consolidado: `/var/backups/investmoz-sequential-20261027/installed-receipt.json`;SHA256 `62584b5abb50a05303a24379a0563e8dc147e25e682dc3566bb8edf015ba9d0b`. A fixture sintética portátil é apenas input de teste, sem importação na aplicação e sem dados dos pilotos.
|
||||
|
||||
|
||||
## 27/10/2026 — avaliação de utilização pela equipa, sem Codex
|
||||
|
||||
**Estado:** roteiro preparado; execução real pela equipa e resultados ainda por observar. O recibo da instalação mantém `9fda6d6e` como referência entregue, incluindo L8 e o percurso proactivo. As provas técnicas aceites mantêm-se válidas. Este exercício avalia utilização e clareza; não constitui outra instalação, ronda de testes técnicos ou nova aprovação obrigatória da entrega.
|
||||
|
||||
### Exercício para a equipa
|
||||
|
||||
Usar a própria conta e o perfil operacional já autorizado no [portal](https://teste-investidor.tempo.co.mz/), pela interface normal. Escolher uma análise privada de trabalho sobre um tema real, com uma fonte já disponível e autorizada. Preservar Songo e Gurué, que aguardam informação comercial; não é necessário obter novas respostas externas para fazer este exercício. Não usar contas ou amostras QA na aplicação activa. O guia de botões existente em «Guia curto da equipa» pode ser consultado; registar essa consulta para distinguir clareza da interface de apoio documental.
|
||||
|
||||
1. **Preparar a análise.** Escolher sector e território existentes, identificar o assunto e guardar como preparação privada, usando apenas a informação conhecida.
|
||||
2. **Registar evidências.** Identificar fonte/exemplar, trecho, período, abrangência e limitações. Separar facto documentado da interpretação. Associar um documento disponível quando aplicável; recuperar o original pelo gestor documental da ficha após o scan. A falta de resposta comercial permanece informação por confirmar.
|
||||
3. **Estruturar a ideia.** Descrever a solução complementar, quem poderá beneficiar, quem poderá contratar/pagar, condições, recursos e próxima acção. Manter hipótese onde a procura não esteja demonstrada; montante, frequência e preço desconhecidos não passam a zero.
|
||||
4. **Guardar e recuperar.** Sair da ficha e voltar a abri-la. Conferir que análise, evidências, documento associado e pendências são os que foram guardados, sem recorrer a scripts ou intervenção do Codex.
|
||||
5. **Levar ao dossier.** Usar a continuação do investimento pela ficha. Escolher o dossier existente quando for o mesmo investimento; criar outro apenas para um investimento novo. Rever a prévia, conservar o título deliberado e confirmar. Reabrir o dossier e localizar a ideia, a origem e as pendências; o original continua acessível pelos recursos da ficha de origem, sem cópia automática para o dossier.
|
||||
6. **Rever sem duplicar.** Actualizar uma pendência da própria análise com informação já conhecida e continuar o mesmo dossier. Conferir a nova versão após prévia/confirmação e a conservação da anterior. Guardar/confirmar não publica a análise, o anexo ou o dossier.
|
||||
|
||||
**O que observar:** se a pessoa encontra a próxima acção, compreende facto versus hipótese, consegue recuperar o que guardou e continuar o mesmo investimento sem ajuda do Codex. Anotar o que foi conseguido directamente, com o guia, com ajuda de outra pessoa, o que bloqueou e o que não foi tentado. Um impedimento concreto não obriga a repetir os passos já conseguidos; podem continuar os passos independentes.
|
||||
|
||||
### Devolução curta da avaliação
|
||||
|
||||
Registar por participante, sem enviar palavras-passe ou documentos privados nesta conversa: data e perfil utilizado; referências internas da análise e do dossier; passos conseguidos e tipo de apoio consultado; passo/campo onde surgiu dificuldade; mensagem exacta ou descrição do comportamento; resultado esperado. Distinguir acesso/perfil, linguagem/descoberta de acções, compreensão dos dados e perda ou erro de gravação/recuperação. Duração e sugestões são opcionais. Os identificadores só são partilhados no canal interno autorizado.
|
||||
|
||||
O coordenador devolve estes resultados pelo canal habitual da equipa. A avaliação só será marcada como observada depois dessa execução real; preparar o roteiro ou uma demonstração pelo Codex não a substitui. Nesta passagem não houve participante observado, análise criada no portal, alteração de conta/permissões, mensagem enviada à equipa ou publicação. As correcções seguintes serão delimitadas pelos obstáculos efectivamente relatados, sem reabrir provas aceites.
|
||||
|
||||
**Âmbitos preservados:** Songo e Gurué privados e pendentes de evidências comerciais. L8 permanece parcial; PEC e créditos com regras próprias continuam separados e não fazem parte deste exercício de utilização. O resultado técnico entregue não declara o IRPC completo nem valida comercialmente os pilotos.
|
||||
|
||||
Registo de preparação e resultados ainda em aberto: `docs/investmoz/unification/proactive-team-use-evaluation-20261027.json`. Não é um recibo de execução pela equipa.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -17,6 +17,7 @@ export const modalityLabels: Record<string, string> = {
|
||||
type Values = Record<string, string | boolean | number[]>;
|
||||
const labels: Record<string, string> = {
|
||||
q: 'O que procura',
|
||||
perspective: 'Consultar por',
|
||||
sector: 'Sector',
|
||||
category: 'Modalidade da oportunidade',
|
||||
preparation: 'Estado de preparação',
|
||||
@@ -215,6 +216,7 @@ export default function OpportunitySearchFilters({
|
||||
onChange={(e) => change({ q: e.target.value })}
|
||||
/>
|
||||
</Field>
|
||||
{select('perspective', [{value:'exists',label:'O que existe'},{value:'needs',label:'Necessidades identificadas'},{value:'ideas',label:'Ideias de investimento'},{value:'opportunities',label:'Oportunidades cadastradas — disponibilidade na ficha'}])}
|
||||
{select('sector', choicesFor('sector'))}
|
||||
{select('category', choicesFor('category'))}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import { createOperationKey } from '@/lib/operation-key';
|
||||
import { Field, control, button } from '@/pages/management/shared';
|
||||
|
||||
export type ProactiveEvidence = {id:string;category:string;purpose:'local'|'methodology';statement:string;interpretation:string;source:string;locator:string;period:string;scope:string;coverage:string;verified_on:string;access:'internal'|'public';document_id:string};
|
||||
export type ProactiveAnalysis = {
|
||||
version:1;kind:'exists'|'needs'|'ideas';evidence:ProactiveEvidence[];
|
||||
need:{state:'hypothesis'|'confirmed';problem:string;observed_supply:string;observed_demand:string;type:string;clients:string;evidence_ids:string[];limitations:string;missing:string;confirmation:string};
|
||||
idea:{solution:string;activity:string;chain_id:string;stage:string;coverage:string;mode:string;resources:string;assumptions:string;conditions:string;pending:string;next_action:string};
|
||||
relations:{id:string;kind:string;target_id:string;relation:string;reference:string;evidence_ids:string[]}[];
|
||||
};
|
||||
export type ProactiveOptions = {documents?:{id:string;title:string}[];groups:Record<string,string>;references:Record<string,{id:string;name:string}[]>};
|
||||
export type ProactivePublic = {version?:number;group:string;state:string;need:string;proposal:string;basis:string;limitations:string;next_action:string;evidence_ids:string[];chain_id?:string|null;stage?:string|null;notice?:string;resources?:string;assumptions?:string;conditions?:string;relation_ids?:string[];relations?:{kind:string;target_id:string;label:string;relationship:string;basis:string}[];evidence?:Partial<ProactiveEvidence>[]};
|
||||
export const proactiveNotice = 'Ausência de registo não comprova ausência de oferta. Proximidade não comprova contrato, participação, energia acessível, terra disponível ou benefício fiscal. Necessidade confirmada não comprova viabilidade comercial; hipótese de fornecimento não é encomenda.';
|
||||
export const newProactive = ():ProactiveAnalysis => ({version:1,kind:'ideas',evidence:[],need:{state:'hypothesis',problem:'',observed_supply:'',observed_demand:'',type:'',clients:'',evidence_ids:[],limitations:'',missing:'',confirmation:''},idea:{solution:'',activity:'',chain_id:'',stage:'',coverage:'',mode:'',resources:'',assumptions:'',conditions:'',pending:'',next_action:''},relations:[]});
|
||||
export const newPublicProactive = ():ProactivePublic => ({group:'ideas',state:'hypothesis',need:'',proposal:'',basis:'',limitations:'',next_action:'',evidence_ids:[],chain_id:'',stage:'',resources:'',assumptions:'',conditions:'',relation_ids:[]});
|
||||
|
||||
export function ProactiveInvestmentEditor({value,onChange,options,history=[]}:{value?:ProactiveAnalysis;onChange:(value:ProactiveAnalysis)=>void;options?:ProactiveOptions;history?:{version:number;at:string;state:string;problem:string;confirmation:string}[]}){
|
||||
if(!value)return <section className="rounded border p-4"><h2 className="font-semibold">Análise territorial e preparação de ideias</h2><p>Comece pelo território e sector existentes, mesmo sem oportunidade publicada, promotor, montante ou coordenadas. O rascunho e a publicação são independentes.</p><button type="button" className={button} onClick={()=>onChange(newProactive())}>Preparar análise e ideia</button></section>;
|
||||
const patch=(p:Partial<ProactiveAnalysis>)=>onChange({...value,...p});
|
||||
const text=(label:string,v:string,change:(v:string)=>void)=><Field label={label}><textarea className={control} aria-label={label} value={v??''} onChange={e=>change(e.target.value)}/></Field>;
|
||||
const select=(label:string,v:string,choices:Record<string,string>,change:(v:string)=>void)=><Field label={label}><select className={control} aria-label={label} value={v??''} onChange={e=>change(e.target.value)}><option value="">Por determinar</option>{Object.entries(choices).map(([key,label])=><option key={key} value={key}>{label}</option>)}</select></Field>;
|
||||
const evidenceChoice=(selected:string[],change:(v:string[])=>void)=><fieldset><legend>Evidências que fundamentam esta entrada</legend>{value.evidence.map((e,i)=><label key={e.id} className="block"><input type="checkbox" checked={selected.includes(e.id)} onChange={event=>change(event.target.checked?[...selected,e.id]:selected.filter(id=>id!==e.id))}/> Evidência {i+1}: {e.statement||'Por descrever'} ({e.access==='public'?'Pública autorizada':'Interna'})</label>)}</fieldset>;
|
||||
return <section className="space-y-4 rounded border p-4" aria-label="Análise territorial e ideia">
|
||||
<h2 className="text-xl font-semibold">Território e sector → evidências → necessidade → ideia</h2><details><summary>Como fundamentar esta análise</summary><p>Inventarie actividades, recursos, infra-estruturas e serviços de apoio. Confronte oferta observada com procura documentada e identifique os clientes ou beneficiários. Registe o período, cobertura e limitações de cada observação. Use referências internacionais para orientar as perguntas; a confirmação do caso depende de evidência local.</p></details><p>Reutiliza o sector e a localização principal escolhidos nesta ficha. Guarde pelo botão de rascunho existente. Nenhum montante, promotor ou ponto exacto é exigido.</p><p>{proactiveNotice}</p>
|
||||
{select('Tipo de conteúdo em preparação',value.kind,{exists:'O que existe',needs:'Necessidade identificada',ideas:'Ideia de investimento'},v=>patch({kind:v as ProactiveAnalysis['kind']}))}
|
||||
<fieldset className="space-y-3 rounded border p-3"><legend>Evidências e proveniência</legend><p>Registe factos e interpretações em campos separados. Listas de empresas, hotéis, restaurantes, contactos e documentos internos permanecem internos; não são copiados para a divulgação.</p>
|
||||
{value.evidence.map((e,i)=>{const change=(p:Partial<ProactiveEvidence>)=>patch({evidence:value.evidence.map(x=>x.id===e.id?{...x,...p}:x)});return <fieldset key={e.id} className="space-y-2 rounded border p-3"><legend>Evidência {i+1}</legend>
|
||||
{select(`Finalidade da evidência ${i+1}`,e.purpose??'',{local:'Evidência local do caso',methodology:'Referência metodológica — não prova procura local'},v=>change({purpose:v as 'local'|'methodology'}))}
|
||||
{select(`Categoria da evidência ${i+1}`,e.category,{activity:'Actividade',resource:'Recurso',infrastructure:'Infra-estrutura',supply:'Oferta',demand:'Procura'},v=>change({category:v}))}
|
||||
{([['statement','Facto documentado'],['interpretation','Interpretação ou hipótese'],['source','Fonte e exemplar'],['locator','Localizador ou trecho'],['period','Período da evidência'],['scope','Abrangência'],['coverage','Cobertura e limitações']]as const).map(([key,label])=><div key={key}>{text(`${label} ${i+1}`,e[key],v=>change({[key]:v}))}</div>)}
|
||||
<Field label={`Verificação ${i+1}`}><input aria-label={`Verificação ${i+1}`} className={control} type="date" value={e.verified_on??''} onChange={event=>change({verified_on:event.target.value})}/></Field>
|
||||
<Field label={`Documento existente associado ${i+1}`}><select aria-label={`Documento existente associado ${i+1}`} className={control} value={e.document_id??''} onChange={event=>change({document_id:event.target.value})}><option value="">Sem documento associado — indicar fonte e localizador</option>{options?.documents?.map(d=><option key={d.id} value={d.id}>{d.title}</option>)}</select></Field>
|
||||
{select(`Divulgação da evidência ${i+1}`,e.access,{internal:'Interna — análise privada',public:'Pública — origem e divulgação autorizadas'},v=>change({access:v as ProactiveEvidence['access']}))}
|
||||
<button type="button" className="underline" onClick={()=>patch({evidence:value.evidence.filter(x=>x.id!==e.id),need:{...value.need,evidence_ids:value.need.evidence_ids.filter(id=>id!==e.id)},relations:value.relations.map(r=>({...r,evidence_ids:r.evidence_ids.filter(id=>id!==e.id)}))})}>Retirar evidência {i+1} deste rascunho</button>
|
||||
</fieldset>;})}
|
||||
<button type="button" className={button} onClick={()=>patch({evidence:[...value.evidence,{id:createOperationKey(),category:'activity',purpose:'local',statement:'',interpretation:'',source:'',locator:'',period:'',scope:'',coverage:'',verified_on:'',access:'internal',document_id:''}]})}>Acrescentar evidência</button>
|
||||
</fieldset>
|
||||
{value.kind!=='exists'&&<fieldset className="space-y-3 rounded border p-3"><legend>Necessidade ou lacuna</legend>
|
||||
{select('Estado da necessidade',value.need.state,{hypothesis:'Hipótese analítica',confirmed:'Necessidade confirmada — fundamento documentado'},v=>patch({need:{...value.need,state:v as 'hypothesis'|'confirmed'}}))}
|
||||
{select('Tipo de lacuna',value.need.type,{quantity:'Quantidade',quality:'Qualidade',logistics:'Logística',processing:'Transformação',coordination:'Coordenação',support:'Serviços de apoio'},v=>patch({need:{...value.need,type:v}}))}
|
||||
{([['problem','Problema identificado'],['observed_supply','Oferta observada'],['observed_demand','Procura observada'],['clients','Potenciais clientes ou beneficiários'],['limitations','Limitações da necessidade'],['missing','Informação por confirmar'],['confirmation','Fundamentação do estado da necessidade']]as const).map(([key,label])=><div key={key}>{text(label,value.need[key],v=>patch({need:{...value.need,[key]:v}}))}</div>)}
|
||||
{evidenceChoice(value.need.evidence_ids,v=>patch({need:{...value.need,evidence_ids:v}}))}
|
||||
</fieldset>}
|
||||
{value.kind==='ideas'&&<fieldset className="space-y-3 rounded border p-3"><legend>Ideia em preparação</legend>
|
||||
{([['solution','Solução proposta'],['activity','Actividade proposta'],['stage','Etapa da cadeia de valor'],['coverage','Localização ou abrangência da ideia'],['resources','Recursos documentados'],['assumptions','Pressupostos explícitos'],['conditions','Condições da ideia'],['pending','Pendências da ideia'],['next_action','Próxima acção']]as const).map(([key,label])=><div key={key}>{text(label,value.idea[key],v=>patch({idea:{...value.idea,[key]:v}}))}</div>)}
|
||||
{select('Cadeia de valor existente',value.idea.chain_id,Object.fromEntries((options?.references.chain??[]).map(c=>[c.id,c.name])),v=>patch({idea:{...value.idea,chain_id:v}}))}
|
||||
{select('Possibilidade de investimento',value.idea.mode,{create:'Criar actividade',expand:'Expandir actividade',associate:'Associar actividades existentes'},v=>patch({idea:{...value.idea,mode:v}}))}
|
||||
</fieldset>}
|
||||
{value.kind!=='ideas'&&<p>Os campos anteriores da ideia são conservados. Escolha “Ideia de investimento” quando pretender preparar uma solução.</p>}
|
||||
<fieldset className="space-y-3 rounded border p-3"><legend>Relações com estruturas existentes</legend>
|
||||
{value.relations.map((r,i)=>{const change=(p:Partial<typeof r>)=>patch({relations:value.relations.map(x=>x.id===r.id?{...x,...p}:x)});return <fieldset key={r.id} className="rounded border p-3"><legend>Relação {i+1}</legend>
|
||||
{select(`Tipo de referência ${i+1}`,r.kind,{project:'Projecto âncora',cluster:'Cluster',corridor:'Corredor',park:'Parque',chain:'Cadeia de valor'},v=>change({kind:v,target_id:''}))}
|
||||
{select(`Referência existente ${i+1}`,r.target_id,Object.fromEntries((options?.references[r.kind]??[]).map(c=>[c.id,c.name])),v=>change({target_id:v}))}
|
||||
{select(`Fundamento da relação ${i+1}`,r.relation,{documented:'Documentada',hypothesis:'Hipótese de relação',proximity:'Proximidade, sem compromisso'},v=>change({relation:v}))}
|
||||
{text(`Fonte da relação ${i+1}`,r.reference,v=>change({reference:v}))}{evidenceChoice(r.evidence_ids,v=>change({evidence_ids:v}))}
|
||||
<button type="button" className="underline" onClick={()=>patch({relations:value.relations.filter(x=>x.id!==r.id)})}>Retirar relação {i+1}</button>
|
||||
</fieldset>;})}
|
||||
<button type="button" className={button} onClick={()=>patch({relations:[...value.relations,{id:createOperationKey(),kind:'project',target_id:'',relation:'hypothesis',reference:'',evidence_ids:[]}]})}>Relacionar referência existente</button>
|
||||
</fieldset>
|
||||
{!!history.length&&<details><summary>Histórico do fundamento da necessidade</summary>{history.map(h=><p key={h.version}>Versão {h.version} · {h.at} · {h.state==='confirmed'?'Necessidade confirmada':'Hipótese'}: {h.problem} — {h.confirmation||'Fundamentação por completar'}</p>)}</details>}
|
||||
<p>Não calcula mercado, investimento ou rentabilidade. Informação em falta permanece por determinar. Uma nova edição não altera os históricos nem publica a análise.</p>
|
||||
</section>;
|
||||
}
|
||||
|
||||
export function ProactiveSummary({value}:{value?:ProactivePublic|null}){
|
||||
if(!value)return null;
|
||||
return <section className="space-y-2 rounded border p-4" aria-label="Origem proactiva do investimento"><h2 className="text-xl font-semibold">{value.group==='ideas'?'Ideia em preparação':value.group==='needs'?'Necessidade identificada':'O que existe'}</h2><p>{value.group==='exists'?'Registo documental; consultar abrangência, cobertura e limitações das fontes.':value.state==='confirmed'?'Necessidade confirmada no âmbito documentado':'Hipótese analítica; conclusão económica por confirmar'}</p>{([['need','Necessidade'],['proposal','Proposta'],['basis','Fundamento'],['limitations','Limitações'],['next_action','Próximo passo'],['stage','Etapa da cadeia'],['resources','Recursos'],['assumptions','Pressupostos'],['conditions','Condições']]as const).map(([key,label])=>value[key]?<p key={key}><strong>{label}:</strong> {value[key]}</p>:null)}{value.relations?.map(r=><p key={r.kind+r.target_id}>Relação seleccionada: {r.label} · {r.relationship==='documented'?'Documentada':r.relationship==='proximity'?'Proximidade, sem pertença':'Hipótese de relação'}. Fundamento: {r.basis}. Não confirma contrato, acesso ou participação.</p>)}{value.evidence?.map((e,i)=><p key={e.id??i}>Evidência pública: {e.statement}; fonte: {e.source}; localizador: {e.locator}; período: {e.period}; abrangência: {e.scope}; cobertura: {e.coverage}; verificação: {e.verified_on}.</p>)}<p>{value.notice??proactiveNotice}</p><p>Sem disponibilidade de participação, viabilidade comercial ou benefício fiscal presumidos.</p></section>;
|
||||
}
|
||||
|
||||
export function ProactivePublicationFields({value,onChange,evidence,relations=[],options,reviewed,onReview}:{value:ProactivePublic;onChange:(v:ProactivePublic)=>void;evidence:ProactiveEvidence[];relations?:{id:string;label:string;relationship:string}[];options?:ProactiveOptions;reviewed:boolean;onReview:(v:boolean)=>void}){
|
||||
const text=(key:'need'|'proposal'|'basis'|'limitations'|'next_action'|'stage'|'resources'|'assumptions'|'conditions',label:string)=><Field label={label}><textarea aria-label={label} className={control} value={value[key]??''} onChange={e=>{onChange({...value,[key]:e.target.value});onReview(false);}}/></Field>;
|
||||
return <fieldset className="space-y-3 rounded border p-4"><legend>Síntese proactiva expressamente pública</legend><p>Redija uma síntese independente. Nenhum facto, interpretação, contacto ou fonte interna é copiado automaticamente. A síntese também não pode revelar informação privada indirectamente.</p>
|
||||
<Field label="Grupo público"><select className={control} aria-label="Grupo público" value={value.group} onChange={e=>onChange({...value,group:e.target.value})}>{Object.entries(options?.groups??{exists:'O que existe',needs:'Necessidades identificadas',ideas:'Ideias de investimento'}).map(([k,v])=><option key={k} value={k}>{v}</option>)}</select></Field>
|
||||
{value.group!=='exists'&&<Field label="Estado público da necessidade"><select className={control} aria-label="Estado público da necessidade" value={value.state} onChange={e=>onChange({...value,state:e.target.value})}><option value="hypothesis">Hipótese analítica</option><option value="confirmed">Necessidade confirmada com fundamento público</option></select></Field>}
|
||||
{value.group!=='exists'&&text('need','Necessidade pública')}{value.group==='ideas'&&text('proposal','Proposta pública')}{text('basis','Fundamento público')}{text('limitations','Limitações públicas da ideia')}{text('next_action','Próximo passo público')}{text('stage','Etapa pública da cadeia')}{text('resources','Recursos públicos documentados')}{text('assumptions','Pressupostos públicos')}{text('conditions','Condições públicas')}
|
||||
<Field label="Cadeia de valor pública"><select className={control} aria-label="Cadeia de valor pública" value={value.chain_id??''} onChange={e=>onChange({...value,chain_id:e.target.value})}><option value="">Por determinar</option>{options?.references.chain?.map(c=><option key={c.id} value={c.id}>{c.name}</option>)}</select></Field>
|
||||
<fieldset><legend>Relações públicas seleccionadas</legend>{relations.map(r=><label key={r.id} className="block"><input type="checkbox" checked={(value.relation_ids??[]).includes(r.id)} onChange={event=>onChange({...value,relation_ids:event.target.checked?[...(value.relation_ids??[]),r.id]:(value.relation_ids??[]).filter(id=>id!==r.id)})}/> {r.label} · {r.relationship}</label>)}</fieldset><fieldset><legend>Evidências públicas a divulgar</legend>{evidence.map(e=><label key={e.id} className="block"><input type="checkbox" checked={value.evidence_ids.includes(e.id)} onChange={event=>onChange({...value,evidence_ids:event.target.checked?[...value.evidence_ids,e.id]:value.evidence_ids.filter(id=>id!==e.id)})}/> {e.statement||'Evidência pública por descrever'}</label>)}</fieldset>
|
||||
<label className="block"><input type="checkbox" checked={reviewed} onChange={e=>onReview(e.target.checked)}/> Confirmei a divulgação deste texto e das evidências públicas seleccionadas, sem exposição directa ou indirecta de informação privada.</label>
|
||||
</fieldset>;
|
||||
}
|
||||
|
||||
export function proactiveView(raw:unknown):ProactivePublic|null{
|
||||
if(!raw||typeof raw!=='object')return null;
|
||||
const p=raw as Partial<ProactivePublic&ProactiveAnalysis>;
|
||||
if(p.version!==1)return null;
|
||||
if(typeof p.group==='string'&&typeof p.need==='string')return p as ProactivePublic;
|
||||
const a=raw as ProactiveAnalysis;
|
||||
if(!a.need||typeof a.need.problem!=='string'||!a.idea)return null;
|
||||
return {version:1,group:a.kind,state:a.need.state,need:a.kind==='exists'?'':a.need.problem,proposal:a.kind==='ideas'?a.idea.solution:'',basis:a.need.confirmation||'Fundamento por completar',limitations:[a.need.limitations,a.need.missing,a.idea.assumptions,a.idea.conditions,a.idea.pending].filter(Boolean).join('; '),next_action:a.idea.next_action,evidence_ids:a.need.evidence_ids,chain_id:a.idea.chain_id,stage:a.kind==='ideas'?a.idea.stage:'',notice:'Origem privada autorizada deste dossier. '+proactiveNotice};
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import {SimulationIrpcAnnual} from '@/components/simulation-irpc-annual';
|
||||
import {SimulationIrpcNormal} from '@/components/simulation-irpc-normal';
|
||||
import {SimulationIrpcWithholdings} from '@/components/simulation-irpc-withholdings';
|
||||
import {SimulationIspcResiduals} from '@/components/simulation-ispc-residuals';
|
||||
@@ -3513,6 +3514,7 @@ export function SimulationForm() {
|
||||
{(current.id === 'financial' || current.id === 'tax') && <SimulationIspcResiduals draft={draft} onChange={change} />}
|
||||
{(current.id === 'financial' || current.id === 'tax') && <SimulationIrpcWithholdings draft={draft} onChange={change} />}
|
||||
{(current.id === 'financial' || current.id === 'tax') && <SimulationIrpcNormal draft={draft} onChange={change} />}
|
||||
{(current.id === 'financial' || current.id === 'tax') && <SimulationIrpcAnnual draft={draft} onChange={change} />}
|
||||
{(current.id === 'financial' || current.id === 'tax') && <SimulationMonthlyIva draft={draft} busy={isCalculating} onCalculate={runSimulation} onChange={change} />}
|
||||
{current.id === 'financial' &&
|
||||
(draft.detail_level === 'advanced' ||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import {useState} from 'react';
|
||||
import {annualBook,newAnnualBook,saveAnnualBook,reuseAnnualAssessment,annualAssessment,annualWithholdingOptions,reuseAnnualWithholding,newAnnualPpc,recordAnnual,annualReportRows,annualHtml,annualSettlementSource,type AnnualBook,type AnnualPpc} from '@/lib/irpc-annual-settlement';
|
||||
|
||||
type Props={draft:Record<string,unknown>;onChange:(field:string,value:string)=>void};
|
||||
export function SimulationIrpcAnnual({draft,onChange}:Props){
|
||||
const[error,setError]=useState('');if(draft.fiscal_component!=='irpc')return null;
|
||||
try{
|
||||
const b=annualBook(draft),save=(next:AnnualBook)=>{try{onChange('modelo_a_snapshot',saveAnnualBook(draft,next));setError('');}catch(e){setError(String(e));}};
|
||||
if(!b)return<section aria-label="IRPC — L8 fecho anual" className="rounded border p-4"><h4>L8 — da colecta ao saldo anual simulado</h4><p>Reutiliza a colecta válida, retenções efectivamente sofridas por conta e PPC comprovados do próprio sujeito/exercício. PEC e créditos com regras próprias permanecem separados.</p><button type="button" onClick={()=>{try{save(reuseAnnualAssessment(draft,newAnnualBook()));}catch(e){setError(String(e));}}}>Preparar saldo anual L8</button>{error&&<p role="alert">{error}</p>}</section>;
|
||||
const patch=(p:Partial<AnnualBook>)=>save({...b,...p}),a=annualAssessment(draft),options=annualWithholdingOptions(draft);
|
||||
const field=(key:'subjectNuit'|'year'|'reference'|'assessmentReference',label:string)=><label className="block">{label}<input aria-label={label} value={b[key]} onChange={e=>patch({[key]:e.target.value})}/></label>;
|
||||
const group=(key:'withholdings'|'ppc',label:string)=><><label className="block">Estado — {label}<select aria-label={'Estado L8 — '+label} value={b[key].state} onChange={e=>patch({[key]:{...b[key],state:e.target.value as ''|'known'|'absent'}})}><option value="">Informação em falta</option><option value="known">Valores conhecidos — seleccionar comprovativos</option><option value="absent">Ausência declarada com suporte</option></select></label><label className="block">Suporte — {label}<input aria-label={'Suporte L8 — '+label} value={b[key].reference} onChange={e=>patch({[key]:{...b[key],reference:e.target.value}})}/></label></>;
|
||||
return<section aria-label="IRPC — L8 fecho anual" className="space-y-3 rounded border p-4"><h4>L8 — colecta, abatimentos e saldo anual simulado</h4><p>A colecta acima é anterior aos abatimentos. Este saldo tem cálculo e histórico próprios; retenção entregue pela empresa por pagamento a terceiros não é retenção sofrida. O resultado continua simulado, sem submissão, pagamento ou reembolso automático.</p><p>{annualSettlementSource}</p>{error&&<p role="alert">{error}</p>}
|
||||
{field('subjectNuit','NUIT do sujeito do fecho L8')}{field('year','Exercício do fecho L8')}{field('reference','Suporte do fecho da entidade e exercício L8')}
|
||||
<p>Colecta disponível:{a.colecta?a.colecta.numerator+'/'+a.colecta.denominator+' MZN':'Indeterminada'};origem:{a.kind==='special'?'L7 qualificado':'L6 normal'};NUIT:{a.subjectNuit||'Por identificar'};exercício:{a.year||'Por identificar'}.</p><button type="button" onClick={()=>{try{save(reuseAnnualAssessment(draft,b));}catch(e){setError(String(e));}}}>Reutilizar colecta corrente L6/L7</button>{field('assessmentReference','Suporte da colecta reutilizada L8')}
|
||||
<fieldset className="space-y-2 rounded border p-3"><legend>Retenções efectivamente sofridas por conta</legend>{group('withholdings','Retenções sofridas')}
|
||||
{options.length===0?<p>Não há afectações de comprovativosL5 neste contexto. Reutilize e reconcilie a retenção recebida emL5 ou declare ausência com suporte.</p>:options.map(o=><div key={o.rowId+'|'+o.paymentId} className="rounded border p-2"><p>{o.document||'Prova por identificar'};emitente:{o.issuer};data:{o.date};parcelaL5:{o.amount}MZN;{o.reason||'Retenção recebida/efectiva por conta reconciliada emL5.'}</p><button type="button" disabled={!o.ready||b.withholdings.rows.some(r=>r.rowId===o.rowId&&r.paymentId===o.paymentId)} onClick={()=>{try{save(reuseAnnualWithholding(draft,b,o.rowId,o.paymentId,crypto.randomUUID()));}catch(e){setError(String(e));}}}>Seleccionar prova L5 {o.document||o.paymentId}</button></div>)}
|
||||
{b.withholdings.rows.map((r,index)=>{const change=(p:Partial<typeof r>)=>patch({withholdings:{...b.withholdings,rows:b.withholdings.rows.map(x=>x.id===r.id?{...x,...p}:x)}});return<fieldset key={r.id} className="rounded border p-2"><legend>Retenção seleccionada {index+1}</legend><p>Rendimento:{r.rowId};prova:{r.paymentId};NUIT:{r.subjectNuit};exercício:{r.year}. Fonte conservada. Se mudou, retire esta selecção e seleccione a prova actual. O histórico mantém-se.</p><label className="block">Parcela a abater<input aria-label={'Parcela da retenção L8 '+(index+1)} value={r.amount} onChange={e=>change({amount:e.target.value})}/></label><label className="block">O próprio sujeito é beneficiário e o rendimento está incluído na base deste exercício<select aria-label={'Rendimento incluído L8 '+(index+1)} value={r.incomeIncluded} onChange={e=>change({incomeIncluded:e.target.value as ''|'yes'|'no'})}><option value="">Informação em falta</option><option value="yes">Sim — documentado</option><option value="no">Não — crédito não aplicável neste fecho</option></select></label><label className="block">Suporte da titularidade e inclusão<input aria-label={'Suporte da retenção L8 '+(index+1)} value={r.reference} onChange={e=>change({reference:e.target.value})}/></label><button type="button" onClick={()=>patch({withholdings:{...b.withholdings,rows:b.withholdings.rows.filter(x=>x.id!==r.id)}})}>Retirar selecção L8 da retenção {index+1}</button></fieldset>;})}</fieldset>
|
||||
<fieldset className="space-y-2 rounded border p-3"><legend>PPC efectivamente pagos</legend>{group('ppc','PPC efectuados')}<p>Regista comprovativos de pagamentos por conta; não calcula automaticamente a obrigação PPC nem usa pagamentos previstos no plano.</p><button type="button" onClick={()=>patch({ppc:{...b.ppc,rows:[...b.ppc.rows,{...newAnnualPpc(crypto.randomUUID()),subjectNuit:b.subjectNuit,year:b.year}]}})}>Registar comprovativo PPC</button>
|
||||
{b.ppc.rows.map((r,index)=>{const change=(p:Partial<AnnualPpc>)=>patch({ppc:{...b.ppc,rows:b.ppc.rows.map(x=>x.id===r.id?{...x,...p}:x)}});return<fieldset key={r.id} className="rounded border p-2"><legend>PPC {index+1}</legend>{([['document','Comprovativo'],['issuer','Emitente'],['date','Data (AAAA-MM-DD)'],['subjectNuit','NUIT beneficiário'],['year','Exercício do comprovativo'],['currency','Moeda do comprovativo'],['proofAmount','Montante comprovado'],['amount','Parcela a abater'],['reference','Suporte do pagamento e afectação']]as const).map(([key,label])=><label key={key} className="block">{label}<input aria-label={'PPC L8 '+(index+1)+' — '+label} value={r[key]} onChange={e=>change({[key]:e.target.value})}/></label>)}<label className="block">Pagamento efectivamente comprovado<select aria-label={'PPC L8 '+(index+1)+' — Efectivo'} value={r.effective} onChange={e=>change({effective:e.target.value as ''|'yes'|'no'})}><option value="">Informação em falta</option><option value="yes">Sim — comprovativo reconciliado</option><option value="no">Não — apenas previsão/outro estado</option></select></label><button type="button" onClick={()=>patch({ppc:{...b.ppc,rows:b.ppc.rows.filter(x=>x.id!==r.id)}})}>Retirar PPC {index+1}</button></fieldset>;})}</fieldset>
|
||||
{([['pec','PEC'],['credits','Créditos com regras próprias']]as const).map(([key,label])=><fieldset key={key} className="rounded border p-3"><legend>{label} — tratamento separado</legend><label className="block">Estado — {label}<select aria-label={'Estado L8 — '+label} value={b[key].state} onChange={e=>patch({[key]:{...b[key],state:e.target.value as ''|'known'|'absent'}})}><option value="">Informação em falta</option><option value="absent">Ausência declarada com suporte</option><option value="known">Valor conhecido — positivo exige regra própria</option></select></label>{(b[key].state==='known'||b[key].amount)&&<label className="block">Montante declarado<input aria-label={'Montante L8 — '+label} value={b[key].amount} onChange={e=>patch({[key]:{...b[key],amount:e.target.value}})}/></label>}<label className="block">Suporte<input aria-label={'Suporte L8 — '+label} value={b[key].reference} onChange={e=>patch({[key]:{...b[key],reference:e.target.value}})}/></label></fieldset>)}
|
||||
<button type="button" onClick={()=>{try{save(recordAnnual(draft,b));}catch(e){setError(String(e));}}}>Calcular e guardar saldo anual L8</button><button type="button" onClick={()=>{try{const html=annualHtml(draft),url=URL.createObjectURL(new Blob([html],{type:'text/html;charset=utf-8'})),link=document.createElement('a');link.href=url;link.download='IRPC-L8-saldo-simulado.html';link.click();URL.revokeObjectURL(url);setError('');}catch(e){setError(String(e));}}}>Exportar saldo anual L8</button>
|
||||
{annualReportRows(draft).map((r,n)=><p key={n}>{r[1]} — {r[2]} — {r[3]}</p>)}</section>;
|
||||
}catch(e){return<p role="alert">PreparaçãoL8 não recuperável:{String(e)}. Originais e históricos conservados.</p>;}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
import {normalBook,normalCurrent} from './irpc-normal.ts';
|
||||
import {irpcBook,irpcCurrent} from './irpc-withholdings.ts';
|
||||
import {acquisitionScope} from './iva-acquisitions.ts';
|
||||
import {closureFingerprint} from './iva-closure.ts';
|
||||
import {addFractions,subtractFractions,decimalFraction,fraction,fractionPresentation,type FiscalFraction} from './fiscal-rational.ts';
|
||||
|
||||
export const annualSettlementVersion='IRPC-annual-settlement/1';
|
||||
export const annualSettlementSource='CIRPC, arts. 63 e 67 (Lei 34/2007 e natureza da retenção na redacção aplicável da Lei 12/2025); Regulamento, Decreto 9/2008, arts. 21(2–5) e 27(1–2/6). Recorte: 2026, residente no regime geral, ano civil e MZN. Colecta corrente válida, retenções efectivamente sofridas por conta e PPC comprovados. PEC/créditos positivos e tributação autónoma ficam fora deste fecho inicial. Art. 27(6): montante inferior a 100 MZN sem cobrança/reembolso; saldo aritmético exacto conservado. Saldo simulado por colecta projectada; não é declaração submetida, pagamento ou reembolso recebido.';
|
||||
type State=''|'known'|'absent';
|
||||
type Evidence={state:State;amount:string;reference:string};
|
||||
type Group={state:State;reference:string};
|
||||
export type AnnualWithholding={id:string;rowId:string;paymentId:string;sourceKey:string;subjectNuit:string;year:string;amount:string;incomeIncluded:''|'yes'|'no';reference:string};
|
||||
export type AnnualPpc={id:string;document:string;issuer:string;date:string;subjectNuit:string;year:string;currency:string;proofAmount:string;amount:string;effective:''|'yes'|'no';reference:string};
|
||||
type AnnualRecord={version:typeof annualSettlementVersion;key:string;createdAt:string;model:AnnualModel};
|
||||
export type AnnualBook={version:1;subjectNuit:string;year:string;reference:string;assessment:''|'normal'|'special';assessmentKey:string;assessmentReference:string;withholdings:Group&{rows:AnnualWithholding[]};ppc:Group&{rows:AnnualPpc[]};pec:Evidence;credits:Evidence;result?:AnnualRecord;history:AnnualRecord[]};
|
||||
const evidence=():Evidence=>({state:'',amount:'',reference:''});
|
||||
export const newAnnualBook=():AnnualBook=>({version:1,subjectNuit:'',year:'',reference:'',assessment:'',assessmentKey:'',assessmentReference:'',withholdings:{state:'',reference:'',rows:[]},ppc:{state:'',reference:'',rows:[]},pec:evidence(),credits:evidence(),history:[]});
|
||||
export const newAnnualPpc=(id:string):AnnualPpc=>({id,document:'',issuer:'',date:'',subjectNuit:'',year:'',currency:'MZN',proofAmount:'',amount:'',effective:'',reference:''});
|
||||
const zero=()=>fraction(0n),cmp=(a:FiscalFraction,b:FiscalFraction)=>BigInt(a.numerator)*BigInt(b.denominator)-BigInt(b.numerator)*BigInt(a.denominator);
|
||||
const iso=(s:string)=>/^20\d{2}-\d{2}-\d{2}$/.test(s)&&Number.isFinite(Date.parse(s))&&new Date(s).toISOString().slice(0,10)===s;
|
||||
const moneyInput=(s:string)=>{if(!/^\d{1,18}(\.\d{1,2})?$/.test(s))throw Error('MontanteMZN em falta/inválido;máximo dois decimais,sem zero presumido.');return decimalFraction(s);};
|
||||
const canonical=(s:string)=>s.normalize('NFKC').trim().toLocaleLowerCase('pt').replace(/\s+/g,' ');
|
||||
const proofIdentity=(issuer:string,document:string,_date:string)=>JSON.stringify([canonical(issuer),canonical(document)]);
|
||||
function store(d:Record<string,unknown>){const s=JSON.parse(String(d.modelo_a_snapshot||'{"version":1,"books":{}}'));if(s.version!==1||!s.books||typeof s.books!=='object'||Array.isArray(s.books))throw Error('Livros fiscais não recuperáveis;originais conservados.');return s;}
|
||||
function books(d:Record<string,unknown>):Record<string,AnnualBook>{const m=store(d).irpcAnnual;if(m===undefined)return{};if(!m||typeof m!=='object'||Array.isArray(m))throw Error('MapaL8 não recuperável;originais conservados.');return m;}
|
||||
export function validateAnnual(b:AnnualBook){
|
||||
if(!b||b.version!==1||['subjectNuit','year','reference','assessmentKey','assessmentReference'].some(k=>typeof b[k as 'year']!=='string')||!['','normal','special'].includes(b.assessment)||!Array.isArray(b.history))throw Error('PreparaçãoL8 não recuperável.');
|
||||
for(const g of[b.withholdings,b.ppc,b.pec,b.credits])if(!g||!['','known','absent'].includes(g.state)||typeof g.reference!=='string')throw Error('EstadoL8 não recuperável.');
|
||||
for(const g of[b.pec,b.credits])if(typeof g.amount!=='string')throw Error('CréditoL8 não recuperável.');
|
||||
const w=['id','rowId','paymentId','sourceKey','subjectNuit','year','amount','incomeIncluded','reference'],p=Object.keys(newAnnualPpc(''));
|
||||
for(const[rows,keys]of[[b.withholdings.rows,w],[b.ppc.rows,p]]as const)if(!Array.isArray(rows)||new Set(rows.map(r=>r?.id)).size!==rows.length||rows.some(r=>!r||keys.some(k=>typeof(r as unknown as Record<string,unknown>)[k]!=='string')))throw Error('ComprovativosL8 não recuperáveis ou identificador repetido.');
|
||||
if(b.withholdings.rows.some(r=>!['','yes','no'].includes(r.incomeIncluded))||b.ppc.rows.some(r=>!['','yes','no'].includes(r.effective)))throw Error('QualificaçãoL8 não recuperável.');
|
||||
for(const r of[b.result,...b.history])if(r&&(r.version!==annualSettlementVersion||typeof r.key!=='string'||typeof r.createdAt!=='string'||!r.model||!Array.isArray(r.model.pending)))throw Error('HistóricoL8 não recuperável.');
|
||||
}
|
||||
export function annualBook(d:Record<string,unknown>){const b=books(d)[acquisitionScope(d)];if(b)validateAnnual(b);return b;}
|
||||
export function saveAnnualBook(d:Record<string,unknown>,b:AnnualBook){validateAnnual(b);return JSON.stringify({...store(d),irpcAnnual:{...books(d),[acquisitionScope(d)]:b}});}
|
||||
export function annualAssessment(d:Record<string,unknown>){
|
||||
const b=normalBook(d),r=b.result,m=r?.model;
|
||||
return{book:b,record:r,current:normalCurrent(d,b),key:r?closureFingerprint(r):'',subjectNuit:b.base?.subjectNuit??'',year:b.year,period:m?.periodsFx?{from:m.periodsFx.input.from,to:m.periodsFx.input.to}:m?.fiscalPeriod??m?.assessment?.period??null,kind:b.special?'special' as const:'normal' as const,colecta:b.special?m?.special?.colecta??null:m?.colecta??null,autonomous:b.special?m?.special?.expenses.autonomousTax??null:zero()};
|
||||
}
|
||||
export function reuseAnnualAssessment(d:Record<string,unknown>,b:AnnualBook):AnnualBook{const a=annualAssessment(d);return{...b,subjectNuit:b.subjectNuit||a.subjectNuit,year:b.year||a.year,assessment:a.kind,assessmentKey:a.key,assessmentReference:b.assessmentReference||a.book.assessment?.reference||''};}
|
||||
export function annualWithholdingOptions(d:Record<string,unknown>){
|
||||
const b=irpcBook(d),current=irpcCurrent(d,b);return b.rows.flatMap(r=>r.allocations.map(a=>{
|
||||
const p=b.payments.find(p=>p.id===a.paymentId),v=b.result?.rows.find(v=>v.id===r.id),issues:string[]=[];
|
||||
if(!current||!b.result)issues.push('Recalcule e guardeL5 com as entradas actuais.');
|
||||
if(r.direction!=='received'||r.origin!=='effective'||v?.direction!=='received'||v.status!=='calculated'||v.nature!=='on_account'||r.settlement!=='complete'||v.settled===null)issues.push('Apenas retenção recebida/efectiva por conta,calculada e reconciliada emL5;remessa por terceiros,definitiva ou projecção não é crédito próprio.');
|
||||
if(!p||p.kind!=='withholding_proof'||p.currency!=='MZN'||r.currency!=='MZN'||!iso(p.date)||!p.reference.trim())issues.push('Comprovativo de retenção sofrida emMZN em falta ou fora do recorte.');
|
||||
return{rowId:r.id,paymentId:a.paymentId,document:p?.reference??'',issuer:r.counterparty,date:p?.date??'',eventDate:v?.eventDate??'',year:v?.eventDate.slice(0,4)??'',amount:a.amount,proofAmount:p?.amount??'',identity:proofIdentity(r.counterparty,p?.reference??'',p?.date??''),key:closureFingerprint([r,v,p,a]),ready:!issues.length,reason:issues.join(' ')};
|
||||
}));
|
||||
}
|
||||
export function reuseAnnualWithholding(d:Record<string,unknown>,b:AnnualBook,rowId:string,paymentId:string,id:string):AnnualBook{
|
||||
const o=annualWithholdingOptions(d).find(o=>o.rowId===rowId&&o.paymentId===paymentId);if(!o)throw Error('ComprovativoL5 não encontrado;originais conservados.');
|
||||
if(b.withholdings.rows.some(r=>r.rowId===rowId&&r.paymentId===paymentId))throw Error('Retenção/prova já seleccionada;altere a parcela existente sem duplicar.');
|
||||
return{...b,withholdings:{...b.withholdings,rows:[...b.withholdings.rows,{id,rowId,paymentId,sourceKey:o.key,subjectNuit:b.subjectNuit,year:o.year,amount:o.amount,incomeIncluded:'',reference:''}]}};
|
||||
}
|
||||
function dependencies(d:Record<string,unknown>){let normal:unknown,L5:unknown;try{const a=annualAssessment(d);normal=[a.record,a.current];}catch(e){normal=String(e);}try{const b=irpcBook(d);L5=[b.rows,b.payments,b.result,irpcCurrent(d,b)];}catch(e){L5=String(e);}return[normal,L5,Object.entries(books(d)).filter(([k])=>k!==acquisitionScope(d)).map(([k,b])=>[k,b.subjectNuit,b.year,b.withholdings,b.ppc])];}
|
||||
function key(d:Record<string,unknown>,b:AnnualBook){const{result:_,history:__,...input}=b;return closureFingerprint([annualSettlementVersion,acquisitionScope(d),input,dependencies(d)]);}
|
||||
export function annualCurrent(d:Record<string,unknown>,b:AnnualBook){return !!b.result&&b.result.key===key(d,b);}
|
||||
export function calculateAnnual(d:Record<string,unknown>,b:AnnualBook){
|
||||
validateAnnual(b);const{result:_result,history:_history,...input}=b;const pending:string[]=[],warn:string[]=[];let assessment:ReturnType<typeof annualAssessment>|null=null,colecta:FiscalFraction|null=null;let options:ReturnType<typeof annualWithholdingOptions>=[];
|
||||
try{assessment=annualAssessment(d);const a=assessment,m=a.record?.model;
|
||||
if(!a.record||!a.current||a.key!==b.assessmentKey||b.assessment!==a.kind)pending.push('Colecta de origem ausente,alterada ou não corrente;reutilize a execuçãoL6/L7 aplicável,não some nem contorne efeitosL7.');
|
||||
if(!/^\d{9}$/.test(b.subjectNuit)||b.subjectNuit!==a.subjectNuit||b.year!=='2026'||b.year!==a.year||a.book.scope!=='resident_general'||m?.currency!=='MZN'||a.period?.from!=='2026-01-01'||a.period?.to!=='2026-12-31')pending.push('Entidade/NUIT,exercício ou âmbito fora do recorte residente/ano civil2026/MZN;períodos especiais permanecem separados.');
|
||||
if(!b.reference.trim()||!b.assessmentReference.trim())pending.push('Falta suporte do fecho do sujeito/exercício e da colecta seleccionada.');
|
||||
if(!a.colecta||cmp(a.colecta,zero())<0n)pending.push('Colecta aplicável indeterminada;uma parcelaL6 não substitui totalL7 pendente.');else colecta=structuredClone(a.colecta);
|
||||
if(a.kind==='special'&&(!m?.special||!a.autonomous||cmp(a.autonomous,zero())!==0n))pending.push('Tributação autónoma positiva/indeterminada exige liquidação própria;este primeiro saldo não a ignora nem a compensa.');
|
||||
}catch(e){pending.push('Origem da colecta não recuperável: '+String(e));}
|
||||
try{options=annualWithholdingOptions(d);}catch(e){if(b.withholdings.state==='known'||b.withholdings.rows.length)pending.push('OrigemL5 não recuperável: '+String(e));}
|
||||
const group=(g:Group,rows:unknown[],label:string)=>{if(!g.state||!g.reference.trim())pending.push(label+':identifique valor conhecido,ausência declarada ou informação em falta com suporte.');if(g.state==='absent'&&rows.length)pending.push(label+':ausência declarada contradiz parcelas presentes;conserve e reconcilie.');if(g.state==='known'&&!rows.length)pending.push(label+':não há comprovativos seleccionados;ausência exige declaração própria.');};
|
||||
group(b.withholdings,b.withholdings.rows,'Retenções sofridas por conta');group(b.ppc,b.ppc.rows,'PPC efectuados');
|
||||
try{if(b.withholdings.state==='absent'&&options.some(o=>o.ready&&o.year===b.year&&cmp(moneyInput(o.amount),zero())>0n))pending.push('Ausência de retenções sofridas contradiz provaL5 efectiva por conta no exercício;reconcilie sem a ignorar.');}catch(e){pending.push('Reconciliação da ausência de retenções: '+String(e));}
|
||||
for(const[label,e]of[['PEC',b.pec],['Créditos com regras próprias',b.credits]]as const){try{if(!e.state||!e.reference.trim())throw Error('presença/ausência e suporte em falta');if(e.state==='absent'){if(e.amount.trim())throw Error('ausência contradiz montante preenchido');}else if(cmp(moneyInput(e.amount),zero())!==0n)throw Error('montante positivo fora deste recorte:corresponder ordem,limite e transporte próprios;sem abatimento ou reembolso automático');}catch(err){pending.push(label+': '+String(err));}}
|
||||
const claims:Array<{id:string;kind:'withholding'|'ppc';identity:string;proofAmount:FiscalFraction|null;value:FiscalFraction|null;sourceKey:string;allocationAmount:FiscalFraction|null;document:string;issuer:string;date:string;subjectNuit:string;year:string;reason:string}>=[];
|
||||
for(const r of b.withholdings.rows){const o=options.find(o=>o.rowId===r.rowId&&o.paymentId===r.paymentId),issues:string[]=[];let value:FiscalFraction|null=null,proofAmount:FiscalFraction|null=null;
|
||||
try{if(!o||!o.ready||r.sourceKey!==o.key)throw Error(o?.reason||'provaL5 ausente ou alterada;reutilize sem duplicar');if(r.subjectNuit!==b.subjectNuit||r.year!==b.year||o.year!==b.year||!o.date.startsWith(b.year+'-'))throw Error('entidade/exercício da retenção não correspondem ao fecho');if(r.incomeIncluded!=='yes'||!r.reference.trim())throw Error('confirme o próprio beneficiário/NUIT e inclusão do rendimento na base do exercício com suporte');value=moneyInput(r.amount);proofAmount=moneyInput(o.proofAmount);if(cmp(value,moneyInput(o.amount))>0n)throw Error('parcela ultrapassa a retenção efectivamente comprovada e afectada emL5');if(b.withholdings.rows.filter(x=>x.rowId===r.rowId&&x.paymentId===r.paymentId).length!==1)throw Error('retenção/prova repetida;uma afectação por linhaL5');if(assessment?.record?.model.special?.cooperative.status==='calculated'&&cmp(value,zero())>0n)throw Error('cooperativa integralmente elegível declara ausência de rendimentos retidos;segregue o casoL7 antes do crédito anual');}catch(e){issues.push(String(e));value=null;}
|
||||
claims.push({id:r.id,kind:'withholding',identity:o?.identity??'',proofAmount,value,sourceKey:r.sourceKey,allocationAmount:o&&value?moneyInput(o.amount):null,document:o?.document??r.paymentId,issuer:o?.issuer??'',date:o?.date??'',subjectNuit:r.subjectNuit,year:r.year,reason:issues.join(' ')});
|
||||
}
|
||||
for(const r of b.ppc.rows){const issues:string[]=[];let value:FiscalFraction|null=null,proofAmount:FiscalFraction|null=null;
|
||||
try{if(!r.document.trim()||!r.issuer.trim()||!r.reference.trim()||r.effective!=='yes'||r.currency!=='MZN'||!iso(r.date)||!r.date.startsWith(b.year+'-')||r.subjectNuit!==b.subjectNuit||r.year!==b.year)throw Error('PPC exige comprovativo efectivo,MZN,data,entidade e exercício correspondentes;projecção/tesouraria não é pagamento');value=moneyInput(r.amount);proofAmount=moneyInput(r.proofAmount);if(cmp(value,proofAmount)>0n)throw Error('parcelaPPC ultrapassa o montante comprovado');}catch(e){issues.push(String(e));value=null;}
|
||||
claims.push({id:r.id,kind:'ppc',identity:proofIdentity(r.issuer,r.document,r.date),proofAmount,value,sourceKey:'',allocationAmount:null,document:r.document,issuer:r.issuer,date:r.date,subjectNuit:r.subjectNuit,year:r.year,reason:issues.join(' ')});
|
||||
}
|
||||
const elsewhere:Array<{identity:string;subjectNuit:string;year:string;value:FiscalFraction;proofAmount:FiscalFraction;sourceKey:string}>=[];
|
||||
for(const[scope,other]of Object.entries(books(d))){if(scope===acquisitionScope(d))continue;try{validateAnnual(other);for(const r of other.ppc.rows)elsewhere.push({identity:proofIdentity(r.issuer,r.document,r.date),subjectNuit:r.subjectNuit,year:r.year,value:moneyInput(r.amount),proofAmount:moneyInput(r.proofAmount),sourceKey:''});for(const r of other.withholdings.rows){const source=(store(d).irpcWithholdings??{})[scope];const row=source?.rows?.find((x:{id:string})=>x.id===r.rowId),p=source?.payments?.find((x:{id:string})=>x.id===r.paymentId);if(row&&p)elsewhere.push({identity:proofIdentity(row.counterparty,p.reference,p.date),subjectNuit:r.subjectNuit,year:r.year,value:moneyInput(r.amount),proofAmount:moneyInput(p.amount),sourceKey:r.sourceKey});}}catch(e){if(other?.subjectNuit===b.subjectNuit)pending.push('Outro mapa da mesma entidade não recuperável para conferir duplicações: '+scope+';'+String(e));}}
|
||||
for(const c of claims){if(!c.value||!c.proofAmount)continue;const same=claims.filter(x=>x.identity===c.identity&&x.value),other=elsewhere.filter(x=>x.identity===c.identity);let issue='';
|
||||
if(same.filter(x=>x.kind==='ppc').length>1||new Set(same.map(x=>x.kind)).size>1)issue='Mesmo comprovativo repetido ou usado como retenção ePPC;reconcilie sem dedução dupla.';
|
||||
if(other.some(x=>x.subjectNuit!==b.subjectNuit||x.year!==b.year))issue='Mesmo comprovativo já associado a outra entidade/exercício;reconcilie a titularidade e a afectação.';
|
||||
if([...same,...other].some(x=>x.proofAmount&&cmp(x.proofAmount,c.proofAmount!)!==0n)||cmp(addFractions([...same.flatMap(x=>x.value?[x.value]:[]),...other.map(x=>x.value)]),c.proofAmount)>0n)issue='Comprovativo utilizado além do montante disponível ou com montantes divergentes neste/outro mapa.';
|
||||
if(c.kind==='withholding'&&c.sourceKey&&c.allocationAmount&&cmp(addFractions([...same.filter(x=>x.sourceKey===c.sourceKey).flatMap(x=>x.value?[x.value]:[]),...other.filter(x=>x.sourceKey===c.sourceKey).map(x=>x.value)]),c.allocationAmount)>0n)issue='Mesma afectação L5 reutilizada além da parcela disponível, ainda que o comprovativo global seja maior.';
|
||||
if(issue)c.reason=[c.reason,issue].filter(Boolean).join(' ');
|
||||
}
|
||||
for(const c of claims)if(c.reason)pending.push((c.document||c.id)+': '+c.reason);
|
||||
const knownWithholdings=addFractions(claims.filter(c=>c.kind==='withholding'&&!c.reason&&c.value).map(c=>c.value!)),knownPpc=addFractions(claims.filter(c=>c.kind==='ppc'&&!c.reason&&c.value).map(c=>c.value!));
|
||||
const ready=pending.length===0&&colecta!==null,arithmeticBalance=ready?subtractFractions(subtractFractions(colecta!,knownWithholdings),knownPpc):null;
|
||||
let payable:FiscalFraction|null=null,recoverable:FiscalFraction|null=null,belowMinimum:FiscalFraction|null=null;let status:'payable'|'recoverable'|'balanced'|'below_minimum'|'indeterminate'='indeterminate';
|
||||
if(arithmeticBalance){const n=BigInt(arithmeticBalance.numerator),abs=fraction(n<0n?-n:n,BigInt(arithmeticBalance.denominator));payable=zero();recoverable=zero();belowMinimum=zero();if(!n)status='balanced';else if(cmp(abs,fraction(100n))<0n){status='below_minimum';belowMinimum=abs;warn.push('Art27(6):saldo inferior a100MZN,sem cobrança/reembolso neste recorte;aritmética conservada,não é transporte de crédito.');}else if(n>0n){status='payable';payable=abs;}else{status='recoverable';recoverable=abs;}}
|
||||
return{version:annualSettlementVersion,input:structuredClone(input),subjectNuit:b.subjectNuit,year:b.year,assessment:assessment?.record?{key:b.assessmentKey,kind:b.assessment,version:assessment.record.model.version,createdAt:assessment.record.createdAt,colecta,period:assessment.period,origin:assessment.record.model.origin}:null,claims,knownWithholdings,knownPpc,arithmeticBalance,payable,recoverable,belowMinimum,status,pending:[...new Set(pending)],warnings:warn,source:annualSettlementSource,officialBalancesConsumed:false,submitted:false,refundReceived:false,limitations:['L8 parcial:PEC e créditos positivos,tributação autónoma,períodos especiais e pagamentos noutra moeda exigem regras próprias.','PPC aqui é pagamento comprovado;não cálculo automático da obrigação ou calendário.','Retenção sofrida não é retenção entregue pela empresa por conta de terceiros.','Valores racionais exactos;camposM20/M22 e representação não presumidos.','Saldo simulado por colecta projectada;sem pagamento,submissão ou reembolso automático.']};
|
||||
}
|
||||
export type AnnualModel=ReturnType<typeof calculateAnnual>;
|
||||
export function recordAnnual(d:Record<string,unknown>,b:AnnualBook,now=new Date().toISOString()):AnnualBook{return{...b,history:b.result?[...b.history,structuredClone(b.result)]:b.history,result:{version:annualSettlementVersion,key:key(d,b),createdAt:now,model:calculateAnnual(d,b)}};}
|
||||
const show=(v:FiscalFraction|null)=>v?(fractionPresentation(v).approximate?'≈':'')+fractionPresentation(v).decimal+' MZN (exacto '+v.numerator+'/'+v.denominator+')':'Indeterminado';
|
||||
const stateLabel=(s:State)=>s==='known'?'Valor conhecido':s==='absent'?'Ausência declarada':'Informação em falta';
|
||||
export function annualReportRows(d:Record<string,unknown>):Array<[string,string,string,string]>{
|
||||
try{
|
||||
const b=annualBook(d),r=b?.result;if(!b||!r)return[];const m=r.model;
|
||||
const status={payable:'A pagar',recoverable:'A recuperar',balanced:'Saldo zero',below_minimum:'Inferior ao mínimo de cobrança/reembolso',indeterminate:'Indeterminado'}[m.status];
|
||||
return[
|
||||
['IRPC — L8','Fecho anual — âmbito e origem',
|
||||
'NUIT: '+m.subjectNuit+'; exercício: '+m.year+'; colecta: '+show(m.assessment?.colecta??null)+'; origem: '+(m.assessment?.kind==='special'?'L7 qualificado':'L6 normal')+'. '+(annualCurrent(d,b)?'Entradas correspondentes.':'Histórico; origem/entradas alteradas: recalcule o saldo corrente.')+' Saldo simulado, não liquidação submetida.',
|
||||
m.input.reference+'; '+m.input.assessmentReference+'; '+m.source],
|
||||
...m.claims.map(c=>[
|
||||
'IRPC — L8',(c.kind==='withholding'?'Retenção sofrida':'PPC')+' — '+(c.document||c.id),
|
||||
'Entidade: '+c.subjectNuit+'; exercício: '+c.year+'; emitente: '+c.issuer+'; data: '+c.date+'; comprovado: '+show(c.proofAmount)+'; parcela: '+(c.reason?'Indeterminado':show(c.value))+'. '+(c.reason||'Reconciliada sem utilização duplicada.'),
|
||||
c.kind==='withholding'?m.input.withholdings.reference+'; '+(m.input.withholdings.rows.find(r=>r.id===c.id)?.reference??''):m.input.ppc.reference+'; '+(m.input.ppc.rows.find(r=>r.id===c.id)?.reference??'')
|
||||
]as[string,string,string,string]),
|
||||
['IRPC — L8','Saldo anual simulado',
|
||||
'Estado: '+status+'. Retenções conhecidas: '+show(m.knownWithholdings)+'; PPC conhecidos: '+show(m.knownPpc)+'; saldo aritmético: '+show(m.arithmeticBalance)+'; a pagar: '+show(m.payable)+'; a recuperar: '+show(m.recoverable)+'. '+m.pending.join(' | ')+' '+m.warnings.join(' '),m.source],
|
||||
['IRPC — L8','Estados dos comprovativos',
|
||||
'Retenções sofridas: '+stateLabel(m.input.withholdings.state)+'; PPC: '+stateLabel(m.input.ppc.state)+'. Subtotais conhecidos não substituem informação em falta.',m.input.withholdings.reference+'; '+m.input.ppc.reference],
|
||||
['IRPC — L8','PEC e créditos separados',
|
||||
'PEC: '+stateLabel(m.input.pec.state)+'; montante declarado: '+(m.input.pec.amount||'Não preenchido')+'; créditos: '+stateLabel(m.input.credits.state)+'; montante declarado: '+(m.input.credits.amount||'Não preenchido')+'. Sem dedução, transporte ou reembolso presumidos. '+m.limitations.join(' '),m.input.pec.reference+'; '+m.input.credits.reference]
|
||||
];
|
||||
}catch(e){return[['IRPC — L8','Não recuperável',String(e),'Originais e históricos conservados.']];}
|
||||
}
|
||||
export function annualHtml(d:Record<string,unknown>){const b=annualBook(d);if(!b?.result||!annualCurrent(d,b))throw Error('Calcule e guardeL8 com as fontes actuais antes de exportar.');const esc=(s:string)=>s.replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]!));return'<!doctype html><html lang="pt"><meta charset="utf-8"><title>IRPC — L8 saldo anual simulado</title><h1>IRPC — colecta e saldo anual simulado</h1><p>Não é declaração submetida,pagamento efectuado ou reembolso recebido.</p>'+annualReportRows(d).map(r=>'<section><h2>'+esc(r[1])+'</h2><p>'+esc(r[2])+'</p><small>'+esc(r[3])+'</small></section>').join('')+'</html>';}
|
||||
@@ -0,0 +1,31 @@
|
||||
type Analysis = {version?:number;group?:string;kind?:string;state?:string;need?:string|{state?:string;problem?:string;confirmation?:string;limitations?:string;missing?:string};idea?:{solution?:string;activity?:string;stage?:string;coverage?:string;resources?:string;assumptions?:string;conditions?:string;pending?:string;next_action?:string};proposal?:string;basis?:string;limitations?:string;next_action?:string;stage?:string;resources?:string;assumptions?:string;conditions?:string;relations?:{kind:string;target_id:string;label:string;relationship:string;basis:string}[];evidence?:{id?:string;statement?:string;interpretation?:string;source?:string;locator?:string;period?:string;scope?:string;coverage?:string;verified_on?:string;access?:string}[]};
|
||||
type Source={key?:string;title?:string;version?:string|number;analysis?:{proactive?:Analysis}};
|
||||
export function proactiveInvestmentRows(draft:Record<string,unknown>):Array<[string,string,string,string]>{
|
||||
const rows:Array<[string,string,string,string]>=[],sources:Source[]=[],seen=new Set<string>();
|
||||
try{
|
||||
const selected=draft.context_opportunity_snapshot?JSON.parse(String(draft.context_opportunity_snapshot)):null;
|
||||
const context=draft.context_applicability_snapshot?JSON.parse(String(draft.context_applicability_snapshot)):null;
|
||||
if(selected?.choice?.opportunity)sources.push(selected.choice.opportunity);
|
||||
else if(Array.isArray(context?.opportunity_choices))sources.push(...context.opportunity_choices.map((c:{opportunity:Source})=>c.opportunity));
|
||||
else if(context?.selection?.opportunity)sources.push(context.selection.opportunity);
|
||||
for(const source of sources){
|
||||
const p=source?.analysis?.proactive;if(!p||p.version!==1||!source.key||seen.has(source.key))continue;seen.add(source.key);
|
||||
if(draft.context_opportunity&&draft.context_opportunity!==source.key)continue;
|
||||
const origin=`${source.title??'Ideia por identificar'}; ${source.key}; versão ${source.version??'Por identificar'}`;
|
||||
const kind=p.group??p.kind;
|
||||
const privateNeed=typeof p.need==='object'?p.need:null;
|
||||
rows.push(['Localização','Origem da análise e ideia',source.title??'Por identificar',origin]);
|
||||
if(kind!=='exists')rows.push(['Localização','Estado da necessidade',(privateNeed?.state??p.state)==='confirmed'?'Necessidade confirmada no âmbito documentado; não comprova viabilidade comercial':'Hipótese analítica; informação económica por confirmar',origin]);
|
||||
if(kind!=='exists')rows.push(['Localização','Necessidade identificada',privateNeed?.problem??(typeof p.need==='string'?p.need:'Por determinar'),origin]);
|
||||
if(kind==='ideas')rows.push(['Localização','Proposta de investimento',p.proposal??p.idea?.solution??'Por determinar',origin]);
|
||||
rows.push(['Localização','Fundamento da ideia',p.basis??privateNeed?.confirmation??'Por completar',origin]);
|
||||
if(kind==='ideas')rows.push(['Localização','Etapa e pressupostos',[p.stage??p.idea?.stage,p.idea?.coverage,p.resources??p.idea?.resources,p.assumptions??p.idea?.assumptions,p.conditions??p.idea?.conditions].filter(Boolean).join('; ')||'Por determinar',origin]);
|
||||
rows.push(['Localização','Limitações da ideia',[p.limitations,kind!=='exists'?privateNeed?.limitations:null,kind!=='exists'?privateNeed?.missing:null,kind==='ideas'?p.idea?.pending:null].filter(Boolean).join('; ')||'Por completar',origin]);
|
||||
rows.push(['Localização','Próxima acção da ideia',p.next_action??p.idea?.next_action??'Por determinar',origin]);
|
||||
for(const r of p.relations??[])rows.push(['Localização','Relação documentada ou hipótese',`${r.label}; ${r.relationship}; sem contrato, acesso ou participação presumidos`,`${origin}; ${r.kind}:${r.target_id}; ${r.basis}`]);
|
||||
for(const e of p.evidence??[])rows.push(['Localização','Evidência da ideia',[e.statement,e.interpretation?`Interpretação: ${e.interpretation}`:null,`Período: ${e.period||'Por determinar'}`,`Abrangência: ${e.scope||'Por determinar'}`,`Cobertura: ${e.coverage||'Por determinar'}`,`Verificação: ${e.verified_on||'Por determinar'}`].filter(Boolean).join('; '),`${origin}; fonte: ${e.source||'Por identificar'}; localizador: ${e.locator||'Por identificar'}`]);
|
||||
rows.push(['Localização','Limites da preparação proactiva','Não comprova contrato, encomenda, participação disponível, energia acessível, terra disponível, viabilidade ou benefício fiscal. Informação em falta não é zero.',origin]);
|
||||
}
|
||||
}catch{/* Preserve unreadable original context; do not reconstruct an economic conclusion. */}
|
||||
return rows;
|
||||
}
|
||||
@@ -179,6 +179,7 @@ const rowSection: Record<string, DossierReportSectionId> = {
|
||||
'IRPC — retenções': 'finance',
|
||||
'IRPC normal — L6': 'finance',
|
||||
'IRPC — L7': 'finance',
|
||||
'IRPC — L8': 'finance',
|
||||
Equipa: 'team',
|
||||
'Necessidade de negócio': 'resources',
|
||||
Financiamento: 'resources',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import {annualReportRows} from './irpc-annual-settlement.ts';
|
||||
import {proactiveInvestmentRows} from './proactive-investment-report.ts';
|
||||
import {normalReportRows} from './irpc-normal.ts';
|
||||
import {irpcReportRows} from './irpc-withholdings.ts';
|
||||
import {ispcResidualReportRows} from './ispc-residuals.ts';
|
||||
@@ -697,6 +699,7 @@ export function buildProjectDossierRows(
|
||||
rows.push(...ispcResidualReportRows(draft));
|
||||
rows.push(...irpcReportRows(draft));
|
||||
rows.push(...normalReportRows(draft));
|
||||
rows.push(...annualReportRows(draft));
|
||||
rows.push(...fiscalCalculationGapReportRows(draft));
|
||||
rows.push(...l3FormPreparationReportRows(draft));
|
||||
const operationRows = salesReportRows(draft);
|
||||
@@ -802,6 +805,7 @@ export function buildProjectDossierRows(
|
||||
if (land.need === 'yes') rows.push(['Localização', 'Situação do terreno', String(draft.land_status_label ?? ({ owned: 'Próprio', duat: 'DUAT', leased: 'Arrendado', requested: 'Pedido em curso', unknown: 'Por determinar' } as Record<string, string>)[String(draft.land_status)] ?? 'Informação em falta'), 'Informação declarada; não comprova título ou disponibilidade']);
|
||||
else rows.push(['Localização', 'Preparação do terreno', land.need === 'no' ? 'Situação do terreno não aplicável à preparação actual; valores anteriores conservados.' : 'Definir se precisa de terra; pode continuar a preparar o investimento.', 'Sem inferência de dispensa legal']);
|
||||
}
|
||||
rows.push(...proactiveInvestmentRows(draft));
|
||||
const lineageFields: Record<string, string> = {'Título':'project_title','Resumo':'project_summary','Sector':'sector_id','Província':'province_id','Distrito':'district_id','Posto administrativo':'admin_post_id','Localidade':'locality_id'};
|
||||
return rows.map(row => {
|
||||
const key = lineageFields[row[1]];
|
||||
|
||||
@@ -60,6 +60,7 @@ export default function Catalogue({
|
||||
setInvestmentSelection(next); sessionStorage.setItem('investment-opportunity-selection', JSON.stringify(next));
|
||||
}
|
||||
const form = useForm({
|
||||
perspective: String(filters.perspective ?? ''),
|
||||
association_type: String(filters.association_type ?? ''),
|
||||
association_target: String(filters.association_target ?? ''),
|
||||
association_purpose: String(filters.association_purpose ?? ''),
|
||||
@@ -601,7 +602,7 @@ export default function Catalogue({
|
||||
</h2>
|
||||
<p>{r.summary}</p>
|
||||
<p className="font-semibold">{money(r)}</p>
|
||||
<p>{r.maturity_label}</p>
|
||||
<p>{r.proactive?(r.proactive.group==='ideas'?'Ideia em preparação':r.proactive.group==='needs'?'Necessidade identificada':'O que existe'):r.maturity_label}</p>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<Link
|
||||
className="underline"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {ProactiveSummary} from '@/components/proactive-investment';
|
||||
import EducationalGuides from '@/components/educational-guides';
|
||||
import InvestmentComplements, { type ComplementOption } from '@/components/investment-complements';
|
||||
import { searchTerritoryHref, investmentPreparationHref } from '@/lib/search-territory';
|
||||
@@ -53,6 +54,7 @@ export default function Detail({
|
||||
<Link href={returnUrl} className="underline">
|
||||
Voltar à pesquisa
|
||||
</Link>
|
||||
<ProactiveSummary value={r.proactive}/>
|
||||
{dossierOrigin && (
|
||||
<p>
|
||||
<Link
|
||||
|
||||
@@ -44,6 +44,7 @@ export type References = {
|
||||
sectors: { id: number; name: string; slug: string }[];
|
||||
};
|
||||
export type Opportunity = {
|
||||
proactive?: import('@/components/proactive-investment').ProactivePublic;
|
||||
id: number;
|
||||
title: string;
|
||||
slug: string;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {ProactiveSummary,proactiveView} from '@/components/proactive-investment';
|
||||
import {
|
||||
PreparationSummary,
|
||||
type Preparation,
|
||||
@@ -548,6 +549,8 @@ export default function InvestmentPath(path: Path) {
|
||||
/>
|
||||
)}
|
||||
{!!path.investment_context?.opportunity_choices?.length && <OpportunityChoices contextId={path.case.id} choices={path.investment_context.opportunity_choices}/>}
|
||||
{path.investment_context?.opportunity_choices?.map(choice=><ProactiveSummary key={choice.opportunity.key} value={proactiveView(choice.opportunity.analysis?.proactive)}/>)}
|
||||
{!path.investment_context?.opportunity_choices?.length&&<ProactiveSummary value={proactiveView(path.investment_context?.selection.opportunity?.analysis?.proactive)}/>}
|
||||
<SelectedComplements items={path.investment_context?.complements ?? []}/>
|
||||
<InvestmentRequirements assessment={path.investment_context?.requirements_assessment} contextId={path.case.id} excludedSteps={path.steps.filter((step) => !step.preparation_allowed).map((step) => step.code)}/>
|
||||
{!!path.content_sources?.length && (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {ProactiveInvestmentEditor,type ProactiveAnalysis,type ProactiveOptions} from '@/components/proactive-investment';
|
||||
import { ClassificationReview } from '@/components/opportunity-classification';
|
||||
import { createOperationKey } from '@/lib/operation-key';
|
||||
import { valueText } from '@/lib/value-text';
|
||||
@@ -25,6 +26,8 @@ type Entry = {
|
||||
};
|
||||
export default function OpportunityDraft({
|
||||
record,
|
||||
proactiveOptions,
|
||||
proactiveHistory,
|
||||
values,
|
||||
etag,
|
||||
readOnly,
|
||||
@@ -38,6 +41,8 @@ export default function OpportunityDraft({
|
||||
maturityCatalogue,
|
||||
}: {
|
||||
record: Entry | null;
|
||||
proactiveOptions?: ProactiveOptions;
|
||||
proactiveHistory?: {version:number;at:string;state:string;problem:string;confirmation:string}[];
|
||||
values: Values;
|
||||
etag: string | null;
|
||||
readOnly: boolean;
|
||||
@@ -474,6 +479,13 @@ export default function OpportunityDraft({
|
||||
void send('save');
|
||||
}}
|
||||
>
|
||||
{profileMode&&Boolean(data.proactive)&&<fieldset disabled={busy||readOnly||unavailable} className="space-y-3 rounded border p-4"><legend>Contexto existente da análise</legend>
|
||||
<Field label="Título da análise"><input aria-label="Título da análise" className={control} value={String((data.canonical as Record<string,unknown>|undefined)?.official_title??data.title??'')} onChange={e=>{const title=e.target.value;setData(d=>({...d,title,...(d.canonical&&Object.prototype.hasOwnProperty.call(d.canonical,'official_title')?{canonical:{...(d.canonical as Record<string,unknown>),official_title:title}}:{})}));}}/></Field>
|
||||
<Field label="Sector da análise"><select aria-label="Sector da análise" className={control} value={String(data.sector_id??'')} onChange={e=>setData(d=>({...d,sector_id:e.target.value,...(d.canonical?{canonical:{...(d.canonical as Record<string,unknown>),sector_id:Number(e.target.value)||null}}:{})}))}><option value="">Por determinar</option>{sectors.map(s=><option key={s.id} value={s.id}>{s.name}</option>)}</select></Field>
|
||||
<p>Seleccione apenas o nível territorial conhecido; não exige coordenadas, montante ou promotor.</p>
|
||||
{(['province_id','district_id','admin_post_id','locality_id']as const).map((key,index)=><TerritoryLevel key={`proactive-${key}-${path[index-1]?.id??''}`} index={index} parent={path[index-1]?.id??''} selected={path[index]} endpoint="/minhas-oportunidades/territory-options" fieldError={errors[key]} onChange={value=>{const next=[...path.slice(0,index),...(value?[value]:[])];setPath(next);setData(d=>({...d,province_id:next[0]?.id??'',district_id:next[1]?.id??'',admin_post_id:next[2]?.id??'',locality_id:next[3]?.id??''}));}}/>)}
|
||||
</fieldset>}
|
||||
<fieldset disabled={busy || readOnly || unavailable}><ProactiveInvestmentEditor value={data.proactive as ProactiveAnalysis|undefined} onChange={v=>setData(d=>({...d,proactive:v}))} options={proactiveOptions} history={proactiveHistory}/></fieldset>
|
||||
{!profileMode && (
|
||||
<fieldset
|
||||
disabled={busy || readOnly || unavailable}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import {ProactivePublicationFields,ProactiveSummary,newPublicProactive,type ProactivePublic,type ProactiveEvidence,type ProactiveOptions} from '@/components/proactive-investment';
|
||||
import { Link, router } from '@inertiajs/react';
|
||||
import { useState } from 'react';
|
||||
import { createOperationKey } from '@/lib/operation-key';
|
||||
import { profileJson, ProfileValidationError } from '@/lib/profile-json';
|
||||
import { Management, Field, control, button } from './shared';
|
||||
|
||||
type Draft = {title: string; summary: string; description: string; limitations: string; source_reference: string; edition: string; source_date: string; sector_id: number | null; territory_ids: string[]};
|
||||
type Projection = {title: string; summary: string; description: string; sector_id: number | null; maturity_label: string; territories: {id: string; label: string}[]};
|
||||
type Draft = {proactive_public?:ProactivePublic;proactive_reviewed?:boolean;title: string; summary: string; description: string; limitations: string; source_reference: string; edition: string; source_date: string; sector_id: number | null; territory_ids: string[]};
|
||||
type Projection = {title: string; summary: string; description: string; sector_id: number | null; maturity_label: string; territories: {id: string; label: string}[];proactive?:ProactivePublic};
|
||||
type Preview = {token: string; action: 'disclose' | 'withdraw'; projection: Projection; current: {title: string; summary: string; description: string; status: string}};
|
||||
|
||||
export default function OpportunityPromotion({record, initial, etag, publicNow, reauthenticationRequired, sectors, territories, history}: {
|
||||
export default function OpportunityPromotion({proactiveEnabled=false,proactiveKind,proactiveRelations=[],proactiveEvidence=[],proactiveOptions,record, initial, etag, publicNow, reauthenticationRequired, sectors, territories, history}: {
|
||||
proactiveRelations?:{id:string;label:string;relationship:string}[];proactiveEnabled?:boolean;proactiveKind?:string;proactiveEvidence?:ProactiveEvidence[];proactiveOptions?:ProactiveOptions;
|
||||
record: {id: number; reference: string}; initial: Draft; etag: string; publicNow: boolean; reauthenticationRequired: boolean;
|
||||
sectors: {id: number; name: string}[]; territories: {id: string; name: string; location_type: string}[];
|
||||
history: {id: string; action: string; actor_user_id: number; occurred_at: string}[];
|
||||
}) {
|
||||
const [draft, setDraft] = useState<Draft>({...initial, source_date: initial.source_date ?? ''});
|
||||
const [draft, setDraft] = useState<Draft>({...initial, source_date: initial.source_date ?? '',...(proactiveEnabled?{proactive_public:initial.proactive_public??{...newPublicProactive(),group:proactiveKind??'ideas'},proactive_reviewed:false}:{})});
|
||||
const [preview, setPreview] = useState<Preview | null>(null);
|
||||
const [operationKey, setOperationKey] = useState(createOperationKey);
|
||||
const [reason, setReason] = useState('');
|
||||
@@ -45,6 +47,7 @@ export default function OpportunityPromotion({record, initial, etag, publicNow,
|
||||
{needsMfa && <p role="alert">Entre novamente com a sua conta e MFA para confirmar esta operação. O cadastro guardado permanece disponível; a prévia ainda não confirmada terá de ser preparada novamente. <button className="underline" onClick={renewAuthentication}>Renovar entrada com MFA</button></p>}
|
||||
{Object.entries(errors).map(([key,value]) => <p role="alert" key={key}>{key}: {value}</p>)}
|
||||
<form className="space-y-4 rounded border p-5" onSubmit={e=>{e.preventDefault(); void prepare('disclose');}}>
|
||||
{proactiveEnabled&&draft.proactive_public&&<ProactivePublicationFields value={draft.proactive_public} onChange={v=>{change('proactive_public',v);change('proactive_reviewed',false);}} evidence={proactiveEvidence} relations={proactiveRelations} options={proactiveOptions} reviewed={Boolean(draft.proactive_reviewed)} onReview={v=>change('proactive_reviewed',v)}/>}
|
||||
<Field label="Título público"><input required className={control} maxLength={255} value={draft.title} onChange={e=>change('title',e.target.value)}/></Field>
|
||||
<Field label="Resumo público"><textarea required className={control} maxLength={499} value={draft.summary} onChange={e=>change('summary',e.target.value)}/></Field>
|
||||
<Field label="Descrição pública"><textarea className={control} maxLength={6000} value={draft.description} onChange={e=>change('description',e.target.value)}/></Field>
|
||||
@@ -62,6 +65,7 @@ export default function OpportunityPromotion({record, initial, etag, publicNow,
|
||||
{preview && <section className="space-y-4 rounded border p-5" aria-label="Prévia da divulgação">
|
||||
<h2 className="text-xl font-semibold">{preview.action === 'withdraw' ? 'Rever retirada do catálogo' : 'Prévia do conteúdo público'}</h2>
|
||||
<p><strong>{preview.projection.maturity_label}</strong></p>
|
||||
<ProactiveSummary value={preview.projection.proactive}/>
|
||||
<h3>{preview.projection.title}</h3><p>{preview.projection.summary}</p><p className="whitespace-pre-wrap">{preview.projection.description}</p>
|
||||
<p>Sector: {sectors.find(s=>s.id===preview.projection.sector_id)?.name ?? 'Por indicar'}</p>
|
||||
<ul>{preview.projection.territories.map(t=><li key={t.id}>{t.label}</li>)}</ul>
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Tests\TestCase;
|
||||
|
||||
final class IrpcAnnualSettlementDraftTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
public function test_annual_simulated_balances_round_trip_with_proofs_states_and_preserved_books(): void
|
||||
{
|
||||
$target=DB::selectOne('select current_database() as name,inet_server_port() as port');
|
||||
$this->assertSame('simulator_fiscal_delta_20261021_test',$target->name);
|
||||
$this->assertSame(55441,(int)$target->port);
|
||||
config(['investor-path.enabled'=>true,'suitecrm.enabled'=>false]);
|
||||
$this->actingAs(User::factory()->create(['email_verified_at'=>now()]));
|
||||
$id=null;$etag=null;
|
||||
foreach(['payable','recoverable','balanced','absent','missing','duplicate','pec']as$case){
|
||||
$d=json_decode(file_get_contents(base_path('outputs/irpc-l8-settlement/'.$case.'.json')),true,flags:JSON_THROW_ON_ERROR);
|
||||
$personal=['person_type'=>$d['person_type']];unset($d['person_type']);
|
||||
if($id===null)$id=$this->postJson('/api/v1/simulation-drafts',['personal_snapshot'=>$personal,'economic_snapshot'=>$d],['Idempotency-Key'=>(string)Str::uuid()])->assertCreated()->json('data.id');
|
||||
else $this->putJson('/api/v1/simulation-drafts/'.$id,['personal_snapshot'=>$personal,'economic_snapshot'=>$d],['If-Match'=>$etag])->assertOk();
|
||||
$r=$this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk();$etag=$r->headers->get('ETag');$back=$r->json('data.economic_snapshot');
|
||||
$this->assertSame($d['modelo_a_snapshot'],$back['modelo_a_snapshot']);
|
||||
$this->assertSame($d['business_plan_snapshot'],$back['business_plan_snapshot']);
|
||||
$before=json_decode($d['modelo_a_snapshot'],true,flags:JSON_THROW_ON_ERROR);
|
||||
$s=json_decode($back['modelo_a_snapshot'],true,flags:JSON_THROW_ON_ERROR);$scope=$d['context_opportunity'];
|
||||
$b=$s['irpcAnnual'][$scope];$m=$b['result']['model'];
|
||||
foreach(['irpcNormal','irpcWithholdings','books','currencyEvents','ispcQuarters']as$map)$this->assertSame($before[$map],$s[$map]);
|
||||
$this->assertSame('IRPC-annual-settlement/1',$m['version']);
|
||||
$this->assertSame('123456789',$m['subjectNuit']);$this->assertSame('2026',$m['year']);
|
||||
$this->assertSame(['numerator'=>'1408','denominator'=>'1'],$m['assessment']['colecta']);
|
||||
$this->assertFalse($m['officialBalancesConsumed']);$this->assertFalse($m['submitted']);$this->assertFalse($m['refundReceived']);
|
||||
$this->assertSame('known',$m['input']['credits']['state']);$this->assertSame('0',$m['input']['credits']['amount']);
|
||||
if(in_array($case,['missing','duplicate','pec'],true)){
|
||||
$this->assertSame('indeterminate',$m['status']);$this->assertNotEmpty($m['pending']);
|
||||
$this->assertNull($m['arithmeticBalance']);$this->assertNull($m['payable']);$this->assertNull($m['recoverable']);
|
||||
if($case==='missing')$this->assertSame('',$m['input']['ppc']['rows'][0]['effective']);
|
||||
if($case==='pec')$this->assertSame('10',$m['input']['pec']['amount']);
|
||||
if($case==='duplicate')$this->assertCount(2,$m['input']['ppc']['rows']);
|
||||
}else{
|
||||
$this->assertEmpty($m['pending']);
|
||||
$this->assertSame(['payable'=>'payable','recoverable'=>'recoverable','balanced'=>'balanced','absent'=>'payable'][$case],$m['status']);
|
||||
$this->assertSame(['numerator'=>['payable'=>'608','recoverable'=>'-192','balanced'=>'0','absent'=>'1408'][$case],'denominator'=>'1'],$m['arithmeticBalance']);
|
||||
$this->assertSame(['numerator'=>$case==='recoverable'?'192':'0','denominator'=>'1'],$m['recoverable']);
|
||||
if($case==='absent'){$this->assertSame('absent',$m['input']['withholdings']['state']);$this->assertSame('absent',$m['input']['ppc']['state']);}
|
||||
else{$this->assertSame('yes',$m['input']['withholdings']['rows'][0]['incomeIncluded']);$this->assertSame('yes',$m['input']['ppc']['rows'][0]['effective']);}
|
||||
}
|
||||
file_put_contents(base_path('outputs/irpc-l8-settlement/recovered-'.$case.'.json'),json_encode($back,JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\Opportunity;
|
||||
use App\Models\User;
|
||||
use App\Services\OpportunityManagement;
|
||||
use App\Services\ProactiveInvestment;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Tests\Support\ProactiveInvestmentFixture as F;
|
||||
use Tests\TestCase;
|
||||
|
||||
final class ProactiveInvestmentTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
private User $actor;
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();F::guard();$this->withoutVite();
|
||||
config(['portal.profile_access_enabled'=>true,'portal.opportunity_specialized_drafts_enabled'=>true,'portal.managers'=>[],'investor-path.enabled'=>true,'suitecrm.enabled'=>false,'investmoz_ai.enabled'=>false]);
|
||||
$this->actor=F::operator();$this->login($this->actor);
|
||||
}
|
||||
private function login(User $u): void {$this->actingAs($u)->withSession(['portal.mfa_actor'=>$u->id,'portal.mfa_at'=>time(),'portal.access_revision'=>(int)$u->portal_access_revision]);}
|
||||
private function create(string $pilot='Cahora Bassa'): Opportunity
|
||||
{
|
||||
$response=$this->postJson('/minhas-oportunidades/drafts',F::input($pilot));if($response->status()!==201)fwrite(STDERR,substr($response->getContent(),0,400)."\n");$id=$response->assertCreated()->json('id');return Opportunity::findOrFail($id);
|
||||
}
|
||||
private function publication(Opportunity $o,array $patch=[]): array
|
||||
{
|
||||
$a=app(OpportunityManagement::class)->values($o)['proactive'];
|
||||
return [...['etag'=>app(OpportunityManagement::class)->etag($o),'action'=>'disclose','title'=>$o->title,'summary'=>'SYNTHETIC QA ideia em preparação; não é oportunidade com participação disponível.','description'=>'Conteúdo público expressamente redigido.','limitations'=>'Conclusões locais por confirmar.','source_reference'=>'SYNTHETIC QA exemplo público','edition'=>'QA1','source_date'=>'2026-10-27','sector_id'=>$o->sector_id,'territory_ids'=>[$o->primary_territory_id]],...F::publication($a),...$patch];
|
||||
}
|
||||
private function publish(Opportunity $o): array
|
||||
{
|
||||
$p=$this->postJson('/minhas-oportunidades/'.$o->id.'/divulgacao/previa',$this->publication($o))->assertOk()->json();
|
||||
$input=['token'=>$p['token'],'operation_key'=>(string)Str::uuid(),'confirm'=>true,'reason'=>'SYNTHETIC QA explicit public projection reviewed without private information'];
|
||||
$this->postJson('/minhas-oportunidades/'.$o->id.'/divulgacao/confirmar',$input)->assertOk();return $input;
|
||||
}
|
||||
public function test_legacy_records_without_analysis_add_no_publication_lookup(): void
|
||||
{
|
||||
$o=new Opportunity;$o->forceFill(['workflow_context'=>[]]);DB::enableQueryLog();DB::flushQueryLog();
|
||||
$this->assertNull(app(ProactiveInvestment::class)->publicData($o));$this->assertSame([],DB::getQueryLog());DB::disableQueryLog();
|
||||
}
|
||||
public function test_create_recover_edit_with_etag_and_historical_foundation_without_financial_or_promoter_requirements(): void
|
||||
{
|
||||
$o=$this->create();$a=app(OpportunityManagement::class)->values($o)['proactive'];$tag=app(OpportunityManagement::class)->etag($o);
|
||||
$this->assertNull($o->estimated_investment_amount);$this->assertNull($o->promoter_name);$this->assertNotNull($o->primary_territory_id);
|
||||
$this->get('/minhas-oportunidades/'.$o->id.'/edit')->assertOk()->assertInertia(fn($page)=>$page->where('values.proactive.need.state','hypothesis')->has('proactiveHistory',1));
|
||||
$a['need']['state']='confirmed';$a['need']['confirmation']='SYNTHETIC QA confirmation of fixture conditions only, no real market validation.';
|
||||
$this->putJson('/minhas-oportunidades/'.$o->id.'/draft',['etag'=>$tag,'proactive'=>$a,'reason'=>'SYNTHETIC QA updated documented foundation for this fixture only'])->assertOk();
|
||||
$this->assertSame('confirmed',app(OpportunityManagement::class)->values($o->fresh())['proactive']['need']['state']);
|
||||
$history=app(ProactiveInvestment::class)->history($o);$this->assertCount(2,$history);$this->assertSame('hypothesis',$history[1]['state']);
|
||||
$this->putJson('/minhas-oportunidades/'.$o->id.'/draft',['etag'=>$tag,'proactive'=>$a,'reason'=>'SYNTHETIC QA stale version cannot overwrite current analysis'])->assertStatus(409);
|
||||
}
|
||||
public function test_hypothesis_cannot_be_confirmed_without_documented_conditions_and_missing_is_not_zero(): void
|
||||
{
|
||||
$o=$this->create();$a=app(OpportunityManagement::class)->values($o)['proactive'];$a['need']['state']='confirmed';$a['need']['observed_demand']='';
|
||||
$this->putJson('/minhas-oportunidades/'.$o->id.'/draft',['etag'=>app(OpportunityManagement::class)->etag($o),'proactive'=>$a,'reason'=>'SYNTHETIC QA incomplete confirmation must preserve prior hypothesis'])->assertUnprocessable();
|
||||
$this->assertSame('hypothesis',app(OpportunityManagement::class)->values($o->fresh())['proactive']['need']['state']);
|
||||
$a['need']['state']='hypothesis';$a['idea']['resources']='';$this->putJson('/minhas-oportunidades/'.$o->id.'/draft',['etag'=>app(OpportunityManagement::class)->etag($o),'proactive'=>$a,'reason'=>'SYNTHETIC QA unknown resource remains blank rather than zero'])->assertOk();
|
||||
$this->assertNull(app(OpportunityManagement::class)->values($o->fresh())['proactive']['idea']['resources']);
|
||||
}
|
||||
public function test_methodology_alone_cannot_confirm_local_need(): void
|
||||
{
|
||||
$o=$this->create();$a=app(OpportunityManagement::class)->values($o)['proactive'];$a['need']['state']='confirmed';$a['evidence'][0]['purpose']='methodology';
|
||||
$this->putJson('/minhas-oportunidades/'.$o->id.'/draft',['etag'=>app(OpportunityManagement::class)->etag($o),'proactive'=>$a,'reason'=>'SYNTHETIC QA international methodology is not evidence of local demand'])->assertUnprocessable();
|
||||
$this->assertSame('hypothesis',app(OpportunityManagement::class)->values($o->fresh())['proactive']['need']['state']);
|
||||
}
|
||||
public function test_creation_replay_and_duplicate_evidence_and_relations_do_not_duplicate_analysis(): void
|
||||
{
|
||||
$input=F::input();$id=$this->postJson('/minhas-oportunidades/drafts',$input)->assertCreated()->json('id');$this->postJson('/minhas-oportunidades/drafts',$input)->assertCreated()->assertJsonPath('id',$id);
|
||||
$o=Opportunity::findOrFail($id);$a=$input['proactive'];$a['evidence'][]=[...$a['evidence'][0],'id'=>(string)Str::uuid()];
|
||||
$this->putJson('/minhas-oportunidades/'.$id.'/draft',['etag'=>app(OpportunityManagement::class)->etag($o),'proactive'=>$a,'reason'=>'SYNTHETIC QA repeated evidence must be reconciled, not counted twice'])->assertUnprocessable();
|
||||
$this->assertSame(1,Opportunity::where('management_creation_key',$input['creation_key'])->count());
|
||||
}
|
||||
public function test_document_from_another_scope_cannot_be_attached_or_reclassified_as_public(): void
|
||||
{
|
||||
$o=$this->create();$a=app(OpportunityManagement::class)->values($o)['proactive'];$a['evidence'][0]['document_id']=(string)Str::uuid();
|
||||
$this->putJson('/minhas-oportunidades/'.$o->id.'/draft',['etag'=>app(OpportunityManagement::class)->etag($o),'proactive'=>$a,'reason'=>'SYNTHETIC QA document association must use existing access rules'])->assertUnprocessable();
|
||||
}
|
||||
public function test_existing_permissions_reject_unassigned_and_unrelated_operators(): void
|
||||
{
|
||||
$o=$this->create();$this->login(User::factory()->create());
|
||||
$this->postJson('/minhas-oportunidades/drafts',F::input())->assertForbidden();
|
||||
$this->get('/minhas-oportunidades/'.$o->id.'/edit')->assertForbidden();
|
||||
$this->login(F::operator());$this->get('/minhas-oportunidades/'.$o->id.'/edit')->assertForbidden();
|
||||
$this->login($this->actor);$input=F::input();unset($input['proactive']);$this->postJson('/minhas-oportunidades/drafts',$input)->assertForbidden();
|
||||
$this->assertNull($o->organization_id);
|
||||
}
|
||||
public function test_internal_attached_document_cannot_be_changed_to_public_through_analysis(): void
|
||||
{
|
||||
$o=$this->create();$doc=(string)Str::uuid();$hash=hash('sha256','SYNTHETIC QA private source');
|
||||
DB::table('documents')->insert(['id'=>$doc,'file_name'=>'SYNTHETIC-QA-INTERNAL-LIST.txt','storage_key'=>'synthetic-qa/'.$doc,'media_type'=>'text/plain','sha256'=>$hash,'size_bytes'=>strlen('SYNTHETIC QA private source'),'uploaded_by'=>$this->actor->id,'status'=>'active','data_classification'=>'internal','malware_scan_status'=>'clean','malware_scanned_sha256'=>$hash]);
|
||||
DB::table('opportunity_documents')->insert(['id'=>(string)Str::uuid(),'opportunity_id'=>$o->id,'document_id'=>$doc,'version'=>1,'created_by'=>$this->actor->id,'payload'=>json_encode(['title'=>'SYNTHETIC QA internal list','visibility'=>'internal'])]);
|
||||
$a=app(OpportunityManagement::class)->values($o)['proactive'];$a['evidence'][0]['document_id']=$doc;$a['evidence'][0]['access']='public';
|
||||
$this->putJson('/minhas-oportunidades/'.$o->id.'/draft',['etag'=>app(OpportunityManagement::class)->etag($o),'proactive'=>$a,'reason'=>'SYNTHETIC QA original document restrictions cannot be overridden here'])->assertUnprocessable();
|
||||
$this->assertSame('internal',DB::table('documents')->where('id',$doc)->value('data_classification'));
|
||||
}
|
||||
public function test_selected_public_relationship_and_assumptions_travel_without_private_reference_or_duplicate(): void
|
||||
{
|
||||
$o=$this->create();$a=app(OpportunityManagement::class)->values($o)['proactive'];$target=app(\App\Services\OpportunityClassification::class)->targets('project')->first(['id','name']);$this->assertNotNull($target);
|
||||
$r=['id'=>(string)Str::uuid(),'kind'=>'project','target_id'=>$target->id,'relation'=>'hypothesis','reference'=>'PRIVATE-QA-RELATION-REFERENCE-NOT-FOR-PUBLICATION','evidence_ids'=>[$a['evidence'][0]['id']]];$a['relations']=[$r];
|
||||
$this->putJson('/minhas-oportunidades/'.$o->id.'/draft',['etag'=>app(OpportunityManagement::class)->etag($o),'proactive'=>$a,'reason'=>'SYNTHETIC QA reference is a hypothesis, not access or contract'])->assertOk();$o->refresh();
|
||||
$bad=$a;$bad['relations'][]=[...$r,'id'=>(string)Str::uuid()];$this->putJson('/minhas-oportunidades/'.$o->id.'/draft',['etag'=>app(OpportunityManagement::class)->etag($o),'proactive'=>$bad,'reason'=>'SYNTHETIC QA same reference cannot appear twice in the same analysis'])->assertUnprocessable();
|
||||
$d=$this->publication($o);$d['proactive_public']=[...$d['proactive_public'],'relation_ids'=>[$r['id']],'resources'=>'SYNTHETIC QA public resource, no guaranteed capacity.','assumptions'=>'No contract, land or power guaranteed.','conditions'=>'Confirm actual local evidence.'];
|
||||
$p=$this->postJson('/minhas-oportunidades/'.$o->id.'/divulgacao/previa',$d)->assertOk()->json();$this->assertSame($target->name,$p['projection']['proactive']['relations'][0]['label']);$this->assertStringNotContainsString('PRIVATE-QA-RELATION',json_encode($p['projection']));
|
||||
$this->postJson('/minhas-oportunidades/'.$o->id.'/divulgacao/confirmar',['token'=>$p['token'],'operation_key'=>(string)Str::uuid(),'confirm'=>true,'reason'=>'SYNTHETIC QA explicitly reviewed public relationship and assumptions'])->assertOk();
|
||||
$ref=app(\App\Services\InvestorContext::class)->reference('opportunity:'.$o->id);$this->assertSame('hypothesis',$ref['analysis']['proactive']['relations'][0]['relationship']);$this->assertSame('No contract, land or power guaranteed.',$ref['analysis']['proactive']['assumptions']);
|
||||
}
|
||||
public function test_publication_needs_explicit_review_and_rejects_internal_source_and_literal_leakage(): void
|
||||
{
|
||||
$o=$this->create();$data=$this->publication($o);unset($data['proactive_reviewed']);$this->postJson('/minhas-oportunidades/'.$o->id.'/divulgacao/previa',$data)->assertUnprocessable();
|
||||
$data=$this->publication($o);$a=app(OpportunityManagement::class)->values($o)['proactive'];$data['proactive_public']['evidence_ids']=[$a['evidence'][1]['id']];$this->postJson('/minhas-oportunidades/'.$o->id.'/divulgacao/previa',$data)->assertUnprocessable();
|
||||
$data=$this->publication($o,['description'=>$a['evidence'][1]['statement']]);$this->postJson('/minhas-oportunidades/'.$o->id.'/divulgacao/previa',$data)->assertUnprocessable();
|
||||
$data=$this->publication($o);$data['proactive_public']['state']='confirmed';$this->postJson('/minhas-oportunidades/'.$o->id.'/divulgacao/previa',$data)->assertUnprocessable();
|
||||
}
|
||||
public function test_public_snapshot_separate_from_private_edits_and_anonymous_access_no_coordinates_required(): void
|
||||
{
|
||||
$o=$this->create();$private=$o->management_draft;$confirm=$this->publish($o);$this->postJson('/minhas-oportunidades/'.$o->id.'/divulgacao/confirmar',$confirm)->assertOk()->assertJsonPath('replayed',true);
|
||||
$o->refresh();$this->assertSame($private,$o->management_draft);$this->assertFalse(app(ProactiveInvestment::class)->publicData($o)['economic_validation']);
|
||||
$a=app(OpportunityManagement::class)->values($o)['proactive'];$a['idea']['solution']='PRIVATE-QA-NEW-UNPUBLISHED-SOLUTION';
|
||||
$this->putJson('/minhas-oportunidades/'.$o->id.'/draft',['etag'=>app(OpportunityManagement::class)->etag($o),'proactive'=>$a,'reason'=>'SYNTHETIC QA private update must not change published projection'])->assertOk();
|
||||
$this->app['auth']->forgetGuards();$this->get('/oportunidades/'.$o->slug)->assertOk()->assertDontSee('PRIVATE-QA-');
|
||||
$this->get('/minhas-oportunidades/'.$o->id.'/edit')->assertRedirect('/login');
|
||||
$this->assertNotNull(app(ProactiveInvestment::class)->publicData($o->fresh()));
|
||||
}
|
||||
public function test_three_synthetic_pilots_reuse_existing_territories_and_catalogue_groups(): void
|
||||
{
|
||||
foreach(['Cahora Bassa','Montepuez','Gurué']as$pilot){$o=$this->create($pilot);$this->publish($o);$this->assertNotNull($o->fresh()->primary_territory_id);$this->assertTrue(app(\App\Services\InvestmentCatalogue::class)->query(['perspective'=>'ideas'])->whereKey($o->id)->exists());$this->assertFalse(app(\App\Services\InvestmentCatalogue::class)->query(['perspective'=>'needs'])->whereKey($o->id)->exists());}
|
||||
$this->get('/oportunidades?perspective=ideas')->assertOk();
|
||||
}
|
||||
public function test_existing_facts_and_needs_do_not_require_irrelevant_idea_fields(): void
|
||||
{
|
||||
foreach(['exists','needs']as$kind){
|
||||
$input=F::input();$input['proactive']['kind']=$kind;$id=$this->postJson('/minhas-oportunidades/drafts',$input)->assertCreated()->json('id');$o=Opportunity::findOrFail($id);
|
||||
$d=$this->publication($o);unset($d['proactive_public']['proposal']);if($kind==='exists')unset($d['proactive_public']['need']);
|
||||
$p=$this->postJson('/minhas-oportunidades/'.$id.'/divulgacao/previa',$d)->assertOk()->json();$this->assertSame($kind,$p['projection']['proactive']['group']);$this->assertSame('',$p['projection']['proactive']['proposal']);
|
||||
$this->postJson('/minhas-oportunidades/'.$id.'/divulgacao/confirmar',['token'=>$p['token'],'operation_key'=>(string)Str::uuid(),'confirm'=>true,'reason'=>'SYNTHETIC QA only applicable questions for this content group'])->assertOk();
|
||||
$this->assertTrue(app(\App\Services\InvestmentCatalogue::class)->query(['perspective'=>$kind])->whereKey($id)->exists());
|
||||
}
|
||||
}
|
||||
public function test_private_analysis_complements_keep_preparation_valid_without_inventing_public_offers(): void
|
||||
{
|
||||
$private=$this->create('Gurué');$public=$this->create();
|
||||
$input=$this->publication($public,['summary'=>'SYNTHETIC QA: silos e armazenagem como componente documentada.']);
|
||||
$plan=$this->postJson('/minhas-oportunidades/'.$public->id.'/divulgacao/previa',$input)->assertOk()->json();
|
||||
$this->postJson('/minhas-oportunidades/'.$public->id.'/divulgacao/confirmar',['token'=>$plan['token'],'operation_key'=>(string)Str::uuid(),'confirm'=>true,'reason'=>'SYNTHETIC QA public component in transaction only'])->assertOk();
|
||||
$result=$this->postJson('/complementos-investimento',['contexts'=>[['origin'=>'opportunity:'.$private->id],['origin'=>'opportunity:'.$public->id]]])->assertOk()->json();
|
||||
$this->assertSame([],$result['issues']);$this->assertNotEmpty($result['items']);
|
||||
foreach($result['items']as$item)$this->assertSame('opportunity:'.$public->id,$item['origin']['key']);
|
||||
$this->assertStringNotContainsString('PRIVATE-QA-',json_encode($result));
|
||||
$this->assertFalse(Opportunity::published()->whereKey($private->id)->exists());
|
||||
$this->assertSame('draft',$private->fresh()->status);
|
||||
}
|
||||
public function test_private_analysis_complements_still_hide_unauthorised_sources(): void
|
||||
{
|
||||
$private=$this->create('Gurué');$this->login(User::factory()->create());
|
||||
$this->postJson('/complementos-investimento',['origin'=>'opportunity:'.$private->id])->assertNotFound();
|
||||
$result=$this->postJson('/complementos-investimento',['contexts'=>[['origin'=>'opportunity:'.$private->id]]])->assertOk()->json();
|
||||
$this->assertSame([],$result['items']);$this->assertCount(1,$result['issues']);
|
||||
$this->assertStringNotContainsString($private->title,json_encode($result));
|
||||
$this->assertStringNotContainsString('PRIVATE-QA-',json_encode($result));
|
||||
}
|
||||
public function test_authenticated_multi_idea_preparation_keeps_each_origin_and_deliberate_edits_in_existing_dossier(): void
|
||||
{
|
||||
$first=$this->create();$second=$this->create('Gurué');$this->publish($first);$this->publish($second);$investor=User::factory()->create();$this->login($investor);
|
||||
$key=(string)Str::uuid();$create=['title'=>'SYNTHETIC QA deliberately chosen project title','client_key'=>$key,'reuse_consent'=>true];
|
||||
$id=$this->postJson('/investimentos',$create)->assertCreated()->json('id');$this->postJson('/investimentos',$create)->assertCreated()->assertJsonPath('id',$id);
|
||||
$before=$this->getJson('/investimentos/'.$id.'/contexto')->assertOk()->json();
|
||||
$input=['version'=>$before['case']['version'],'selection'=>[],'opportunity_choices'=>array_map(fn($o)=>['source'=>'opportunity:'.$o->id,'territory'=>'territory:'.$o->primary_territory_id],[$first,$second])];
|
||||
$preview=$this->postJson('/investimentos/'.$id.'/contexto/previa',$input)->assertOk()->json();
|
||||
$this->assertCount(2,$preview['opportunity_choices']);$this->assertSame('SYNTHETIC QA deliberately chosen project title',$preview['fields']['project_title']);
|
||||
foreach($preview['opportunity_choices']as$c){$this->assertSame('ideas',$c['opportunity']['analysis']['proactive']['group']);$this->assertStringNotContainsString('PRIVATE-QA-',json_encode($c));}
|
||||
$confirm=[...$input,'preview_hash'=>$preview['preview_hash'],'operation_key'=>(string)Str::uuid(),'confirm'=>true];$this->postJson('/investimentos/'.$id.'/contexto/confirmar',$confirm)->assertOk();$this->postJson('/investimentos/'.$id.'/contexto/confirmar',$confirm)->assertOk()->assertJsonPath('replayed',true);
|
||||
$saved=$this->getJson('/investimentos/'.$id.'/contexto')->assertOk()->json();$this->assertCount(2,$saved['context']['opportunity_choices']);
|
||||
$consumers=[];foreach([$first,$second]as$record){$consumer=$this->getJson('/investimentos/'.$id.'/contexto?opportunity=opportunity:'.$record->id)->assertOk()->json();$snapshot=json_decode($consumer['prefill']['simulator']['context_applicability_snapshot'],true);$this->assertCount(1,$snapshot['opportunity_choices']);$this->assertSame('opportunity:'.$record->id,$snapshot['opportunity_choices'][0]['opportunity']['key']);$this->assertSame('ideas',$snapshot['opportunity_choices'][0]['opportunity']['analysis']['proactive']['group']);$this->assertArrayNotHasKey('tax_benefit',$consumer['prefill']['simulator']);$consumers[]=$consumer;}$saved['consumer_contexts']=$consumers;
|
||||
file_put_contents(base_path('outputs/proactive-investment-20261027/recovered-context.json'),json_encode($saved,JSON_UNESCAPED_UNICODE|JSON_THROW_ON_ERROR));
|
||||
$this->get('/investimentos/'.$id)->assertOk();$this->login($this->actor);$this->getJson('/investimentos/'.$id.'/contexto')->assertForbidden();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace Tests\Support;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Sector;
|
||||
use App\Services\OpportunityManagement;
|
||||
use App\Services\PortalProfileAdministration;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/** Synthetic fixture only, exclusively in the isolated QA database. */
|
||||
final class ProactiveInvestmentFixture
|
||||
{
|
||||
public static function guard(): void
|
||||
{
|
||||
$t=DB::selectOne('select current_database() as name,inet_server_port() as port');
|
||||
throw_unless($t->name==='proactive_investment_20261027_test'&&(int)$t->port===55441,\RuntimeException::class,'Isolated proactive QA required');
|
||||
}
|
||||
|
||||
public static function operator(): User
|
||||
{
|
||||
self::guard();
|
||||
$actor=User::factory()->create(['name'=>'SYNTHETIC QA editorial operator','email'=>'proactive-'.Str::uuid().'@example.invalid','password'=>bcrypt('Synthetic-QA-only-2026!')]);
|
||||
$actor->forceFill(['two_factor_secret'=>Crypt::encrypt('JBSWY3DPEHPK3PXP'),'two_factor_confirmed_at'=>now()])->save();
|
||||
$org=(string)Str::uuid();
|
||||
DB::table('organizations')->insert(['id'=>$org,'name'=>'SYNTHETIC QA proactivity operator','external_id'=>'SYNTHETIC-QA-'.$org,'organization_type'=>'private']);
|
||||
DB::table('audit_events')->insert(['source_system'=>'portal-profiles-v1','entity_type'=>'authorization','action'=>'operator_organization_registered','data_classification'=>'restricted','after_data'=>json_encode(['organization_id'=>$org,'organization'=>['name'=>'SYNTHETIC QA proactivity operator','nuit'=>'SYNTHETIC-QA-'.$org],'source_reference'=>'SYNTHETIC QA designation, not a real appointment'])]);
|
||||
app(PortalProfileAdministration::class)->insertGrant((string)Str::uuid(),User::factory()->create(),['user_id'=>$actor->id,'role'=>'promoter','organization_id'=>$org,'opportunity_types'=>OpportunityManagement::CATEGORIES,'responsibilities'=>[],'source'=>'internal-portal-designation']);
|
||||
return $actor;
|
||||
}
|
||||
|
||||
public static function analysis(string $pilot='Cahora Bassa'): array
|
||||
{
|
||||
$id=(string)Str::uuid();$private=(string)Str::uuid();
|
||||
return ['version'=>1,'kind'=>'ideas','evidence'=>[
|
||||
['id'=>$id,'category'=>'infrastructure','purpose'=>'local','statement'=>'SYNTHETIC QA: capacidade fictícia em '.$pilot.'; não é diagnóstico económico real.','interpretation'=>'Hipótese sintética, sem contrato ou oferta comprovados.','source'=>'SYNTHETIC QA exemplar público fictício '.$pilot,'locator'=>'Fixture QA, linha1','period'=>'Exercício2026 — cenário sintético','scope'=>$pilot.' — contexto piloto','coverage'=>'Cobertura fictícia; informação real por confirmar','verified_on'=>'2026-10-27','access'=>'public','document_id'=>null],
|
||||
['id'=>$private,'category'=>'supply','purpose'=>'local','statement'=>'PRIVATE-QA-UNIQUE-SUPPLY-'.Str::uuid(),'interpretation'=>'PRIVATE-QA-INTERPRETATION-'.Str::uuid(),'source'=>'PRIVATE-QA-COMPANY-LIST-'.Str::uuid(),'locator'=>'PRIVATE-QA-LOCATOR-'.Str::uuid(),'period'=>'2026','scope'=>'Análise interna','coverage'=>'Não divulgar','verified_on'=>'2026-10-27','access'=>'internal','document_id'=>null],
|
||||
],'need'=>['state'=>'hypothesis','problem'=>'SYNTHETIC QA lacuna por verificar em '.$pilot,'observed_supply'=>'Oferta real desconhecida; não equivale a ausência.','observed_demand'=>'Procura real não comprovada; cenário sintético.','type'=>'support','clients'=>'Beneficiários hipotéticos, sem encomenda ou compromisso.','evidence_ids'=>[$id],'limitations'=>'Não demonstra mercado nem viabilidade.','missing'=>'Dados locais reais por confirmar.','confirmation'=>'Fundamento de hipótese sintética, não confirmação económica.'],
|
||||
'idea'=>['solution'=>'SYNTHETIC QA: '.match($pilot){'Montepuez'=>'fornecimentos e manutenção mineira','Gurué'=>'serviços da cadeia do chá',default=>'serviços complementares de energia'},'activity'=>'Actividade hipotética de apoio','chain_id'=>null,'stage'=>'Serviços de apoio — por corresponder','coverage'=>$pilot,'mode'=>'create','resources'=>'Não demonstrados; por inventariar','assumptions'=>'Não há acesso garantido a energia, terra ou cliente.','conditions'=>'Confirmar dados e autorizações aplicáveis.','pending'=>'Evidência económica real','next_action'=>'Recolher dados locais e testar a hipótese.'],'relations'=>[]];
|
||||
}
|
||||
|
||||
public static function input(string $pilot='Cahora Bassa',bool $analysis=true): array
|
||||
{
|
||||
self::guard();
|
||||
$t=DB::table('geo_locations')->whereNull('deleted_at')->where('data_classification','public')->where('location_type','district')->where('name','ilike',$pilot==='Gurué'?'Guru%':($pilot==='Cahora Bassa'?'CAHORA-BASSA':$pilot))->first();
|
||||
throw_unless($t,\RuntimeException::class,'Existing pilot territory required:'.$pilot);
|
||||
$path=app(\App\Services\InvestmentGeography::class)->path($t->id,true);$geo=[];foreach($path as $n)if(in_array($n->location_type,['province','district','admin_post','locality']))$geo[$n->location_type.'_id']=$n->id;
|
||||
$s=Sector::choices()->whereNotNull('published_at')->where('slug',match($pilot){'Cahora Bassa'=>'energia-especifica','Montepuez'=>'mineracao',default=>'agronegocio'})->firstOrFail();
|
||||
return ['creation_key'=>(string)Str::uuid(),'reason'=>'SYNTHETIC QA creating an independent territorial analysis, no active publication','title'=>'SYNTHETIC QA — '.$pilot,'summary'=>'Piloto técnico sintético; conclusões económicas reais por confirmar.','description'=>'Preparação editorial sintética em QA.','sector_id'=>$s->id,'opportunity_category'=>'investment_project',...$geo,...($analysis?['proactive'=>self::analysis($pilot)]:[])];
|
||||
}
|
||||
|
||||
public static function publication(array $analysis): array
|
||||
{
|
||||
return ['proactive_reviewed'=>true,'proactive_public'=>['group'=>$analysis['kind'],'state'=>'hypothesis','need'=>'SYNTHETIC QA necessidade por verificar.','proposal'=>'SYNTHETIC QA solução em preparação.','basis'=>'Fixture pública sintética; não é evidência de procura local.','limitations'=>'Sem validação económica, contrato, terra ou energia garantidos.','next_action'=>'Confirmar evidências reais antes de decidir.','evidence_ids'=>[$analysis['evidence'][0]['id']],'chain_id'=>null,'stage'=>'Apoio — correspondência real por confirmar']];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"fixture_notice": "Synthetic public projection of accepted API QA consumers;no profiles,real pilots,credentials,dossier or personal data. Test input only;never import into application data.",
|
||||
"consumer_contexts": [
|
||||
{
|
||||
"prefill": {
|
||||
"simulator": {
|
||||
"context_applicability_snapshot": "{\"version\":1,\"consumer_opportunity\":\"opportunity:399\",\"opportunity_choices\":[{\"opportunity\":{\"key\":\"opportunity:399\",\"title\":\"SYNTHETIC QA — Cahora Bassa\",\"version\":2,\"analysis\":{\"proactive\":{\"need\":\"SYNTHETIC QA necessidade por verificar.\",\"basis\":\"Fixture pública sintética; não é evidência de procura local.\",\"group\":\"ideas\",\"stage\":\"Apoio — correspondência real por confirmar\",\"state\":\"hypothesis\",\"notice\":\"A ausência de registo não comprova ausência de oferta. Proximidade não comprova contrato, participação, energia acessível, terra disponível ou benefício fiscal. Necessidade confirmada não comprova viabilidade comercial; hipótese de fornecimento não é encomenda.\",\"version\":1,\"chain_id\":null,\"evidence\":[{\"id\":\"3587d2e4-7428-4cd7-994b-60607b20d7da\",\"scope\":\"Cahora Bassa — contexto piloto\",\"period\":\"Exercício2026 — cenário sintético\",\"source\":\"SYNTHETIC QA exemplar público fictício Cahora Bassa\",\"locator\":\"Fixture QA, linha1\",\"purpose\":\"local\",\"category\":\"infrastructure\",\"coverage\":\"Cobertura fictícia; informação real por confirmar\",\"statement\":\"SYNTHETIC QA: capacidade fictícia em Cahora Bassa; não é diagnóstico económico real.\",\"verified_on\":\"2026-10-27\"}],\"proposal\":\"SYNTHETIC QA solução em preparação.\",\"relations\":[],\"limitations\":\"Sem validação económica, contrato, terra ou energia garantidos.\",\"next_action\":\"Confirmar evidências reais antes de decidir.\",\"evidence_ids\":[\"3587d2e4-7428-4cd7-994b-60607b20d7da\"],\"economic_validation\":false,\"availability_confirmed\":false}}}}]}"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"prefill": {
|
||||
"simulator": {
|
||||
"context_applicability_snapshot": "{\"version\":1,\"consumer_opportunity\":\"opportunity:400\",\"opportunity_choices\":[{\"opportunity\":{\"key\":\"opportunity:400\",\"title\":\"SYNTHETIC QA — Gurué\",\"version\":2,\"analysis\":{\"proactive\":{\"need\":\"SYNTHETIC QA necessidade por verificar.\",\"basis\":\"Fixture pública sintética; não é evidência de procura local.\",\"group\":\"ideas\",\"stage\":\"Apoio — correspondência real por confirmar\",\"state\":\"hypothesis\",\"notice\":\"A ausência de registo não comprova ausência de oferta. Proximidade não comprova contrato, participação, energia acessível, terra disponível ou benefício fiscal. Necessidade confirmada não comprova viabilidade comercial; hipótese de fornecimento não é encomenda.\",\"version\":1,\"chain_id\":null,\"evidence\":[{\"id\":\"1421bb80-78c0-40c9-9de0-f45e18c5a093\",\"scope\":\"Gurué — contexto piloto\",\"period\":\"Exercício2026 — cenário sintético\",\"source\":\"SYNTHETIC QA exemplar público fictício Gurué\",\"locator\":\"Fixture QA, linha1\",\"purpose\":\"local\",\"category\":\"infrastructure\",\"coverage\":\"Cobertura fictícia; informação real por confirmar\",\"statement\":\"SYNTHETIC QA: capacidade fictícia em Gurué; não é diagnóstico económico real.\",\"verified_on\":\"2026-10-27\"}],\"proposal\":\"SYNTHETIC QA solução em preparação.\",\"relations\":[],\"limitations\":\"Sem validação económica, contrato, terra ou energia garantidos.\",\"next_action\":\"Confirmar evidências reais antes de decidir.\",\"evidence_ids\":[\"1421bb80-78c0-40c9-9de0-f45e18c5a093\"],\"economic_validation\":false,\"availability_confirmed\":false}}}}]}"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import {normalBook,normalCurrent,saveNormalBook} from '../../resources/js/lib/irpc-normal.ts';
|
||||
import {irpcBook,newIrpcRow,saveIrpcBook,recordIrpc} from '../../resources/js/lib/irpc-withholdings.ts';
|
||||
import {annualBook,newAnnualBook,newAnnualPpc,saveAnnualBook,reuseAnnualAssessment,annualAssessment,annualWithholdingOptions,reuseAnnualWithholding,calculateAnnual,recordAnnual,annualCurrent,annualReportRows,annualHtml} from '../../resources/js/lib/irpc-annual-settlement.ts';
|
||||
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
|
||||
const read=n=>JSON.parse(fs.readFileSync(new URL('./fixtures/'+n,import.meta.url),'utf8'));
|
||||
const val=v=>v?Number(v.numerator)/Number(v.denominator):null;
|
||||
const now='2026-10-26T18:00:00+02:00';
|
||||
const original=()=>read('irpc-assessment-preserved.json');
|
||||
function acceptedL7(expense=false){const d=read('irpc-l7-preserved.json')[expense?'expense':'acceleration'];if(!expense){const f=read('irpc-l7-continuation-preserved.json');d.business_plan_snapshot=f.plan;d.modelo_a_snapshot=saveNormalBook(d,f.book);}return d;}
|
||||
function setup(rf='300',ppc='500'){
|
||||
const d=original(),l5=irpcBook(d);
|
||||
if(rf!==null){
|
||||
const row={...newIrpcRow('L8-received'),direction:'received',origin:'effective',counterparty:'QA pagador A',documentRef:'QA rendimento próprio 2026',base:String(Number(rf)*5),currency:'MZN',kind:'royalty',recipientIrpc:'yes',payerIrpc:'yes',residence:'resident',mozambique:'yes',qualificationRef:'QA royalties próprios incluídos no resultado anual',specialRelief:'none',eventsComplete:'yes',events:[{kind:'payment',date:'2026-10-02',reference:'QA rendimento e primeiro evento 2026'}],settlement:'complete',settlementRef:'QA retenção efectivamente sofrida e reconciliada',allocations:[{paymentId:'RF-L8',amount:rf}],ordinary:{nonDigital:'yes',capitalType:'',rentOwnPropertyManagement:'',specialFacts:'no',capitalSeatAndManagement:'',reference:'QA royalties não digitais de residente'}};
|
||||
l5.rows.push(row);l5.payments.push({id:'RF-L8',kind:'withholding_proof',reference:'QA-RF-2026-1',date:'2026-10-02',amount:rf,currency:'MZN'});
|
||||
d.modelo_a_snapshot=saveIrpcBook(d,recordIrpc(d,l5,now));
|
||||
}
|
||||
let b=reuseAnnualAssessment(d,newAnnualBook());b.reference='QA entidade123456789,exercício2026,declaração integral dos abatimentos';b.assessmentReference='QA colecta válida já demonstrada1408';
|
||||
b.withholdings={state:rf===null?'absent':'known',reference:'QA inventário completo das retenções efectivamente sofridas por este sujeito no exercício',rows:[]};
|
||||
b.ppc={state:ppc===null?'absent':'known',reference:'QA inventário completo dos PPC efectuados no exercício',rows:[]};
|
||||
b.pec={state:'absent',amount:'',reference:'QA ausência de PEC'};b.credits={state:'known',amount:'0',reference:'QA créditos com regras próprias conhecidos zero'};
|
||||
if(rf!==null){b=reuseAnnualWithholding(d,b,'L8-received','RF-L8','claim-rf');Object.assign(b.withholdings.rows[0],{incomeIncluded:'yes',reference:'QA próprio beneficiário NUIT123456789;rendimento incluído na base anual2026'});}
|
||||
if(ppc!==null)b.ppc.rows.push({...newAnnualPpc('claim-ppc'),document:'QA-PPC-2026-1',issuer:'QA AT',date:'2026-06-30',subjectNuit:b.subjectNuit,year:b.year,proofAmount:ppc,amount:ppc,effective:'yes',reference:'QA recibo de PPC efectivo e afectação ao sujeito/exercício'});
|
||||
return{d,b};
|
||||
}
|
||||
const model=(d,b)=>calculateAnnual(d,b);
|
||||
const pending=(d,b)=>{const m=model(d,b);assert.equal(m.status,'indeterminate',m.pending.join(' | '));assert.equal(m.arithmeticBalance,null);assert.equal(m.payable,null);assert.equal(m.recoverable,null);return m;};
|
||||
|
||||
test('optional L8 leaves accepted assessment, other books and report rows untouched',()=>{
|
||||
const d=original(),before=JSON.stringify(d),b=normalBook(d);assert.equal(normalCurrent(d,b),true);assert.equal(val(annualAssessment(d).colecta),1408);assert.equal(annualBook(d),undefined);assert.deepEqual(annualReportRows(d),[]);assert.equal(JSON.stringify(d),before);
|
||||
const old=acceptedL7();assert.deepEqual(annualReportRows(old),[]);assert.equal(normalBook(old).result.model.version,'IRPC-normal-adjustments/13');
|
||||
});
|
||||
test('1408 minus actual received300 and provenPPC500 yields608 payable without consuming official balances',()=>{
|
||||
const{d,b}=setup(),before=d.modelo_a_snapshot,m=model(d,b);assert.deepEqual(m.pending,[]);assert.equal(m.status,'payable');assert.equal(val(m.knownWithholdings),300);assert.equal(val(m.knownPpc),500);assert.equal(val(m.payable),608);assert.equal(val(m.recoverable),0);assert.equal(m.officialBalancesConsumed,false);assert.equal(m.submitted,false);assert.equal(d.modelo_a_snapshot,before);
|
||||
});
|
||||
test('1408 minus1000 and600 yields192 recoverable;408 and1000 balances exactly',()=>{
|
||||
for(const[rf,ppc,status,balance]of[['1000','600','recoverable',-192],['408','1000','balanced',0]]){const{d,b}=setup(rf,ppc),m=model(d,b);assert.deepEqual(m.pending,[]);assert.equal(m.status,status);assert.equal(val(m.arithmeticBalance),balance);assert.equal(val(m.recoverable),balance<0?-balance:0);}
|
||||
});
|
||||
test('declared absence yields1408;known zero has its own proof and missing never becomes zero',()=>{
|
||||
const{d,b}=setup(null,null);assert.equal(val(model(d,b).payable),1408);b.credits.state='';assert.match(pending(d,b).pending.join(' '),/Créditos/);b.credits={state:'absent',amount:'',reference:'QA ausência'};b.ppc.state='';assert.match(pending(d,b).pending.join(' '),/PPC/);
|
||||
const zero=setup('0','0');assert.equal(val(model(zero.d,zero.b).payable),1408);assert.equal(model(zero.d,zero.b).input.withholdings.state,'known');
|
||||
});
|
||||
test('effective received L5 proof is required, not a projection,remittance or definitive withholding',()=>{
|
||||
for(const patch of[{origin:'projected'},{direction:'paid'},{residence:'nonresident',permanentEstablishment:'no'}]){const{d,b}=setup(),l5=irpcBook(d);Object.assign(l5.rows.find(r=>r.id==='L8-received'),patch);d.modelo_a_snapshot=saveIrpcBook(d,recordIrpc(d,l5,now));const option=annualWithholdingOptions(d).find(o=>o.rowId==='L8-received');assert.equal(option.ready,false);pending(d,b);}
|
||||
const{d,b}=setup(),l5=irpcBook(d);l5.payments.find(p=>p.id==='RF-L8').kind='remittance';d.modelo_a_snapshot=saveIrpcBook(d,recordIrpc(d,l5,now));pending(d,b);
|
||||
});
|
||||
test('beneficiary,income inclusion,proof date,entity,exercise and actualPPC are mandatory',()=>{
|
||||
for(const change of[b=>b.withholdings.rows[0].incomeIncluded='',b=>b.withholdings.rows[0].reference='',b=>b.withholdings.rows[0].subjectNuit='999999999',b=>b.year='2025',b=>b.ppc.rows[0].subjectNuit='999999999',b=>b.ppc.rows[0].year='2025',b=>b.ppc.rows[0].currency='USD',b=>b.ppc.rows[0].date='2026-02-30',b=>b.ppc.rows[0].date='2027-01-01',b=>b.ppc.rows[0].effective='no',b=>b.ppc.rows[0].reference='',b=>b.reference='']){const{d,b}=setup();change(b);pending(d,b);}
|
||||
});
|
||||
test('selected current source and reusing collection never overwrite deliberate entity/year edits',()=>{
|
||||
const{d,b}=setup();b.subjectNuit='999999999';b.year='2025';const next=reuseAnnualAssessment(d,b);assert.equal(next.subjectNuit,'999999999');assert.equal(next.year,'2025');pending(d,next);
|
||||
const other=setup();other.b.assessmentKey='old-source';pending(other.d,other.b);
|
||||
});
|
||||
test('absence contradiction and incomplete group inventories are indeterminate,not assumed totals',()=>{
|
||||
for(const change of[b=>{b.withholdings={state:'absent',reference:'QA ausência contraditória',rows:[]};},b=>b.ppc.rows=[],b=>b.ppc.state='absent',b=>b.withholdings.reference='']){const{d,b}=setup();change(b);pending(d,b);}
|
||||
});
|
||||
test('duplicate pair,duplicatePPC,overclaim and cross-kind physical proof cannot be deducted twice',()=>{
|
||||
for(const change of[b=>b.withholdings.rows.push({...b.withholdings.rows[0],id:'duplicate'}),b=>b.ppc.rows.push({...b.ppc.rows[0],id:'duplicate'}),b=>b.withholdings.rows[0].amount='301',b=>b.ppc.rows[0].amount='501',b=>Object.assign(b.ppc.rows[0],{document:' QA-RF-2026-1 ',issuer:'QA pagador A',date:'2026-10-02',amount:'100',proofAmount:'300'})]){const{d,b}=setup();change(b);pending(d,b);}
|
||||
const{d,b}=setup();assert.throws(()=>reuseAnnualWithholding(d,b,'L8-received','RF-L8','again'),/já seleccionada/);
|
||||
});
|
||||
test('partial proof allocations allowed only within its available amount across context maps',()=>{
|
||||
const{d,b}=setup(null,'500');b.ppc.rows[0].amount='300';const other=structuredClone(b);other.ppc.rows[0].id='other';other.ppc.rows[0].amount='200';const s=JSON.parse(d.modelo_a_snapshot);s.irpcAnnual={'opportunity:other':other};d.modelo_a_snapshot=JSON.stringify(s);assert.equal(val(model(d,b).payable),1108);other.ppc.rows[0].amount='201';d.modelo_a_snapshot=JSON.stringify(s);pending(d,b);
|
||||
other.ppc.rows[0].amount='100';other.ppc.rows[0].subjectNuit='999999999';d.modelo_a_snapshot=JSON.stringify(s);pending(d,b);
|
||||
other.ppc.rows[0].subjectNuit=b.subjectNuit;other.ppc.rows[0].year='2025';d.modelo_a_snapshot=JSON.stringify(s);pending(d,b);
|
||||
});
|
||||
test('positive PEC or specialcredit stays separated with null final balances,explicitzero permitted',()=>{
|
||||
for(const key of['pec','credits']){const{d,b}=setup();b[key]={state:'known',amount:'10',reference:'QA saldo positivo exige regra própria'};const m=pending(d,b);assert.match(m.pending.join(' '),/fora deste recorte/);assert.equal(val(m.knownPpc),500);b[key].amount='0';assert.equal(model(d,b).status,'payable');b[key]={state:'absent',amount:'0',reference:'QA ausência contradiz montante'};pending(d,b);}
|
||||
});
|
||||
test('changing receipt date cannot evade identity checks;copied L5 allocation cannot consume larger proof twice',()=>{
|
||||
const p=setup();p.b.ppc.rows.push({...p.b.ppc.rows[0],id:'other-date',date:'2026-07-01',amount:'100'});pending(p.d,p.b);
|
||||
const{d,b}=setup();const l5=irpcBook(d);l5.payments.find(p=>p.id==='RF-L8').amount='1000';d.modelo_a_snapshot=saveIrpcBook(d,recordIrpc(d,l5,now));b.withholdings.rows=[];const fresh=reuseAnnualWithholding(d,b,'L8-received','RF-L8','rf');Object.assign(fresh.withholdings.rows[0],{amount:'200',incomeIncluded:'yes',reference:'QA próprio beneficiário e rendimento incluído'});
|
||||
const other=structuredClone(fresh);other.withholdings.rows[0].amount='101';other.ppc.rows=[];other.ppc.state='absent';const s=JSON.parse(d.modelo_a_snapshot);s.irpcAnnual={'opportunity:other':other};s.irpcWithholdings['opportunity:other']=structuredClone(l5);d.modelo_a_snapshot=JSON.stringify(s);d.modelo_a_snapshot=saveIrpcBook(d,recordIrpc(d,irpcBook(d),now));fresh.withholdings.rows[0].sourceKey=annualWithholdingOptions(d).find(o=>o.rowId==='L8-received').key;other.withholdings.rows[0].sourceKey=fresh.withholdings.rows[0].sourceKey;const current=JSON.parse(d.modelo_a_snapshot);current.irpcAnnual['opportunity:other']=other;d.modelo_a_snapshot=JSON.stringify(current);assert.match(pending(d,fresh).pending.join(' '),/Mesma afectação L5/);
|
||||
other.withholdings.rows[0].amount='100';d.modelo_a_snapshot=JSON.stringify(current);assert.equal(model(d,fresh).status,'payable');
|
||||
});
|
||||
test('annual accepted L7 accelerated assessment is reused once rather than summed with L6',()=>{
|
||||
const d=read('irpc-l7-preserved.json').acceleration,b=reuseAnnualAssessment(d,newAnnualBook());b.reference='QA entidade/exercício';b.assessmentReference='QA colecta L7';for(const key of['withholdings','ppc','pec','credits']){b[key].state='absent';b[key].reference='QA ausência declarada';}
|
||||
const m=model(d,b);assert.deepEqual(m.pending,[]);assert.equal(m.assessment.kind,'special');assert.equal(val(m.payable),1996.8);assert.notEqual(val(m.payable),val(normalBook(d).result.model.colecta)+1996.8);
|
||||
});
|
||||
test('100 minimum is applied symmetrically;99.99 kept exact without invented rounding or carry',()=>{
|
||||
for(const[ppc,status,balance]of[['1308.01','below_minimum',99.99],['1308','payable',100],['1507.99','below_minimum',-99.99],['1508','recoverable',-100]]){const{d,b}=setup(null,ppc),m=model(d,b);assert.equal(m.status,status);assert.equal(val(m.arithmeticBalance),balance);if(status==='below_minimum'){assert.deepEqual(m.belowMinimum,{numerator:'9999',denominator:'100'});assert.equal(val(m.payable),0);assert.equal(val(m.recoverable),0);}}
|
||||
const{d,b}=setup();b.ppc.rows[0].amount='0.001';pending(d,b);
|
||||
});
|
||||
test('existing L7 source cannot be bypassed by choosing L6 and positiveautonomous/shortperiod remain scoped',()=>{
|
||||
for(const expense of[false,true]){const d=acceptedL7(expense);let b=reuseAnnualAssessment(d,newAnnualBook());b.reference='QA fecho';b.assessmentReference='QA colecta';for(const key of['withholdings','ppc','pec','credits']){b[key].state='absent';b[key].reference='QA sem movimentos';}assert.equal(b.assessment,'special');let m=pending(d,b);if(!expense)assert.match(m.pending.join(' '),/períodos especiais/);if(expense)assert.match(m.pending.join(' '),/Tributação autónoma/);b.assessment='normal';assert.match(pending(d,b).pending.join(' '),/não corrente/);}
|
||||
});
|
||||
test('record/recover/recalculate appends history unchanged,preserves all old books/plan,no double deduction',()=>{
|
||||
const{d,b}=setup(),before=JSON.parse(d.modelo_a_snapshot),plan=d.business_plan_snapshot;d.modelo_a_snapshot=saveAnnualBook(d,recordAnnual(d,b,now));const once=annualBook(d),old=structuredClone(once.result);assert.equal(annualCurrent(d,once),true);d.modelo_a_snapshot=saveAnnualBook(d,recordAnnual(d,once,now));const back=annualBook(JSON.parse(JSON.stringify(d)));assert.deepEqual(back.history,[old]);assert.equal(val(back.result.model.payable),608);assert.equal(d.business_plan_snapshot,plan);const snapshot=JSON.parse(d.modelo_a_snapshot);delete snapshot.irpcAnnual;assert.deepEqual(snapshot,before);
|
||||
b.ppc.rows[0].amount='400';assert.equal(annualCurrent(d,b),false);
|
||||
});
|
||||
test('changed L5 or assessment invalidates current L8 while retaining historical report and references',()=>{
|
||||
const{d,b}=setup();d.modelo_a_snapshot=saveAnnualBook(d,recordAnnual(d,b,now));const back=annualBook(d),old=structuredClone(back.result);back.reference='NEW reference';d.modelo_a_snapshot=saveAnnualBook(d,back);assert.equal(annualCurrent(d,back),false);assert.match(annualReportRows(d).flat().join(' '),/Histórico/);assert.doesNotMatch(annualReportRows(d).flat().join(' '),/NEW reference/);assert.throws(()=>annualHtml(d),/fontes actuais/);assert.deepEqual(back.result,old);
|
||||
const n=normalBook(d);n.base.identityReference+=' changed';d.modelo_a_snapshot=saveNormalBook(d,n);assert.equal(annualCurrent(d,back),false);pending(d,back);
|
||||
const changed=setup();changed.d.modelo_a_snapshot=saveAnnualBook(changed.d,recordAnnual(changed.d,changed.b,now));const saved=annualBook(changed.d),prior=structuredClone(saved.result);const l5=irpcBook(changed.d);l5.payments.find(p=>p.id==='RF-L8').reference+=' corrected';changed.d.modelo_a_snapshot=saveIrpcBook(changed.d,recordIrpc(changed.d,l5,now));assert.equal(annualCurrent(changed.d,saved),false);pending(changed.d,saved);assert.deepEqual(saved.result,prior);
|
||||
});
|
||||
test('malformed optionalbook never resets accepted books;report explicitly preserves missing states',()=>{
|
||||
const{d,b}=setup();b.credits.state='';d.modelo_a_snapshot=saveAnnualBook(d,recordAnnual(d,b,now));assert.match(annualHtml(d),/Indeterminado/);assert.match(annualHtml(d),/Informação em falta/);assert.match(JSON.stringify(createProjectDossierReport(d,{selectedSections:new Set(['finance'])})),/Saldo anual simulado/);
|
||||
const old=d.modelo_a_snapshot;b.ppc.rows.push({...b.ppc.rows[0]});assert.throws(()=>saveAnnualBook(d,b),/identificador repetido/);assert.equal(d.modelo_a_snapshot,old);
|
||||
});
|
||||
test('prepare only L8 delta cases for guarded API and report recovery',()=>{
|
||||
const cases={payable:setup(),recoverable:setup('1000','600'),balanced:setup('408','1000'),absent:setup(null,null),missing:setup(),duplicate:setup(),pec:setup()};cases.missing.b.ppc.rows[0].effective='';cases.duplicate.b.ppc.rows.push({...cases.duplicate.b.ppc.rows[0],id:'duplicate'});cases.pec.b.pec={state:'known',amount:'10',reference:'QA PEC separado'};
|
||||
fs.mkdirSync('outputs/irpc-l8-settlement',{recursive:true});for(const[name,{d,b}]of Object.entries(cases)){d.modelo_a_snapshot=saveAnnualBook(d,recordAnnual(d,b,now));fs.writeFileSync('outputs/irpc-l8-settlement/'+name+'.json',JSON.stringify(d));fs.writeFileSync('outputs/irpc-l8-settlement/'+name+'.html',annualHtml(d));}
|
||||
const{d}=setup();fs.writeFileSync('outputs/irpc-l8-settlement/initial.json',JSON.stringify(d));
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import test from 'node:test';import assert from 'node:assert/strict';import fs from 'node:fs';
|
||||
import {buildProjectDossierRows} from '../../resources/js/lib/project-dossier.ts';
|
||||
import {proactiveInvestmentRows} from '../../resources/js/lib/proactive-investment-report.ts';
|
||||
const source=(id,need)=>({key:'opportunity:'+id,title:'SYNTHETIC QA '+id,version:3,analysis:{proactive:{version:1,group:'ideas',state:'hypothesis',need,proposal:'Solução '+id,basis:'Fixture pública sintética',limitations:'Não comprova procura real.',next_action:'Confirmar dados reais.',evidence:[{statement:'QA facto '+id,source:'QA exemplar',locator:'Fixture linha1',period:'2026',scope:'Piloto',coverage:'Sintética',verified_on:'2026-10-27'}]}}});
|
||||
test('absent proactivity is a no-op for accepted dossiers',()=>{assert.deepEqual(proactiveInvestmentRows({}),[]);assert.deepEqual(proactiveInvestmentRows({context_applicability_snapshot:'{"version":1,"opportunity_choices":[]}'}),[]);assert.deepEqual(proactiveInvestmentRows({context_opportunity_snapshot:'unreadable-original-preserved'}),[]);});
|
||||
test('each idea retains origin,source,need,limits without summing or inventing economic values',()=>{const choices=[{opportunity:source(1,'A')},{opportunity:source(2,'B')}],d={context_applicability_snapshot:JSON.stringify({version:1,opportunity_choices:choices})},r=proactiveInvestmentRows(d);assert.equal(r.filter(x=>x[1]==='Origem da análise e ideia').length,2);assert.match(JSON.stringify(r),/opportunity:1/);assert.match(JSON.stringify(r),/opportunity:2/);assert.match(JSON.stringify(r),/Hipótese analítica/);assert.match(JSON.stringify(r),/não é zero/);assert.equal(d.context_applicability_snapshot,JSON.stringify({version:1,opportunity_choices:choices}));});
|
||||
test('consumer selection only reports its idea even when other source contexts are present',()=>{const choices=[{opportunity:source(1,'A')},{opportunity:source(2,'B')}],r=proactiveInvestmentRows({context_opportunity:'opportunity:2',context_applicability_snapshot:JSON.stringify({version:1,opportunity_choices:choices})});assert.doesNotMatch(JSON.stringify(r),/opportunity:1/);assert.match(JSON.stringify(r),/opportunity:2/);});
|
||||
test('explicit consumer snapshot is retained and repeat references do not duplicate report rows',()=>{const a=source(1,'A');let r=proactiveInvestmentRows({context_opportunity_snapshot:JSON.stringify({choice:{opportunity:a}})});assert.equal(r.filter(x=>x[1]==='Origem da análise e ideia').length,1);r=proactiveInvestmentRows({context_applicability_snapshot:JSON.stringify({version:1,opportunity_choices:[{opportunity:a},{opportunity:a}]})});assert.equal(r.filter(x=>x[1]==='Origem da análise e ideia').length,1);});
|
||||
test('portable API consumer snapshot produces an independently scoped report',()=>{const d=JSON.parse(fs.readFileSync(new URL('./fixtures/proactive-api-consumers.json',import.meta.url),'utf8'));const before=JSON.stringify(d);const perConsumer=d.consumer_contexts.map(c=>proactiveInvestmentRows(c.prefill.simulator));for(const rows of perConsumer)assert.equal(rows.filter(x=>x[1]==='Origem da análise e ideia').length,1);const r=perConsumer.flat();assert.equal(r.filter(x=>x[1]==='Origem da análise e ideia').length,2);assert.match(JSON.stringify(perConsumer[0]),/opportunity:399/);assert.doesNotMatch(JSON.stringify(perConsumer[0]),/opportunity:400/);assert.match(JSON.stringify(perConsumer[1]),/opportunity:400/);assert.doesNotMatch(JSON.stringify(perConsumer[1]),/opportunity:399/);assert.doesNotMatch(JSON.stringify(r),/PRIVATE-QA-/);assert.equal(JSON.stringify(d),before);});
|
||||
|
||||
test('resources,assumptions and selected relationships are retained in the existing dossier report',()=>{const a=source(7,'A');Object.assign(a.analysis.proactive,{resources:'QA recurso declarado',assumptions:'QA pressuposto explícito',conditions:'QA condição',relations:[{kind:'project',target_id:'QA-reference',label:'QA projecto existente',relationship:'hypothesis',basis:'QA fundamento público'}]});const draft={context_applicability_snapshot:JSON.stringify({version:1,opportunity_choices:[{opportunity:a}]})},rows=buildProjectDossierRows(draft);assert.match(JSON.stringify(rows),/QA pressuposto explícito/);assert.match(JSON.stringify(rows),/QA projecto existente/);assert.match(JSON.stringify(rows),/sem contrato, acesso ou participação presumidos/);});
|
||||
|
||||
test('existing facts hide unrelated need and idea rows without deleting previous preparation',()=>{const a=source(8,'Old need');a.analysis.proactive.group='exists';a.analysis.proactive.proposal='Old idea';const d={context_applicability_snapshot:JSON.stringify({version:1,opportunity_choices:[{opportunity:a}]})},before=d.context_applicability_snapshot,r=proactiveInvestmentRows(d);assert.equal(r.some(x=>x[1]==='Estado da necessidade'||x[1]==='Proposta de investimento'),false);assert.equal(d.context_applicability_snapshot,before);assert.match(JSON.stringify(r),/QA facto 8/);});
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
$root=dirname(__DIR__);
|
||||
$operation=$argv[1]??'';
|
||||
if(!in_array($operation,['routes','test'],true)||basename($root)!=='portal-investidor-irpc-l7-common-qa-20261026')throw new RuntimeException('Explicit isolated QA workspace and routes/test operation required.');
|
||||
foreach(['storage/framework/views','storage/framework/cache','storage/framework/sessions','bootstrap/cache','storage/logs','outputs/irpc-l8-settlement']as$dir)if(!is_dir($root.'/'.$dir))mkdir($root.'/'.$dir,0700,true);
|
||||
foreach(['APP_BASE_PATH'=>$root,'APP_ENV'=>'testing','APP_KEY'=>'base64:'.base64_encode(str_repeat('Q',32)),'DB_CONNECTION'=>'pgsql','DB_HOST'=>'127.0.0.1','DB_PORT'=>'55441','DB_DATABASE'=>'simulator_fiscal_delta_20261021_test','DB_USERNAME'=>'postgres','DB_PASSWORD'=>'','DB_URL'=>'','CACHE_STORE'=>'array','SESSION_DRIVER'=>'array','QUEUE_CONNECTION'=>'sync','MAIL_MAILER'=>'array'] as $k=>$v){putenv($k.'='.$v);$_ENV[$k]=$_SERVER[$k]=$v;}
|
||||
$loader=require $root.'/vendor/autoload.php';
|
||||
spl_autoload_register(function($class)use($root){foreach(['App\\'=>'app/','Tests\\'=>'tests/','Database\\Factories\\'=>'database/factories/']as$prefix=>$dir){if(str_starts_with($class,$prefix)){$file=$root.'/'.$dir.str_replace('\\','/',substr($class,strlen($prefix))).'.php';if(is_file($file)){require $file;return;}}}},true,true);
|
||||
$app=require $root.'/bootstrap/app.php';
|
||||
(new Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables)->bootstrap($app);
|
||||
(new Illuminate\Foundation\Bootstrap\LoadConfiguration)->bootstrap($app);
|
||||
$c=config('database.connections.pgsql');
|
||||
if($app->configurationIsCached()||$c['host']!=='127.0.0.1'||(int)$c['port']!==55441||$c['database']!=='simulator_fiscal_delta_20261021_test'||!empty($c['url']))throw new RuntimeException('QA guard');
|
||||
$pdo=new PDO('pgsql:host=127.0.0.1;port=55441;dbname='.$c['database'],$c['username'],$c['password']);
|
||||
if($pdo->query('select current_database()')->fetchColumn()!==$c['database'])throw new RuntimeException('QA identity');
|
||||
if($operation==='routes'){
|
||||
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
$status=Illuminate\Support\Facades\Artisan::call('wayfinder:generate',['--with-form'=>true]);
|
||||
echo Illuminate\Support\Facades\Artisan::output();exit($status);
|
||||
}
|
||||
$argv=['phpunit','-c','phpunit.investmoz.xml','tests/Feature/IrpcAnnualSettlementDraftTest.php'];$argc=count($argv);$_SERVER['argv']=$argv;$_SERVER['argc']=$argc;require $root.'/vendor/phpunit/phpunit/phpunit';
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
$root=dirname(__DIR__);
|
||||
$operation=$argv[1]??'';
|
||||
if(!in_array($operation,['routes','test'],true)||basename($root)!=='portal-investidor-proactive-qa-20261027')throw new RuntimeException('Explicit isolated QA workspace and routes/test operation required.');
|
||||
foreach(['storage/framework/views','storage/framework/cache','storage/framework/sessions','bootstrap/cache','storage/logs','outputs/proactive-investment-20261027']as$dir)if(!is_dir($root.'/'.$dir))mkdir($root.'/'.$dir,0700,true);
|
||||
foreach(['APP_BASE_PATH'=>$root,'APP_ENV'=>'testing','APP_KEY'=>'base64:'.base64_encode(str_repeat('Q',32)),'DB_CONNECTION'=>'pgsql','DB_HOST'=>'127.0.0.1','DB_PORT'=>'55441','DB_DATABASE'=>'proactive_investment_20261027_test','DB_USERNAME'=>'postgres','DB_PASSWORD'=>'','DB_URL'=>'','CACHE_STORE'=>'array','SESSION_DRIVER'=>'array','QUEUE_CONNECTION'=>'sync','MAIL_MAILER'=>'array'] as $k=>$v){putenv($k.'='.$v);$_ENV[$k]=$_SERVER[$k]=$v;}
|
||||
$loader=require $root.'/vendor/autoload.php';
|
||||
spl_autoload_register(function($class)use($root){foreach(['App\\'=>'app/','Tests\\'=>'tests/','Database\\Factories\\'=>'database/factories/']as$prefix=>$dir){if(str_starts_with($class,$prefix)){$file=$root.'/'.$dir.str_replace('\\','/',substr($class,strlen($prefix))).'.php';if(is_file($file)){require $file;return;}}}},true,true);
|
||||
$app=require $root.'/bootstrap/app.php';
|
||||
(new Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables)->bootstrap($app);
|
||||
(new Illuminate\Foundation\Bootstrap\LoadConfiguration)->bootstrap($app);
|
||||
$c=config('database.connections.pgsql');
|
||||
if($app->configurationIsCached()||$c['host']!=='127.0.0.1'||(int)$c['port']!==55441||$c['database']!=='proactive_investment_20261027_test'||!empty($c['url']))throw new RuntimeException('QA guard');
|
||||
$pdo=new PDO('pgsql:host=127.0.0.1;port=55441;dbname='.$c['database'],$c['username'],$c['password']);
|
||||
if($pdo->query('select current_database()')->fetchColumn()!==$c['database'])throw new RuntimeException('QA identity');
|
||||
if($operation==='routes'){
|
||||
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
$status=Illuminate\Support\Facades\Artisan::call('wayfinder:generate',['--with-form'=>true]);
|
||||
echo Illuminate\Support\Facades\Artisan::output();exit($status);
|
||||
}
|
||||
$argv=['phpunit','-c','phpunit.investmoz.xml','tests/Feature/ProactiveInvestmentTest.php'];if(getenv('PROACTIVE_QA_FILTER')){$argv[]='--filter';$argv[]=getenv('PROACTIVE_QA_FILTER');}$argc=count($argv);$_SERVER['argv']=$argv;$_SERVER['argc']=$argc;require $root.'/vendor/phpunit/phpunit/phpunit';
|
||||
Reference in New Issue
Block a user